1.如何用webpack来优化前端性能
1.1 压缩JS
1.2 压缩CSS
optimize-css-assets-webpack-plugin
1.3 压缩图片
1.4 清除无用的CSS
单独取出css并清除用不到的css
const path = require("path");+const MiniCssExtractPlugin = require("mini-css-extract-plugin");+const PurgecssPlugin = require("purgecss-webpack-plugin");module.exports = {module: {rules: [{test: /\.css$/,include: path.resolve(__dirname, "src"),exclude: /node_modules/,use: [{loader: MiniCssExtractPlugin.loader,},"css-loader",],}]},plugins: [new MiniCssExtractPlugin({filename: "[name].css",}),new PurgecssPlugin({paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),})]devServer: {},};
1.5 Tree Shaking
- 一个模块可以导出多个方法,只要一个方法被用到了就会把整个文件打包到bundle中去,tree shaking就是把只用到的方法打包到bundle,不用到的在uglify的时候去掉
- 原理是ES6模块的特点,只能作为模块顶层语句出现,import的模块名只能是字符串常量
以下摘自官网
sideEffects
如果被标记为无副作用的模块没有被直接导出使用,打包工具会跳过进行模块的副作用分析评估[sideEffects](https://webpack.docschina.org/configuration/optimization/#optimizationsideeffects) 和 [usedExports](https://webpack.docschina.org/configuration/optimization/#optimizationusedexports)(更多被认为是 tree shaking)是两种不同的优化方式。**sideEffects** 更为有效 是因为它允许跳过整个模块/文件和整个文件子树。usedExports 依赖于 terser 去检测语句中的副作用。它是一个 JavaScript 任务而且没有像 sideEffects 一样简单直接。而且它不能跳转子树/依赖由于细则中说副作用需要被评估。尽管导出函数能运作如常,但 React 框架的高阶函数(HOC)在这种情况下是会出问题的。
webpack.config.js
module.exports = {//...optimization: {usedExports: false}};op
package.json
{"name": "awesome npm module","version": "1.0.0","sideEffects": false}
1.6 scope Hoisting
- Scope Hoisting 可以让 Webpack 打包出来的代码文件更小、运行的更快, 它又译作 “作用域提升”
- scope hoisting的原理是将所有的模块按照引用顺序放在一个函数作用域里,然后适当地重命名一些变量以防止命名冲突
这个功能在mode为
production下默认开启,开发环境要用webpack.optimize.ModuleConcatenationPlugin插件1.7 代码分割
将所有的代码全部打包到一个文件中运行是不合理的,webpack将代码分割成许多代码块(chunks),运行时在加载他们。
1.7.1 动态导入和懒加载
给单页面做按需加载优化的时候一般采用的原则:
- 对网站的功能划分,一个类一个chunk
- 对于首次打开页面的功能直接加载
- 分割出去的模块需要一个加载的时机
按需加载对应chunk的名称
preload通常用于本页面要用到的关键资源,包括关键js、字体、css文件
- preload将会把资源得下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度
在资源上添加预先加载的注释,你指明该模块需要立即被使用
import(`./utils.js`/* webpackPreload: true *//* webpackChunkName: "utils" */)
1.7.3 预拉起(prefetch)
它的作用是告诉浏览器未来可能会使用到的某个资源,浏览器就会在闲时去加载对应的资源,若能预测到用户的行为,比如懒加载,点击到其它页面等则相当于提前预加载了需要的资源
import(`./utils.js`/* webpackPrefetch: true *//* webpackChunkName: "utils" */).then(result => {result.default.log('hello');})
1.7.4 splitChunks
module js的模块化webpack支持commonJS、ES6等模块化规范,简单来说就是你通过import语句引入的代码
- chunk 根据功能拆分的代码块,分为三种
- 入口代码
- import动态导入代码
- splitChunks拆分的代码
bundle是打包之后的文件,一般就是和chunk是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出
splitChunks: {chunks: "all", //默认作用于异步chunk,值为all/initial/asyncminSize: 0, //默认值是30kb,代码块的最小尺寸minChunks: 1, //被多少模块共享,在分割之前模块的被引用次数maxAsyncRequests: 2, //限制异步模块内部的并行最大请求数的,说白了你可以理解为是每个import()它里面的最大并行请求数量maxInitialRequests: 4, //限制入口的拆分数量name: true, //打包后的名称,默认是chunk的名字通过分隔符(默认是~)分隔开,如vendor~automaticNameDelimiter: "~", //默认webpack将会使用入口名和代码块的名称生成命名,比如 'vendors~main.js'cacheGroups: {//设置缓存组用来抽取满足不同规则的chunk,下面以生成common为例vendors: {chunks: "all",test: /node_modules/, //条件priority: -10, ///优先级,一个chunk很可能满足多个缓存组,会被抽取到优先级高的缓存组中,为了能够让自定义缓存组有更高的优先级(默认0),默认缓存组的priority属性为负值.},commons: {chunks: "all",minSize: 0, //最小提取字节数minChunks: 2, //最少被几个chunk引用priority: -20}}}
1.8 CDN
CND又叫内容分发网络,把资源分布到世界各地,从最近的地方取资源,从而加快获取速度。CDN作用加速网络传输
- 可以在 http 响应头加上 Cache-control 或 Expires 字段来设置缓存,浏览器可以将这些资源一一缓存到本地
- 后续访问的时候,如果需要再次请求同样的静态资源,且静态资源没有过期,那么浏览器可以直接走本地缓存而不用再通过网络请求资源
- 缓存配置
- HTML文件不缓存,放在自己的服务器上,关闭自己服务器的缓存,静态资源的URL变成指向CDN服务器的地址,并且文件名带上HASH值
- 为了并行加载不阻塞,把不同的静态资源分配到不同的CDN服务器上
- 域名限制
