Webpack中MiniCssExtractPlugin无法提取CSS文件求助
我帮你梳理了配置里的几个关键错误,正是这些问题导致CSS文件没有被分离出来:
1. 插件加载逻辑完全搞反了
你的plugins选项里的三元判断逻辑写反了,生产环境下根本没加载MiniCssExtractPlugin!
原代码:
plugins: !process.env.NODE_ENV || !devMode ? basicPlugins : basicPlugins.concat(prodPlugins)
解释:devMode = process.env.NODE_ENV !== 'production',所以当执行npm run build(生产环境)时,devMode是false,!devMode是true,这时三元运算会返回basicPlugins——而MiniCssExtractPlugin只在prodPlugins里,所以生产环境根本没启用这个插件,自然不会生成CSS文件。
修正后的逻辑应该是:生产环境时合并basicPlugins和prodPlugins,开发环境只用basicPlugins:
plugins: devMode ? basicPlugins : basicPlugins.concat(prodPlugins)
2. SCSS/SASS Loader顺序错误且冗余
在处理SCSS/SASS的规则里,你同时放了vue-style-loader和style-loader/MiniCssExtractPlugin.loader,这会导致冲突,而且loader的执行顺序是从右到左,正确的顺序应该是把提取/注入样式的loader放在最左边:
原代码:
{ test: /\.(scss|sass)$/, use: [ devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 'vue-style-loader', 'css-loader', 'sass-loader' ] }
问题:vue-style-loader是专门处理Vue组件内样式的loader,当你用MiniCssExtractPlugin时,应该用它的loader替换vue-style-loader和style-loader;开发环境下用vue-style-loader(比style-loader更适配Vue)就够了,不需要同时用style-loader。
修正后:
{ test: /\.(scss|sass)$/, use: [ devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ] }
3. OptimizeCssAssetsPlugin的匹配规则错误
你配置的assetNameRegExp: /\.optimize\.css$/g根本匹配不到MiniCssExtractPlugin生成的css/style.css,所以CSS不会被压缩优化。
修正为匹配所有CSS文件:
new OptimizeCssAssetsPlugin({ assetNameRegExp: /\.css$/g, // 修改这里 cssProcessor: require('cssnano'), cssProcessorOptions: { discardComments: { removeAll: true } }, canPrint: true })
4. 额外:CleanWebpackPlugin旧版本用法提示
你用的clean-webpack-plugin是0.1.x版本,新版本的用法已经变更,但这个不影响CSS生成,只是提一下:如果后续升级到2.x+,需要改成new CleanWebpackPlugin(['dist'])。
修正后的完整Webpack配置
import path from 'path'; import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import VueLoaderPlugin from 'vue-loader/lib/plugin'; import UglifyJsPlugin from 'uglifyjs-webpack-plugin'; import CleanWebpackPlugin from 'clean-webpack-plugin'; const devMode = process.env.NODE_ENV !== 'production'; const prodPlugins = [ new UglifyJsPlugin(), new MiniCssExtractPlugin({ filename: "css/style.css" }), new OptimizeCssAssetsPlugin({ assetNameRegExp: /\.css$/g, // 修正匹配规则 cssProcessor: require('cssnano'), cssProcessorOptions: { discardComments: { removeAll: true } }, canPrint: true }) ]; const basicPlugins = [ new CleanWebpackPlugin('dist'), new VueLoaderPlugin() ]; const config = { entry: { bundle: './src/main.js' }, output: { filename: 'js/[name].js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.css$/, use: [ devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader, // 换成vue-style-loader更适配Vue 'css-loader' ] }, { test: /\.(scss|sass)$/, use: [ devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader, // 修正loader顺序和冗余 'css-loader', 'sass-loader' ] }, { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { js: 'babel-loader', } } }, { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: {} } ] } ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['*', '.js', '.vue', '.json'] }, plugins: devMode ? basicPlugins : basicPlugins.concat(prodPlugins) // 修正插件逻辑 }; module.exports = config;
现在执行npm run build,应该就能在dist/css目录下看到生成的style.css文件了!
内容的提问来源于stack exchange,提问作者szczepaniakdominik

