Webpack打包时丢失.jsx文件中引入的第三方CSS模块怎么办?
我目前的Webpack配置需要同时生成资源的压缩版和未压缩版,配置代码如下:
const path = require('path'); const webpack = require("webpack"); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const readSass = new ExtractTextPlugin({ filename: "foo/bar/style.min.css" }); config = { entry: { "main": './main.js', "main.min": './main.js', "style.min": './style.scss' }, watch: true, devtool: "source-map", output: { path: path.resolve(__dirname, '/dist'), filename: '[name].js' }, module: { rules: [ { test: /\.jsx?$/i, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['es2015', 'react'], minified: true } }, { test: /\.scss|css$/, use: readSass.extract({ use: [{ loader: "css-loader", options: { minimize: true } }, { loader: "sass-loader" }] }) } ], }, plugins: [ readSass, new UglifyJsPlugin({ include: /\.min\.js$/ }) ], } module.exports = config;
一切运行正常,但在部分.jsx文件中引入第三方组件的CSS(比如import 'react-plugin/react-plugin.css';)后,这些样式并未出现在编译后的JS和CSS文件中,唯独style.scss里的样式和JS代码正常,请问哪里操作有误?
嘿,我来帮你捋清楚问题出在哪:
你当前的配置里,ExtractTextPlugin只在处理style.min这个独立SCSS入口时生效,但JSX中引入的第三方CSS属于main和main.min这两个JS入口的依赖,Webpack并没有把这些CSS合并到你指定的style.min.css文件里。简单说就是,你的CSS提取逻辑只覆盖了单独的SCSS入口,没覆盖JS里引入的CSS资源。
给你几个具体的修复步骤:
第一步:统一CSS引入方式,调整入口配置
把style.scss直接引入到main.js里(比如在main.js顶部加import './style.scss';),然后删掉entry里的style.min项。这样所有CSS资源(包括你自己的SCSS和第三方组件的CSS)都会成为JS入口的依赖,ExtractTextPlugin就能统一捕获它们了。第二步:优化CSS Loader配置,兼容第三方非模块化CSS
你的loader规则已经包含了.css文件且没有排除node_modules,这部分没问题,但可以给css-loader加个modules: false的选项,避免第三方非模块化CSS被错误当成CSS模块处理:{ test: /\.(scss|css)$/, use: readSass.extract({ use: [ { loader: "css-loader", options: { minimize: true, modules: false // 确保第三方非模块化CSS正常处理 } }, { loader: "sass-loader" } ] }) }第三步:修正Output路径的小问题
你原来的output.path用了path.resolve(__dirname, '/dist'),这会生成根目录下的绝对路径/dist,改成path.resolve(__dirname, 'dist')会更合理,生成项目根目录下的dist文件夹。
调整后的完整配置大概是这样的:
const path = require('path'); const webpack = require("webpack"); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const readSass = new ExtractTextPlugin({ filename: "foo/bar/style.min.css" }); config = { entry: { "main": './main.js', "main.min": './main.js' }, watch: true, devtool: "source-map", output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js' }, module: { rules: [ { test: /\.jsx?$/i, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['es2015', 'react'], minified: true } }, { test: /\.(scss|css)$/, use: readSass.extract({ use: [ { loader: "css-loader", options: { minimize: true, modules: false } }, { loader: "sass-loader" } ] }) } ], }, plugins: [ readSass, new UglifyJsPlugin({ include: /\.min\.js$/ }) ], } module.exports = config;
这样调整后,JSX里引入的第三方CSS就会被ExtractTextPlugin提取到foo/bar/style.min.css里,和你自己的SCSS样式合并在一起了。
内容的提问来源于stack exchange,提问作者Wordpressor

