We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
随着浏览器的日新月异,网页的性能和速度越来越好,并且对于用户体验来说也越来越重要。 现在有很多优化页面的办法,比如:静态资源的合并和压缩,code splitting,DNS预读取等等。 本文介绍的是另一种优化方法:首屏阻塞css优化
首先我们了解一下页面的基本渲染流程(参考): webkit渲染过程: Gecko渲染过程: 那么,为什么要做这种优化呢?上面的流程图就是原因:首先解析html生成dom树,同时解析css生成css树,之后结合两者生成渲染树,然后渲染到屏幕上。不但如此,如果css后面有其他javascript,并且css加载时间过长,也会阻塞后面的js执行,因为js可能会操作dom节点或者css样式,所以需要等待render树完成。那么,如果我们能优化css,那么就能大大减少页面渲染出来的时间,从而提升pv,增加黏性,走向编码巅峰。。。
目前我知道的比较实用的办法是webpack集成critical,critical是一个提取关键css,内联到html中,并且使用preload和noscript兼容加载非关键css的工具。 那么,我们开门见山,直接从webpack配置开始:
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 创建html来服务你的资源 const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 提取css到分离的文件,需要webpack4 const HtmlCriticalWebpackPlugin = require('html-critical-webpack-plugin'); // 集成critical的html-webpack-plugin版本 const path = require('path'); // 用于设置Chromium,因为Chromium使用npm或者yarn经常有问题 process.env['PUPPETEER_EXECUTABLE_PATH'] = '你电脑中的Chromium地址'; module.exports = { mode: 'none', module: { rules: [ { test: /\.css$/, // 使用MiniCssExtractPlugin.loader代替style-loader use: [MiniCssExtractPlugin.loader, 'css-loader'] }, { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }), new MiniCssExtractPlugin({}), new HtmlCriticalWebpackPlugin({ base: path.resolve(__dirname, 'dist'), src: 'index.html', dest: 'index.html', inline: true, minify: true, extract: true, width: 375, height: 565, // 确保调用打包后的JS文件 penthouse: { blockJSRequests: false } }) ] };
然后是html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div class="div"></div> <h2>hello world</h2> <div class="mask">这是一个弹窗</div> </body> </html>
接着是css文件:
.div { width: 200px; height: 100vh; background-color: red; } h2 { color: blue; } .mask { width: 500px; height: 500px; display: none; position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin: auto; background-color: yellowgreen; }
运行webpack后,查看打包后的html文件:
// 省略... <style> .div { width: 200px; height: 100vh; background-color: red; } .mask { width: 500px; height: 500px; display: none; position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin: auto; background-color: #9acd32; } </style> <link href="main.80dc2a9c.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" /> <noscript><link href="main.80dc2a9c.css" rel="stylesheet"/></noscript> // 省略...
可以看到,h2标签的css样式没有出现在内联style里,而是出现在main.[hash].css中,因为它不再所设置首屏范围内,这就是所谓的首屏css优化。
在上面打包后的html文件里,我们看到了有一个link内有rel="preload" as="style"字段,紧接着下面就有一个noscript标签,这两个是做什么的呢?
rel="preload" as="style"
noscript
rel="preload"
preload
<noscript>
利用critical可以大大提高页面渲染速度,但是由于其使用puppeteer,所以下载安装比较麻烦,上面的webpack中使用设置env中puppeteer位置的方法解决了这一问题。
文中如若有不对的地方,还望之处,共同交流。
The text was updated successfully, but these errors were encountered:
补充:可以将依赖css的js引入放在关键依赖的css之上,也就是说先link,然后在script:src,如果js不依赖任何css,那么可以将它放在css之上,这要是一个可以提高性能的点 可参考链接
link
script:src
Sorry, something went wrong.
比较全面的方案
No branches or pull requests
原理:
首先我们了解一下页面的基本渲染流程(参考):
webkit渲染过程:
Gecko渲染过程:
那么,为什么要做这种优化呢?上面的流程图就是原因:首先解析html生成dom树,同时解析css生成css树,之后结合两者生成渲染树,然后渲染到屏幕上。不但如此,如果css后面有其他javascript,并且css加载时间过长,也会阻塞后面的js执行,因为js可能会操作dom节点或者css样式,所以需要等待render树完成。那么,如果我们能优化css,那么就能大大减少页面渲染出来的时间,从而提升pv,增加黏性,走向编码巅峰。。。
怎么做呢:
目前我知道的比较实用的办法是webpack集成critical,critical是一个提取关键css,内联到html中,并且使用preload和noscript兼容加载非关键css的工具。
那么,我们开门见山,直接从webpack配置开始:
然后是html文件:
接着是css文件:
运行webpack后,查看打包后的html文件:
代码仓库在此,点击fork进行实战练习
可以看到,h2标签的css样式没有出现在内联style里,而是出现在main.[hash].css中,因为它不再所设置首屏范围内,这就是所谓的首屏css优化。
相关内容
在上面打包后的html文件里,我们看到了有一个link内有
rel="preload" as="style"
字段,紧接着下面就有一个noscript
标签,这两个是做什么的呢?rel="preload" as="style"
: 用于进行页面预加载,rel="preload"
通知浏览器开始获取非关键CSS以供之后用。其关键在于,preload
不阻塞渲染,无论资源是否加载完成,浏览器都会接着绘制页面。并且,搭配as使用,可以指定将要预加载内容的类型,可以让浏览器:noscript
:如果页面上的脚本类型不受支持或者当前在浏览器中关闭了脚本,则在HTML<noscript>
元素中定义脚本未被执行时的替代内容。换句话说,就是当浏览器不支持js脚本或者用户主动关闭脚本,那么就会展示noscript
里的内容,而critical则是利用这一点做了向后兼容总结
利用critical可以大大提高页面渲染速度,但是由于其使用puppeteer,所以下载安装比较麻烦,上面的webpack中使用设置env中puppeteer位置的方法解决了这一问题。
文中如若有不对的地方,还望之处,共同交流。
The text was updated successfully, but these errors were encountered: