Webpack性能优化

一、理想目标

  1. 初始化 js <= 200kb
  2. 初始化 css <= 100kb
  3. http1.1 <= 6个请求
  4. http2.0 <= 20个请求
  5. 更高的代码已使用率,更低的代码未使用率

二、查看代码已使用率

在 Chrome 浏览器的开发者工具中查看。

1. 京东(已用68%)

image-20200708211339672

2. 淘宝(已用52%)

image-20200708211454811

淘宝还有很大的优化空间。


三、代码分离(静态导入)

1. 配置多个入口文件

// webpack.config.js
module.exports = {
  entry: {
    index1: './src/index.js',
    index2: './src/index2.js'
  }
}

2. 配置输出文件名字(便于区分)

// webpack.config.js
module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  }
}

四、代码分离(动态导入,按需加载)

为了减少初始化 js 的大小,有些模块一开始不需要引入,只有在需要它的时候才引入。例如,按钮的点击事件,点击时才加载需要的模块。

1. 需求

点击 html 中的按钮时,切换按钮的字体颜色。

// button.js 生成一个按钮
export default function makeBtn() {
  let btn = document.createElement('button');
  let body = document.getElementsByTagName('body')[0];
  btn.innerHTML = '我是一个Btn!';
  body.appendChild(btn);
}


// color.js
let colorRed = 'red';
let colorBlue = 'blue';
export {
  colorRed,
  colorBlue
}

2. 模块引入

// 入口文件 index.js
import makeBtn from './button.js'
makeBtn(); // 生成按钮
let btn = document.getElementsByTagName('button')[0];

3. 静态导入

import {colorRed, colorBlue} from './color.js'

btn.onclick = function () {
	this.style.color = (this.style.color === colorRed ? colorBlue : colorRed);
}

4. 动态导入

btn.onclick = function () {
  // 动态导入,按需导入
  import('./color.js')
    .then(res => {
      this.style.color = (this.style.color === res.colorRed ? res.colorBlue : res.colorRed);
    })
}

只有在触发了 btn 的点击事件时,才会引入 color 模块。

5. 动态导入的 loader 配置

这里因为使用了动态语法可能会涉及动态 import 的兼容问题,需要安装依赖和配置。

npm i @babel/plugin-syntax-dynamic-import

https://blog.csdn.net/m0_37616866/article/details/85601201


五、动态导入的优化写法

将 import(...) 写在顶部,优化代码。

// 入口文件 index.js
const getColor = () => {
  return import('./color.js')
}
// 进一步优化为:
const getColor = () => import('./color.js')

使用,通过 getColor() 调用,相当于原来的写法。

btn.onclick = function () {
  getColor().then(res => {
    this.style.color = (this.style.color === res.colorRed ? res.colorBlue : res.colorRed);
  })
}

六、动态导入的其他形式

1. 导入第三方库

例如,动态导入lodash工具库。

const getLodash = () => import('lodash-es')

注意要安装依赖 lodash-es,这是es6版本的 lodash。

npm i lodash-es --save-dev

2. 导入文件夹中所有模块

(1)在 scr 下新建文件夹 buttonBgc,里面放着三种颜色。

// bgcA.js
export default {
  color: '#ccc'
}

// bgcB.js
export default {
  color: '#666'
}

// bgcC.js
export default {
  color: '#eee'
}

(2)导入文件

const getBgc = (bgc) => import(`./buttonBgc/${bgc}.js`)

btn2.onclick = function () {
  getBgc('bgcB').then(res => {
    // console.log(res.default)
    this.style.backgroundColor = res.default.color
  })
}

现在传进去的是 bgcB 的颜色。

(3)打包编译

image-20200708231400698

名字非常拉胯,webpack 提供了一个叫做魔法注释的方法去设置他们的名字。


七、Magic Comments

https://webpack.js.org/api/module-methods/#magic-comments

1. webpackChunkName

(1) 使用

const getColor = () => import(/* webpackChunkName: "font-color" */ './color.js')
const getLodash = () => import(/* webpackChunkName: "lodash" */ 'lodash-es')
const getBgc = (bgc) => import(/* webpackChunkName: "bgc-color" */ `./buttonBgc/${bgc}.js`)

(2) 效果

打包编译后:

image-20200708232652114

chunkhash 有点长,可以自定义位数,具体在 output 的 filename 上设置。

2. webpackMode

开发模式适用 lazy-once 模式。

对于 bgcColor 文件夹下的模块,下面只用到了 bgcB.js 一个模块,因此完全没有必要把那个目录下所有的模块都去打包编译出来。

用了 / webpackMode: "lazy-once" / 就能实现这种功能:只打包用到的模块。

/* webpackMode: "lazy-once" */
// 入口文件 index.js

// 对环境进行判断,从而确定是否使用 lazy-once。如果是开发模式就用lazy-once,否则不用。
// console.log(process.env.NODE_ENV); // node中提供的查看环境的变量

if (process.env.NODE_ENV === 'development') {
  const getBgc = (bgc) => import(/* webpackChunkName: "bgc-color" */ /* webpackMode: "lazy-once" */ `./buttonBgc/${bgc}.js`)
} else if (process.env.NODE_ENV === 'production') {
  const getBgc = (bgc) => import(/* webpackChunkName: "bgc-color" */ `./buttonBgc/${bgc}.js`)
}

btn2.onclick = function () {
  getBgc('bgcB').then(res => {
    console.log(res.default)
    this.style.backgroundColor = res.default.color
  })
}

八、Prefetching/Preloading modules

代码分离中的预加载功能:

https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules

有些模块可以让它提前进行加载,以免动态导入时产生延迟,这样就提高了用户体验。

const getColor = () => import(/* webpackChunkName: "font-color" */ /* webpackPrefetch: true */ './color.js')
posted @ 2020-07-14 16:29  见嘉于世  阅读(454)  评论(0编辑  收藏  举报