【问题标题】:Using css modules with Extract Text Plugin使用带有提取文本插件的 css 模块
【发布时间】:2017-12-13 08:51:45
【问题描述】:

使用带有 extract-text-webpack-plugin 的 css-loader 中的 css modules 选项,Webpack 2 构建在生产模式下无法正常工作。

正确生成的类是在 html 元素上创建的,这意味着 css-loader 正在按预期工作,但是从 extract-text-webpack-plugin 提取的 css 文件缺少 css 标识符。

我正在使用一种方法来同时实现全局 css 和 css 模块,如下所述:https://github.com/css-modules/css-modules/pull/65 在这里:https://github.com/kitze/custom-react-scripts/issues/29

我对以 .css 结尾的文件和以 .cssm.css 结尾的文件使用不同的加载器测试,表明它们应该使用模块加载。

配置相关部分:

const extractTextPlugin = new ExtractTextPlugin({filename: '[name].[id].[contenthash].css', allChunks: true});

return {
    module: {
        rules: [
            {
                test: /\.cssm.(css|less)$/,
                loader: extractTextPlugin.extract({
                    fallbackLoader: 'style-loader',
                    loader: [
                        {
                            loader: 'css-loader',
                            query: {
                                importLoaders: 1,
                                modules: true,
                                localIdentName: '[name]_[local]_[hash:base64:5]'
                            }
                        },
                        {
                            loader: 'postcss-loader',
                            query: {
                                ident: 'postcss',
                                plugins: function() {
                                    return [
                                            require('autoprefixer')
                                    ];
                                }
                            }
                        },
                        {
                            loader: 'less-loader'
                        }
                    ]
                })
            },
            {
                test: /\.(css|less)$/,
                include: paths,
                loader: extractTextPlugin.extract({
                    fallbackLoader: 'style-loader',
                    loader: [
                        {
                            loader: 'css-loader',
                            query: {
                                importLoaders: 1
                            }
                        },
                        {
                            loader: 'postcss-loader',
                            query: {
                                ident: 'postcss',
                                plugins: function() {
                                    return [
                                            require('autoprefixer')
                                    ];
                                }
                            }
                        },
                        {
                            loader: 'less-loader'
                        }
                    ]
                })
            }
        ]
    },
    plugins: [
        extractTextPlugin
    ]
};

我已经尝试过建议的解决方案,例如使用 webpack 1 编写加载器的风格,但这没有帮助。

我正在使用 webpack 版本:2.6.1 和 extract-text-webpack-plugin: 2.1.2.

我也尝试了其他版本,但似乎也没有帮助。

我的全局 css 文件工作正常,只有导入的 .cssm.css 文件在与 extract-text-webpack-plugin 一起使用时被忽略。

如何解决 css 模块文件无法与其他全局 css 正确提取的问题?

【问题讨论】:

  • 如果我能再次投票给你,我会的。感谢您跟进您的回答。

标签: reactjs webpack-2 css-loader extract-text-plugin extracttextwebpackplugin


【解决方案1】:

显然我的设置很好。问题是我没有在“入口”webpack 配置中包含我所有的样式(css/less)文件。配置通过了构建阶段,但没有处理我在尝试将 css 模块与常规全局 css 一起使用时添加的新 .cssm.less 文件。

现在一切正常!为了将来参考,我将包括我的更新配置,以使用带有全局 css 的 css 模块(用于生产和开发)。显然,在较新版本的 webpack 和 extractTextPlugin 中,确切的语法(“use”与“loader”、“options”与“query”等)不再重要,而且可以双向使用。

对于生产,我在“localIdentName”属性中的所有 css 模块类名上添加前缀 cssm,以便以后可以使用 PurifyCSSPlugin 并将每个包含 cssm 的类列入白名单:

exports.setupSeparateStyles = function(paths, cssModulesPaths) {
    const extractTextPlugin = new ExtractTextPlugin({
            filename: '[name].[contenthash].css', 
            allChunks: true
        });

    return {
        module: {
            rules: [
                {
                    test: /\.(css|less)$/,
                    include: paths,
                    exclude: /\.cssm\.(css|less)$/,
                    use: extractTextPlugin.extract({
                        fallback: 'style-loader',
                        use: [
                            {
                                loader: 'css-loader',
                                options: {
                                    importLoaders: 1
                                }
                            },
                            'postcss-loader',
                            'less-loader'
                        ]
                    })
                },
                {
                    test: /\.(css|less)$/,
                    include: cssModulesPaths,
                    use: extractTextPlugin.extract({
                        fallback: 'style-loader',
                        use: [
                            {
                                loader: 'css-loader',
                                options: {
                                    importLoaders: 1,
                                    modules: true,
                                    localIdentName: 'cssm-[name]_[local]_[hash:base64:5]',
                                }
                            },
                            'postcss-loader',
                            'less-loader'
                        ]
                    })
                }
            ]
        },
        plugins: [
            new webpack.LoaderOptionsPlugin({
                options: {
                    postcss: [
                        require('autoprefixer')
                    ]
                }
            }),
            extractTextPlugin
        ]
    };
};

对于开发来说,它要简单得多:

exports.setupInlineStyles = function (paths, cssModulesPaths) {
    return {
        module: {
            rules: [
                {
                    test: /\.(css|less)$/,
                    include: paths,
                    exclude: /\.cssm\.(css|less)$/,
                    use: [
                        'style-loader',
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1
                            }
                        },
                        'postcss-loader',
                        'less-loader'
                    ]
                },
                {
                    test: /\.(css|less)$/,
                    include: cssModulesPaths,
                    use: [
                        'style-loader',
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1,
                                modules: true,
                                localIdentName: '[name]_[local]_[hash:base64:5]'
                            }
                        },
                        'postcss-loader',
                        'less-loader'
                    ]
                }
            ]
        },
        plugins: [
            new webpack.LoaderOptionsPlugin({
                options: {
                    postcss: [
                        require('autoprefixer')
                    ]
                }
            })
        ]
    };
};

【讨论】:

  • 为什么有人使用localIdentName: '[name]_[local]_[hash:base64:5]',为什么没有人不使用小于5的哈希数,我的意思是localIdentName: '[name]_[local]_[hash:base64:3]',当我使用少于5时,一些哈希类具有相同的名称并且发生这种情况让所有的 CSS 样式都变坏了。
  • @AmerllicA:处理“localIdentName”参数时,从 webpack/loader-utils 库调用函数 interpolateName。 interpolateName 函数参数可以在这里找到:[link]github.com/webpack/loader-utils.
  • @AmerllicA:解决您的问题:根据选定的“digestType”(base64)生成完整的哈希数。然后,如果您指定哈希“长度”(在 css-loader decommentation 中建议为 5 - link 或在您的情况下为 3),则会返回具有指定长度的原始哈希数的子字符串。因为这个数字被削减了,如果你只使用 3 个字符,那么生成的哈希很可能不是唯一的哈希码,从而导致 css 问题。
  • 我创建了一种使用RandomName 的新方法,而不是散列,随机名称,它非常棒,我可以制作许多不同的名称。阅读这个问题,请投票,谢谢。 stackoverflow.com/questions/47580113
猜你喜欢
  • 1970-01-01
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 2018-04-07
  • 2018-08-11
  • 2019-03-09
相关资源
最近更新 更多