背景
- 在实际应用中,比如想让骨架屏等样式资源优先加载等场景下使用
webpack loader设置匹配规则
- 可以通过文件名包含 preload 或者在文件路径添加 ? prelaod 查询参数进行区分
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /preload/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
],
},
],
}
};
webpack plugin 提取不同文件
-
MiniCssExtractPlugin 提取 css 打包进不同的文件
new MiniCssExtractPlugin({
filename: (chunkData) => {
return chunkData.chunk.name.includes('preload') ? '[name].preload.css' : '[name].css';
},
}),
-
HtmlWebpackPlugin 写入不同优先级的文件
new HtmlWebpackPlugin({
template: './src/index.html',
inject: false,
}),
<!DOCTYPE html>
<html>
<head>
<!-- 预加载样式文件 -->
<% htmlWebpackPlugin.files.css.forEach(function(file) { %>
<% if(file.includes('preload')) { %>
<link rel="preload" href="<%= file %>" as="style" onload="this.οnlοad=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="<%= file %>"></noscript>
<% } %>
<% }); %>
</head>
<body>
<!-- 应用的主入口 -->
<div id="app"></div>
<!-- 正常加载主样式文件 -->
<% htmlWebpackPlugin.files.css.forEach(function(file) { %>
<% if(!file.includes('preload')) { %>
<link rel="stylesheet" href="<%= file %>">
<% } %>
<% }); %>
</body>
</html>
-
先设置 preload 再通过 js 设置 rel 属性原因
- 将 <link> 元素的rel属性设置为 “preload”,这样CSS文件会被异步加载,也就是说,文件的加载过程不会阻塞页面的渲染
- 预加载的 css 文件并不会被浏览器应用到页面上,除非将 <link> 元素的 rel 属性改为 “stylesheet”
- 再通过 js 将 <link> 元素的 rel 属性从 “preload” 改为 “stylesheet”,这样就可以在 css 文件加载完毕后将其应用到页面上,而不会阻塞页面的初次渲染
<link rel="preload" href="<%= file %>" as="style" onload="this.οnlοad=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="<%= file %>"></noscript>