【问题标题】:Webpack - scss/css modules styles not being applied in prodWebpack - scss/css 模块样式未在产品中应用
【发布时间】:2020-03-27 15:16:21
【问题描述】:

我正在使用 scss 模块,所以我在我的 react 组件中使用了 styleName,并且一切都在 dev 中运行。 prod 中的元素看起来像 <div class="row" stylename="table"></div>,但没有对 table 应用任何样式。

webpack 配置被分成多个文件(webpack.profile.jswebpack.base.jswebpack.dev.jswebpack.prod.js

旁注:我还注意到某些 jenkins 作业无法处理 @ 变量,不确定它是否与 webpack/sass-loader 有关。

webpack.profile.js

const path = require('path')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CompressionPlugin = require('compression-webpack-plugin')
const VisualizerPlugin = require('webpack-visualizer-plugin')

module.exports = require('./webpack.base')({
    mode: 'production',
    devServer: {
        port: 3000,
        contentBase: path.join(process.cwd(), 'dist/')
    },
    optimization: {
        minimizer: [
            new UglifyJsPlugin({
                cache: true,
                parallel: true
            }),
            new OptimizeCSSAssetsPlugin()
        ]
    },
    module: {
        rules: [
            {
                test: /\.(sc|sa|c)ss$/,
                use: [
                    { loader: MiniCssExtractPlugin.loader },
                        {
                        loader: "css-loader",
                        options: {
                                modules: true,
                                sourceMap: true,
                                localIdentName: "[name]_[local]_[hash:base64:5]"
                        }
                        }
                ]
            }
        ]
    },
    plugins: [
        new CompressionPlugin({
            test: /\.(js|css|html)$/
        }),
        new VisualizerPlugin({
            filename: '../stats/bundleStats.html'
        }),
        new MiniCssExtractPlugin({
            filename: '[name].[hash].css',
            chunkFilename: '[id].[hash].css'
        })
    ]
})

webpack.base.js

const path = require('path')
const Dotenv = require('dotenv-webpack')
const HtmlWebPackPlugin = require('html-webpack-plugin')

module.exports = options => {
    let envPath = '.env'
    process.argv.forEach(val => {
        if (val.includes('--env=')) {
            const curEnv = val.slice(6)
            if (['dev', 'stg'].includes(curEnv)) {
                envPath = `.env.${curEnv}`
            }
        }
    })
    return {
        mode: options.mode,
        devServer: options.devServer,
        entry: [path.join(process.cwd(), 'src/main.js')],
        output: {
            path: path.join(__dirname, '../dist/'),
            publicPath: '/',
            filename: '[name].[hash].js',
            chunkFilename: '[id].[hash].js'
        },
        resolve: {
            extensions: ['.js', '.jsx'],
            modules: [
                path.join(__dirname, '../src'),
                path.join(__dirname, '../node_modules')
            ],
            alias: {
                '@constants': path.join(__dirname, '../src/constants'),
                '@c': path.join(__dirname, '../src/components'),
                '@C': path.join(__dirname, '../src/containers')
            }
        },
        plugins: options.plugins.concat([
            new Dotenv({
                path: path.join(process.cwd(), envPath)
            }),
            new HtmlWebPackPlugin({
                inject: true,
                template: path.join(__dirname, '../src/static/index.html'),
                favicon: path.join(__dirname, '../src/static/favicon.ico')
            })
        ]),
        module: {
            rules: options.module.rules.concat([
                // {
                //  enforce: 'pre',
                //  test: /\.jsx?$/,
                //  exclude: /node_modules/,
                //  use: [
                //      {
                //          loader: 'eslint-loader',
                //          options: {
                //              quiet: true
                //          }
                //      }
                //  ]
                // },
                {
                    test: /\.(woff|woff2|eot|ttf|otf)$/,
                    exclude: [ /\.scss$/ ],
                    use: [
                        {
                            loader: 'file-loader',
                            options: {
                                name: '[hash].[ext]',
                                outputPath: 'fonts'
                            }
                        }
                    ]
                },
                {
                    test: /\.svg$/,
                    loader: 'svg-react-loader'
                },
                {
                    test: /\.(gif|png|jpe?g)$/i,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                limit: 10 * 1024,
                                name: '[hash].[ext]',
                                outputPath: 'assets'
                            }
                        },
                        {
                            loader: 'image-webpack-loader',
                            options: {
                                disable: options.mode === 'development'
                            }
                        }
                    ]
                }
            ])
        }
    }
}

