默认情况下,css 会被打包到 JavaScript 中,在生产环境这么做有一些问题,比如会导致页面闪动。因为浏览器需要加载完 js 以后才能加载样式,此时已有的 html 只能使用浏览器的默认样式。
我们需要将 css 导出到单独的文件中。通过 mini-css-extract-pluginopen in new window 插件我们可以实现将 css 导出到单独的 css bundle 中。mini-css-extract-plugin 插件还可以将多个 css 文件合并成一个 css 文件。出于这个原因,mini-css-extract-plugin 实际上会有一个 loader 来处理导出过程,然后将导出的内容通过插件保存为 css 文件。
mini-css-extract-plugin
安装 mini-css-extract-plugin 插件:
npm add mini-css-extract-plugin --develop
mini-css-extract-plugin 包含有一个 loader MiniCssExtractPlugin.loader
,这个 loader 负责将最终 css 内容导出,然后插件基于导出的内容处理,最终生成 css 文件。
webpack.parts.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
exports.extractCSS = ({ options = {}, loaders = [] } = {}) => {
return {
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: MiniCssExtractPlugin.loader, options },
'css-loader',
].concat(loaders),
sideEffects: true, // 如果构建结果作为一个 npm 包使用时建设设置
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
};
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[name]
占位符使用了导入 css 文件的那个 entry 的名字,如果需要将 css 生成到目录,则可以将路径也放到 filename
配置项里,比如 filename: "styles/[name].css"
。
更新 webpack.config.js
const commonConfig = merge([
...// parts.loadCSS(),
parts.extractCSS(),
]);
2
3
4
执行 npm run build
,输出结果如下:
⬡ webpack: Build Finished
⬡ webpack: asset index.html 229 bytes [compared for emit]
asset main.js 136 bytes [compared for emit] [minimized] (name: main)
asset main.css 33 bytes [compared for emit] (name: main)
Entrypoint main 169 bytes = main.css 33 bytes main.js 136 bytes
orphan modules 199 bytes [orphan] 2 modules
code generated modules 298 bytes (javascript) 32 bytes (css/mini-extract) [code generated]
./src/index.js + 2 modules 298 bytes [built] [code generated]
css ./node_modules/css-loader/dist/cjs.js!./src/main.css 32 bytes [code generated]
webpack 5.11.1 compiled successfully in 572 ms
2
3
4
5
6
7
8
9
10
css 被打包到单独的文件中,避免了闪屏问题。
默认情况下,我们需要在应用入口引入 css 文件,换句话说需要在 js 文件中引入 css。如果不想在 js 文件引用 css 的话,则可以通过 webpack entry 和 globopen in new window 的形式实现 css 的加载。示例如下:
const glob = require('glob');
const commonConfig = merge([
{
entry: { style: glob.sync('./src/**/*.css') }, // 需要手动保证 css 的顺序
},
]);
2
3
4
5
6
7
总结
通过使用 MiniCssExtractPlugin 插件可以解决闪屏问题,同时也优化了浏览器资源加载性能。
如果不想在 JavaScript 中引入 css 文件,则可以通过 webpack entry 的形式加载 css,但是要额外 css 的引用顺序。
关注微信公众号,获取最新推送~
加微信,深入交流~