2

I simply declare a key-frames:

@keyframes spinner {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

But in CSS file that Webpack made for me I see:

animation: 1s infinite alternate :local(spinner)

What is :local???

I search and found some solutions but why it appear in css?

some of solution was, where I use the declared animation I must use :global:

:global .i-spinner4 {
    animation: 1s infinite alternate spinner;
  }

I used that solution I found, it became right but in webpack -p css version it dissapear completely, it means PostCSS parser in prod version ignore it completely...

How I can fix this???

this is my dev version webpack config:

const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin"),
    CleanWebpackPlugin = require('clean-webpack-plugin');

const DistDir = path.resolve(__dirname, './dist'),
    SrcDir = path.resolve(__dirname, './src');

module.exports = {
    resolve: {
        alias: {
            AppRoot: path.resolve(__dirname, './src/app'),
            PcssRoot: path.resolve(__dirname, './src/pcss')
        }
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: ['src/app/redux', 'node_modules'],
                include: SrcDir,
                loader: 'babel-loader'
            },
            {
                test: /\.pcss$/,
                exclude: /node_modules/,
                include: SrcDir,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1,
                            modules: true,
                                localIdentName: '[local]',
                                sourceMap: true
                            }
                        },
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'postcss',
                                sourceMap: true,
                                syntax: 'postcss-scss',
                                map: true,
                                plugins: () => ([
                                    require('postcss-partial-import')({
                                        prefix: "_",
                                        extension: ".pcss",
                                        glob: false,
                                        path: ['./src/pcss']
                                    }),
                                    require('postcss-nested-ancestors'),
                                    require('postcss-apply'),
                                    require('postcss-custom-properties'),
                                    require('postcss-nested'),
                                    require('postcss-cssnext')({
                                        features: {
                                            nesting: false
                                        },
                                        warnForDuplicates: false
                                    }),
                                    require('postcss-extend'),
                                    require('css-mqpacker')({
                                        sort: true
                                    }),
                                    require('autoprefixer')({
                                        browsers: [`last 15 versions`]
                                    })
                                ])
                            }
                        }
                    ]
                })
            },
            {
                test: /\.(woff|woff2|eot|ttf|svg)$/,
                exclude: /node_modules/,
                loader: 'file-loader',
                options: {
                    limit: 1024,
                    name: '[name].[ext]',
                    publicPath: '../font/',
                    outputPath: 'asset/font/'
                }
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
            filename: `asset/css/style.css`
        }),
        new CleanWebpackPlugin(`${DistDir}/asset`)
    ],
    entry: {
        "sd": `${SrcDir}/app/index.js`
    },
    externals: {
      config: JSON.stringify(require(SrcDir + '/config/config.dev.json'))
    },
    output: {
        path: DistDir,
        filename: "asset/js/[name].bundle.js"
    },
    devServer: {inline: true},
    devtool: 'source-map'
};

And this my prod version webpack:

const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin"),
    CleanWebpackPlugin = require('clean-webpack-plugin');

const DistDir = path.resolve(__dirname, './dist'),
    SrcDir = path.resolve(__dirname, './src');

let q = [],
    cache = {};

function randomNaming(length,limit) {
    let result = '',
        chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
        fchars = 'abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';

    do {
        if (q.length >= (52 * Math.pow(64, limit - 1)) && limit >= length) {
            return 'OutOfPossibility';
        } else if (q.length >= (52 * Math.pow(64, limit - 1)) && limit < length) {
            ++limit;
        }
        result = '';
        result += fchars[Math.floor(Math.random() * fchars.length)];
        for (let i = limit - 1; i > 0; --i) {
            result += chars[Math.floor(Math.random() * chars.length)];
        }
    } while (q.includes(result));
    q.push(result);
    return result;
}

module.exports = {
    resolve: {
        alias: {
            AppRoot: path.resolve(__dirname, './src/app'),
            PcssRoot: path.resolve(__dirname, './src/pcss')
        }
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                include: SrcDir,
                loader: 'babel-loader'
            },
            {
                test: /\.pcss$/,
                exclude: /node_modules/,
                include: SrcDir,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1,
                                modules: true,
                                getLocalIdent: (loaderContext, localIdentName, localName, options) => {
                                    var randName = randomNaming(3,2);
                                    if (localName.match(/^i-/i)) {
                                        randName = `i-${randName}`;
                                    } else if (localName.match(/^i_/i)) {
                                        randName = `i_`;
                                    } else {
                                        randName = `${randName}`;
                                    }
                                    if (typeof cache[localName] == 'undefined') {
                                        cache[localName] = randName;
                                        return cache[localName];
                                    } else {
                                        return cache[localName];
                                    }
                                }
                            }
                        },
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'postcss',
                                syntax: 'postcss-scss',
                                plugins: () => ([
                                    require('postcss-partial-import')({
                                        prefix: "_",
                                        extension: ".pcss",
                                        glob: false,
                                        path: ['./src/pcss']
                                    }),
                                    require('postcss-nested-ancestors'),
                                    require('postcss-apply'),
                                    require('postcss-custom-properties'),
                                    require('postcss-nested'),
                                    require('postcss-cssnext')({
                                        features: {
                                            nesting: false
                                        },
                                        warnForDuplicates: false
                                    }),
                                    require('postcss-extend'),
                                    require('css-mqpacker')({
                                        sort: true
                                    }),
                                    require('autoprefixer')({
                                        browsers: [`last 15 versions`]
                                    })/*,
                                    require('postcss-csso')({
                                        comments: false
                                    })*/
                                ])
                            }
                        }
                    ]
                })
            },
            {
                test: /\.(woff|woff2|eot|ttf|svg)$/,
                exclude: /node_modules/,
                loader: 'file-loader',
                options: {
                    limit: 1024,
                    name: '[hash:base64:3].[ext]',
                    publicPath: '../font/',
                    outputPath: 'asset/font/'
                }
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
            filename: `asset/css/style.css`
        }),
        new CleanWebpackPlugin(`${DistDir}/asset`)
    ],
    entry: {
        "sd": `${SrcDir}/app/index.js`
    },
    externals: {
        config: JSON.stringify(require(SrcDir + '/config/config.prod.json'))
    },
    output: {
        path: DistDir,
        filename: "asset/js/[name].bundle.js"
    },
    devServer: {inline: true},
};

3 Answers 3

4

Use the name of the animation first ...

I was able to get rid of the failed build by simply using the name of the animation first as shown below

animation: spinner 1s infinite alternate

instead of => animation: 1s spinner infinite alternate


Another workaround is to not use the animation shorthand property. It causes the name of the animation to be localised, e.g:

.fadein {
  animation-duration: 300ms
  animation-name: fadein
  animation-fill-mode: forwards
}

@keyframes fadein {
  from {
    opacity: 0
  }
}

Source

Sign up to request clarification or add additional context in comments.

Comments

1

This issue was made when I declare a keyframes without any hint to css-loader for CSS Modules, I must write like below:

@keyframes :local(spinner) {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

Every keyframes must declare with :local when Modules are true in css-loader, then easily write your class with any property and its animation property. like below:

.my-class {
    animation: spinner 1s infinite alternate;
}

Comments

0

I recently experienced this problem when using version 2.0.0 of css-loader.

It seemed to be a bug caused by one of their dependencies, as related in this issue: https://github.com/webpack-contrib/css-loader/issues/872

The problem was fixed in version 2.0.2, so just upgrading to 2.0.2 solved it for me.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.