如何使用Webpack将关键的CSS打印到索引.html?



我正在开发一个大型单页应用程序,其中包含由Webpack生成的非常大的CSS和JS文件,这会导致在最初加载应用程序时闪烁无样式的内容。

为了避免这种情况,我想将CSS的关键部分打印到文档的头部,这样当浏览器处理JS和CSS的其余部分时,文档就不会显得没有样式。

此 CSS 是用 SASS 编写的,并且依赖于全局应用程序变量,因此 webpack 必须处理文件以将它们从 SASS 编译到 CSS,然后再将其打印到文档头。

如何使用 Webpack 完成此操作?

我这样做的方式是

  1. 使用单独的加载器规则和 ExtractTextPlugin 实例将关键 CSS 分离到自己的资产中;
  2. 禁用默认注入html-webpack-plugin以在模板中手动注入资产;
  3. 非关键资产通过文件链接注入(示例(。关键 CSS 是使用compilation变量内联注入的(示例(。

注意。您可以将逻辑放在HtmlWebpackPlugin选项中的函数中。示例在答案的末尾。

这样,人们几乎可以完全控制资产的包含方式,例如标签、属性、位置。

有几个插件也可能有助于内联CSS和JS,例如

  • html-webpack-inline-source-plugin
  • style-ext-html-webpack-plugin
  • script-ext-html-webpack-plugin

但它们剥夺了完全控制格式、逻辑和输出的灵活性,并用有限的配置选项取而代之。


示例配置

plugins: [
//...
new HtmlWebpackPlugin({
template: 'path-to-index-template',
inject: false,
injectCriticalCss(htmlWebpackPluginStats, compilation) {
return lodash(htmlWebpackPluginStats.files.chunks)
.map(chunk => chunk.css)
.flatten()
.filter(cssFilename => /^criticalb/.test(cssFilename))
.map(cssFilename => `<style>${
compilation.assets[cssFilename].source()
}</style>`)
.join('n');
},
injectNonCriticalCss(htmlWebpackPluginStats) {
return lodash(htmlWebpackPluginStats.files.chunks)
.map(chunk => chunk.css)
.flatten()
.filter(cssFilename => !/^criticalb/.test(cssFilename))
.map(cssFilename => `<link rel="preload" as="style" href="${
cssFilename
}" onload="this.rel='stylesheet'"/>`)
.join('n');
},
//...
}),
//...
]

然后在模板中

<html>
<head>
<!-- ... -->
<%= htmlWebpackPlugin.options.injectCriticalCss(htmlWebpackPlugin, compilation) %>
</head>
<body>
<!-- ... -->
<%= htmlWebpackPlugin.options.injectNonCriticalCss(htmlWebpackPlugin) %>
</body>
</html>

你需要使用ExtractTextPlugin,以便从js文件中提取它并写入单个文件,以便你可以将其链接到html的头部。

看看它是如何与sass-loader一起使用的。

const extractSass = new ExtractTextPlugin({
filename: '[name].css',
})
module: {
rules: [
{
test: /.(scss)$/,
use: extractSass.extract({
use: [{
loader: 'css-loader', options: {
sourceMap: true,
minimize: true
}
}, {
loader: 'sass-loader', options: {
sourceMap: true,
minimize: true
}
}],
// use style-loader in development
fallback: 'style-loader'
})
}
]
},
plugins: [
extractSass,
]

最新更新