• 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')
    
  • 相关阅读:
    Ubuntu无法初始化软件包信息
    数组名做函数的参数
    Printf函数中%p代表什么数据类型
    assert()函数用法总结
    C语言printf 格式 zz
    零值指针指向何处? zz~
    命名空间“System.Net”中不存在类型或命名空间名称“Sockets”。是否缺少程序集引用?
    AD20配置为中文显示
    sharepoint:实现搜索功能
    sharepoint:爬网完成后上传新文档搜索不到(设定爬网Schedule)
  • 原文地址:https://www.cnblogs.com/buildnewhomeland/p/13299798.html
Copyright © 2020-2023  润新知