18_webpack代码分离

2022/5/3 6:14:19

本文主要是介绍18_webpack代码分离,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

什么是代码分离

代码分离(Code Splitting)是webpack一个非常重要的特性

他主要的目的是将代码分离到不同的bundle中,之后我们可以按需加载,或者并行加载这些文件

比如默认情况下,所有的JS代码(业务代码,第三方依赖,展示没有用到的模块)在首页全部都加载
就会影响首页的加载速度

代码分离可以分出更小的bundle,以及控制资源加载优先级,提供代码的加载性能

webpack中常用的代码分离有三种
  入口起点:使用entry配置手动代码分离
  防止重复:使用Entry Dependencies或者SplitChunksPlugin去重和分离代码
  动态导入:通过模块的内联函数调用来分离代码

 

Entry Dependencies(入口依赖)

 

入口手动分离代码

 entry: {
    main: "./src/main.js",
    index: "./src/index.js",
  },
  output: {
    path: resolveApp("./build"),
    filename: "[name].bundle.js",
  },

但是这样子会有缺点

如:我在main.js引入了lodash库,在index.js也引入了lodash这个库,那么webpack在打包后的index.js中有一份lodash,main.js中也有一份lodash,相当于生成了两份lodash

我们不想在打包后的每个引用第三方依赖的js文件中都把第三方的依赖都打包进去,这个时候我们就需要对第三方代码进行一个分离

 entry: {
                      //也可以写成一个数组
    main: { import: "./src/main.js", dependOn: "lodash" },
    index: { import: "./src/index.js", dependOn: "lodash" },
    lodash: "lodash",
  },

那么这个时候,lodash就会生成一个单独的js文件,webpack会通过模块化加载lodash

假如我在main和index文件又引入了dayjs第三方库的时候,我们还需要对dayjs进行分离,那么改如何设置呢?
我们可以这样设置:

  entry: {
    main: { import: "./src/main.js", dependOn: ["lodash", "dayjs"] },
    index: { import: "./src/index.js", dependOn: ["lodash", "dayjs"] },
    lodash: "lodash",
    dayjs: "dayjs",
  },

也可以这样设置:

  entry: {
    //他们两个依赖的库是一样的话可以添加一个shared属性
    main: { import: "./src/main.js", dependOn: "shared" },
    index: { import: "./src/index.js", dependOn: "shared" },
    shared: ["lodash", "dayjs"],
  },

 

当我们build的时候会给我们生成一个LICENSE.txt文件,那么我们如何去掉呢?

const TerserPlugin = require("terser-webpack-plugin");

// 和entry同级
optimization: {
    minimizer: [
      new TerserPlugin({
        extractComments: false,
      }),
    ],
  },

 

 

Split Chunks

它是使用 SplitChunksPlugin来实现的

  因为该插件webpack已经默认安装和集成,所以我们并不需要单独安装,直接使用该插件

  只需要提供SplitChunksPlugin相关的配置信息即可

webpack提供了SplitChunksPlugin默认的配置,我们也可以手动来修改它的配置:

  比如默认配置中,chunks仅仅针对于异步(async)请求,我们可以设置为initial或者all

 

如:我们使用import语句导入的dayjs和lodash,他们相当于是同步的,所以该插件并不会对他进行任何的分离,所以我们需要修改其中的chunks值

require()和import()就是异步加载js文件所以该插件会对导入的其js代码进行分离

  optimization: {
    minimizer: [
      new TerserPlugin({
        extractComments: false,
      }),
    ],
    splitChunks: {
      // async:require,import函数
      // initial:同步导入如:import语句
      // all:异步/同步都支持
      chunks: "all",
    },
  },

你会发现在我们的build文件夹已经生成了一个叫xxx(数字).bundle.js文件,就已经对代码进行了一个分离

 

因为我们所有的分离都是使用SplitChunksPlugin来实现的,所以我们需要对它的配置有所了解

   splitChunks: {
      // async:require,import函数
      // initial:同步导入如:import语句
      // all:异步/同步都支持
      chunks: "all",
      // 最小值:默认值为:20000kb,如果我们拆分出来一个包,那么拆分出来的这个包的大小最小为minSize,如果达不到就不拆分了
      // minSize的优先级大于maxSize的优先级
      minSize: 2000,
      // 将大于maxSize的包拆分成不小于minSize的包,
      maxSize: 2000,
      // minChunks表示引入的包,至少被引入了一次
      minChunks: 1,
      // 缓存组:b把匹配的文件打包到vendors中
      // 把来自node_modules文件夹的代码(第三方库)打包到vendors中
      // 当匹配到了lodash不会立即做一个输出,先缓存,等到把所有的匹配都加载完成之后,一起用filename命名的名字一起做一个输出
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          filename: "[id]_vendors.js",
          //优先级,如果vendors和default都满足的情况下,它会优先使用default
          priority: -20,
        },
        /* bar: {
          test: /bar_/,
          filename: "[id]_bar.js",
        }, */
        default: {
          //如果有一个文件被引用了两次,会被打包成一个单独的文件
          minChunks: 2,
          filename: "common_[id].js",
          //优先级 一般是负数
          priority: -10,
        },
      },
    },

这些配置我们一般都不需要进行配置的,使用默认的就好了。

 

动态导入(dynamic import)

另外一个代码拆分是动态导入时,webpack提供了两种实现动态导入的方式
  使用ECMAScript中的import()语法来完成,也是目前推荐的方式
  使用webpack遗留的require.ensure,目前已经不推荐使用

在vue中同步打包出来的文件最多的就4个
1.main.bundle.js
2.vendors_chunks.js
3.common_chunks.js
4.runtime.js

只要是异步导入的代码,webpack都会进行代码分离
无论你的splitChunksPlugin设置的是什么,webpack都会对异步导入的代码进行分离   当我们使用import()函数动态导入,在打包的文件夹中会生成一个[id].bundle.js
打包过后的文件名字来自于哪里呢?
  默认情况下如果你没有告诉他,打包过后的文件叫什么名字,它会根据output.filename来进行命名,但是我这里的filename设置的是 [name].bundle.js ,为什么我的name是一个数字,这个数字来自哪里,它来自optimization的属性中有一个叫chunkIds,他就来自这里  

optimization.chunkIds配置

Optimization | webpack

optimization.chunkIds配置用于告知webpack模块的id采用什么算法生成

boolean = false string: 'natural' | 'named' | 'size' | 'total-size' | 'deterministic'   natural:使用自然数,不推荐,不利于浏览器缓存,假如我对应a.js是1_vendors.js b.js是2_vendors.js,那么我把a.js删除掉了,下次再进行打包的时候,1_vendors.js对应的就是b.js了   named:使用包所在的目录作为name(开发环境推荐)   deterministic:生成id,针对相同的文件,生成的id是不变的(默认)     一般我们的异步代码不叫xxx.bundle.js,应该是xxx.cunk.js,那么该怎么设置呢?
  output: {
    path: resolveApp("./build"),
    filename: "[name].bundle.js",
    chunkFilename: "[name].chunk.js",
  },
但是我们就算设置了[name].chunk.js,那么它生成的文件还是id.chunk.js那么该怎么办呢?
我们可以使用我们的魔法注释(magic comments)

这篇关于18_webpack代码分离的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程