webpack.dev.js

const webpack = require('webpack')
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')

module.exports = require('./webpack.base')({
    mode: 'development',
    devServer: {
        hot: true,
        port: 3000,
        historyApiFallback: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new BrowserSyncPlugin(
            { proxy: 'http://localhost:3000/', open: false },
            { reload: false }
        )
    ],
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        plugins: [
                            [
                                'react-css-modules',
                                {
                                    "filetypes": {
                                        ".scss": { "syntax": "postcss-scss" }
                                    },
                                    "generateScopedName": '[name]_[local]_[hash:base64:5]'
                                }
                            ],
                        ],
                    },
                },
                resolve: {
                        extensions: ['.js', '.jsx']
                }
            },
            {
                test: /\.(sa|sc)ss$/,
                use: [
                    { loader: 'style-loader' },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            sourceMap: true,
                            localIdentName: '[name]_[local]_[hash:base64:5]'
                        }
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader', 'postcss-loader']
            },
        ]
    }
})

webpack.prod.js

const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = require('./webpack.base')({
    mode: 'production',
    devServer: {
        port: 3000,
        contentBase: path.join(process.cwd(), 'dist/')
    },
    optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin({
                cache: true,
                parallel: true
            }),
            new OptimizeCSSAssetsPlugin()
        ]
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules\/@babel/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            [
                            '@babel/preset-env',
                                {
                                    'targets': {
                                        'ie': '11'
                                    },
                                    'loose': true,
                                    'forceAllTransforms': true
                                }
                            ],
                            '@babel/preset-react'
                        ],
                        sourceType: 'unambiguous',
                        plugins: [
                            [
                                '@babel/plugin-proposal-decorators',
                                {
                                    'legacy': true
                                }
                            ],
                            '@babel/plugin-transform-runtime',
                            '@babel/plugin-syntax-dynamic-import',
                            '@babel/plugin-proposal-function-bind',
                            '@babel/plugin-proposal-class-properties',
                            '@babel/plugin-proposal-export-default-from',
                            '@babel/plugin-proposal-export-namespace-from'
                        ]
                    }
                },
                resolve: {
                    extensions: ['.js', '.jsx']
                }
            },
            {
                test: /\.(sc|sa)ss$/,
                use: [
                    { loader: MiniCssExtractPlugin.loader },
                    {
                    loader: "css-loader",
                    options: {
                        modules: true,
                        sourceMap: true,
                        localIdentName: "[name]_[local]_[hash:base64:5]"
                    }
                    },
                    { loader: "postcss-loader" },
                    {  loader: "sass-loader" }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin([path.join(process.cwd(), '/dist')], {
            allowExternal: true
        }),
        new MiniCssExtractPlugin({
            filename: '[name].[hash].css',
            chunkFilename: '[id].[hash].css'
        }),
        new CompressionPlugin({
            test: /\.(js|css)$/,
            filename: asset => asset.file
        })
    ]
})

【问题讨论】:

    标签: javascript css node.js webpack sass


    【解决方案1】:

    对于这行代码

    test: /\.(sc|sa|c)ss$/,
                    use: [
                        { loader: MiniCssExtractPlugin.loader },
                            {
                            loader: "css-loader",
    

    我很确定你不能这样做,因为 scss 和 sass 需要有 sass 或 scss 加载器,所以如果你使用 css-loader,它就无法处理 sass 或 scss

    这是我的配置方式

    module: {
            rules: [{
                    test: /\.scss$/,
                    use: [
                        'style-loader',
                        MiniCssExtractPlugin.loader,
                        {
                            loader: "css-loader",
                            options: {
                                minimize: true,
                                sourceMap: true
                            }
                        },
                        {
                            loader: "sass-loader"
                        }
                    ]
                }
            ]
        }
    

    你可以查看我的完整配置here

    【讨论】:

    • 我正在尝试使用 scss 模块并生成一个作用域名称,其中类名看起来像 table_3A5D。我的元素的类名/样式名正在转换,所以我不确定是否是未加载 scss 样式表,或者转换样式名是否可以解决问题。
    • 我已经通过将react-css-modules 插件添加到babel-loader 来处理scss 文件类型来解决我的问题。
    猜你喜欢
    • 2020-03-25
    • 1970-01-01
    • 2018-02-28
    • 2020-02-13
    • 2017-06-21
    • 2019-12-19
    • 2019-04-08
    • 2018-05-31
    • 2018-06-30
    相关资源
    最近更新 更多