这是我参与 8 月更文挑战的第 6 天,活动详情查看: 8月更文挑战
前言
当我们的前端工程日益庞大、业务日益复杂下,前端优化显得尤为重要。
- 浏览器输入url到页面的展现,具体发生了些什么,前端能做哪些优化
- DNS 递归查询解析 —— DNS优化prefetch;
- TCP 三次握手、四次挥手 —— http1.0/1.1/2.0 的区别,http/s的区别;
- http 缓存 —— 304 与 CDN;
- webpack —— 资源打包策略
- 浏览器渲染机制 —— CSS、JS顺序的重要性,@import的损耗,防抖、节流、重排、重绘,GPU加速等;
- 如何优化JS主线程 —— web worker,任务分片
- ...
前端要做的性能优化真的很多,本文会列出一些比较常见的点,大家可以进行自查。
DNS 递归查询解析
DNS递归解析原理. “递归解析”(或叫“递归查询”,其实意思是一样的)是最常见, 也是默认的解析方式 。. 在这种解析方式中,如果客户端配置的本地名称服务器, (又称Local DNS, 可以是默认的运营商提供的Local DNS 或者自己设置的DNS) 不能解析的话,则后面的查询全由本地名称服务器代替DNS客户端进行查询,直到本地名称服务器从权威名称服务器得到了正确的解析结果,然后由本地名称服务器告诉DNS客户端查询的结果。
当然在实际情况中,我们一个网页的资源可能来源自不同的域名。这时候,预解析就上场了,在空闲时间对需要DNS查询的资源做前置查询,提高后期加载速度。
<html>
<head>
<link rel="dns-prefetch" href="https://fonts.gstatic.com/">
<!-- and all other head elements -->
</head>
<body>
<!-- your page content -->
</body>
</html>
TCP三次握手、四次挥手
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。
TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
http 缓存
浏览器的缓存有以下特点:
- 减少冗余的数据传输
- 减少服务器负担
- 加快客户端加载网页的速度
强缓存
强缓存是利用http头中的Expires和Cache-Control两个字段来控制的,用来表示资源的缓存时间。强缓存中,普通刷新会忽略它,但不会清除它,需要强制刷新。浏览器强制刷新,请求会带上Cache-Control:no-cache和Pragma:no-cache
协商缓存
协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问。
普通刷新会启用弱缓存,忽略强缓存。只有在地址栏或收藏夹输入网址、通过链接引用资源等情况下,浏览器才会启用强缓存,这也是为什么有时候我们更新一张图片、一个js文件,页面内容依然是旧的,但是直接浏览器访问那个图片或文件,看到的内容却是新的。
这个主要涉及到两组header字段:Etag和If-None-Match、Last-Modified和If-Modified-Since。If-None-Match的单位是秒,在颗粒度更细的场景下有点爱莫能助,所以需要Etag字段做配合使用。
webpack
分析工具
包大小分析
webpack-bundle-analyzer 是打包分析神器,可以看到每个包的大小,以及是否有包被重复打包。
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const config = {
plugins: [
new BundleAnalyzerPlugin(),
]
}
打包速度分析
我们可以通过 speed-measure-webpack-plugin 这个插件帮助我们分析整个打包的总耗时,以及每一个loader 和每一个 plugins 构建所耗费的时间,从而帮助我们快速定位到可以优化 Webpack 的配置。
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports = (production) => {
if (production) {
const endProdConfig = merge(commonConfig, prodConfig);
return smp.wrap(endProdConfig);
} else {
const endDevConfig = merge(commonConfig, devConfig);
return smp.wrap(endDevConfig);
}
};
体积优化
webpack4.0 默认在生产环境的时候是支持代码压缩的,即 mode=production 模式下。
JS压缩
const TerserPlugin = require('terser-webpack-plugin');
const config = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(),
],
},
}
CSS压缩
我们可以借助 optimize-css-assets-webpack-plugin 插件来压缩 css,其默认使用的压缩引擎是 cssnano。
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const prodConfig = {
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
},
canPrint: true,
})
]
},
}
图片压缩
使用很简单,我们只要在 file-loader 之后加入 image-webpack-loader 即可。
const config = {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
}
},
{
loader: 'image-webpack-loader',
options: {
// 压缩 jpeg 的配置
mozjpeg: {
progressive: true,
quality: 65
},
// 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
optipng: {
enabled: false,
},
// 使用 imagemin-pngquant 压缩 png
pngquant: {
quality: '65-90',
speed: 4
},
// 压缩 gif 的配置
gifsicle: {
interlaced: false,
},
// 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
webp: {
quality: 75
}
}
}
]
},
]
}
小结
这篇文章介绍了前端加载性能的一些优化方案,从网络加载到资源打包,我们能做的事情还是很多的。
最后打波小广告,美团校招社招内推,不限部门,不限岗位,不限投递数量,海量hc,快来快来~