当我们遇到多入口项目时,如果不抽离代码块,一些公用的代码就会被加载两次,造成资源损耗。

本节介绍如何实现多入口打包配置,以及如何抽离公有代码块。

01 多入口打包

准备:

准备两个入口文件(或更多)

  • aaa.js
  • bbb.js

aaa.js

console.log("aaa.js")

bbb.js

console.log("bbb.js")

webpack配置:

原来单入口配置是这样的:

module.exports = {
  mode: "production",//模式,两种模式,产线模式"production"、开发模式"development"。产线模式会把编译文件进行压缩优化,代码变成一行。
  entry: "./src/aaa.js",//入口,相对路径
  output: {
    filename: "bundle.[hash:8].js",//打包后的文件名
    path: path.resolve(__dirname, "dist"),//打包后的路径(文件夹路径),必须是绝对路径,"__dirname"指当前路径
  },
}

修改entryoutputfilename字段。

[name]是指:获取entry里面的key值,这里是作为文件名。

修改后如下:

module.exports = {
  mode: "production",//模式,两种模式,产线模式"production"、开发模式"development"。产线模式会把编译文件进行压缩优化,代码变成一行。
  entry: {
    aaa:'./src/aaa.js',
    bbb:'./src/bbb.js'
  },
  output: {
    filename: "[name].js",//打包后的文件名
    path: path.resolve(__dirname, "dist"),//打包后的路径(文件夹路径),必须是绝对路径,"__dirname"指当前路径
  },
}

打包:

npx webpack

发现输出目录(这里是./dist)下生成了aaa.jsbbb.js两个输出文件。

这就实现多入口打包。

02 公用代码块抽离

准备:

我们在多入口打包的基础上,新增两个文件。

  • common1.js
  • common2.js

common1.js

console.log("common1 呀~~~~~")

common2.js

console.log("common1 呀~~~~~")

分别在aaa.js和bbb.js中引入:

aaa.js

import common1 from "./common1"
import common2 from "./common2"
console.log("aaa.js")

bbb.js

import common1 from "./common1"
import common2 from "./common2"
console.log("bbb.js")

此时运行打包npx webpack

会发现

{var n={906:function(){console.log("common1 呀~~~~~")},385:function(){console.log("common2 呀~~~~~")}}

这段代码再两个入口文件中都出现了。

这就证明了,common1.jscommon2.js被打包了两次。

webpack 配置

在webpack中添加如下配置:


module.exports = {
  optimization:{//优化配置项
    splitChunks:{//分割代码块
      cacheGroups:{//缓存组
        common:{//缓存公用模块
          chunks:'initial',//从入口文件抽离
          minSize:0,//只要大于0字节就抽离
          minChunks:2,//只要使用2次以上就抽离
        }
      }
    }
  },
}

运行npx webpack打包。

你会发现, 除了两个入口文件以外,多了一个文件。

这个多出来的文件里,存储了common1.jscommon2.js两个文件的代码内容。

./dist/383.js

(self.webpackChunkmm_webpack=self.webpackChunkmm_webpack||[]).push([[383],{906:function(){console.log("common1 呀~~~~~")},385:function(){console.log("common2 呀~~~~~")}}]);

然后aaa.jsbbb.js文件分别引用这个文件。

./dist/aaa.js

var n={246:function(n,r,t){t(906),t(385),console.log("aaa.js")}},

./dist/bbb.js

var n={709:function(n,r,t){t(906),t(385),console.log("bbb.js")}},

至此,公用代码抽离就实现了。

03 抽离第三方模块

有时候我们不仅仅需要抽离自己写的公用代码,还需要抽离node_modules文件夹下的第三方模块代码。

一般第三方代码比较多,抽离重复使用的代码,能大大减少包体积。

准备:

这里用一个测试文件来代替存在node_modules文件夹下的第三方模块代码。

  • ./node_modules/test.js
console.log("test.js ~~~")

修改我们原有的入口文件。

  • ./src/aaa.js
import common1 from "./common1"
import common2 from "./common2"

import test from "test"
console.log(test)
console.log("aaa.js")
  • ./src/bbb.js
import common1 from "./common1"
import common2 from "./common2"

import test from "test"
console.log(test)
console.log("bbb.js")

aaa.jsbbb.js分别引入了test.js,这就模拟了代码中多页面使用同一个第三方库的情况。

接下来编写webpack配置:

module.exports = {
  optimization:{//优化配置项
    splitChunks:{//分割代码块
      cacheGroups:{//缓存组
        common:{//缓存公用模块
          chunks:'initial',//从入口文件抽离
          minSize:0,//只要大于0字节就抽离
          minChunks:2,//只要使用2次以上就抽离
        },
        vendor: {
          test: /node_modules/,//把node_modules文件夹下的公用引用抽离出来
          chunks: 'initial',//从入口文件抽离
          minSize: 0,//只要大于0字节就抽离
          minChunks: 2,//只要使用2次以上就抽离
        }
      }
    }
  },
}

运行npx webpack打包
会发现抽离出来的test.js的代码与之前的公用代码合并到一个文件里了。

(self.webpackChunkmm_webpack=self.webpackChunkmm_webpack||[]).push([[854],{507:function(){console.log("test.js ~~~")},906:function(){console.log("common1 呀~~~~~")},385:function(){console.log("common2 呀~~~~~")}}]);

其实这是一个错误,你会发现webpack里不添加vendor配置也是生成这样的结果。

这说明vendor配置并没有生效。

原因是:

webpack的optimization执行顺序是从上到下,先执行到的common配置,并且满足条件,就不会执行下面的vendor配置了。

所以我们需要给vendor配置添加一个priority参数,告诉webpack它需要优先执行。

修改webpack配置:

module.exports = {
  optimization:{//优化配置项
    splitChunks:{//分割代码块
      cacheGroups:{//缓存组
        common:{//缓存公用模块
          chunks:'initial',//从入口文件抽离
          minSize:0,//只要大于0字节就抽离
          minChunks:2,//只要使用2次以上就抽离
        },
        vendor: {
          priority: 1,//优先级提高,先执行vendor,再执行其他
          test: /node_modules/,//把node_modules文件夹下的公用引用抽离出来
          chunks: 'initial',//从入口文件抽离
          minSize: 0,//只要大于0字节就抽离
          minChunks: 2,//只要使用2次以上就抽离
        }
      }
    }
  },
}

再运行npx webpack
你会发现多了一个输出文件。

这次,./node_modules/test.js文件与其他公用代码的抽离分成了两个文件,内容分别是:

(self.webpackChunkmm_webpack=self.webpackChunkmm_webpack||[]).push([[507],{507:function(){console.log("test.js ~~~")}}]);
(self.webpackChunkmm_webpack=self.webpackChunkmm_webpack||[]).push([[383],{906:function(){console.log("common1 呀~~~~~")},385:function(){console.log("common2 呀~~~~~")}}]);

至此,第三方模块代码的抽离就完成了。

如有疑问,欢迎留言交流。

END