webpack如何分别打包第三方库和自己写的公用业务逻辑库

背景

我的项目是一个多页应用,用webpack作为构建工具,目前是用CommonsChunkPlugin(minChunks: 5)把所有require5次以上的模块(这里面既包括第三方库,也包括我自己写的公用业务逻辑模块)都打包到一起,因此基本上每个页面只加载俩js,一个是前面提到的这个打包的js,另外一个就是仅在本页面使用到的entry.js。
以登录页作为例子,每个页面加载的js是这样的:

<!-- 公用模块(这里面既包括第三方库,也包括我自己写的公用业务逻辑模块) -->
<script type="text/javascript" src="../../../build/commons.bundle.js"></script>
<!-- 每个页面独有的入口文件,在本页面用到而又没有被打包到commons.bundle.js里的话(可能是当前页面独有的逻辑,也可能是少于5次require的公用业务逻辑模块/第三方库)就会被打包到entry.js里 -->
<script type="text/javascript" src="../../../build/index/login/page/entry.js"></script>

需求

现在我的需求是,把第三方库和我自己写的公用业务逻辑库分开来打包,这是基于下面的考虑:

  • 第三方库基本不会改动,打包一次就不用动了,对缓存有好处。

  • 把第三方库拉出来后,webpack打包速度可以更快。
    我希望最后达到的效果是:

<!-- 公用业务逻辑模块打包 -->
<script type="text/javascript" src="../../../build/commons.bundle.js"></script>
<!-- 所有的第三方库打包 -->
<script type="text/javascript" src="../../../build/commons.bundle.js"></script>
<!-- 每个页面独有的入口文件 -->
<script type="text/javascript" src="../../../build/index/login/page/entry.js"></script>

尝试

我在网上没有搜到这样的例子,只搜得到仅把第三方库独立出来打包的例子(没有考虑到公用业务逻辑库的情况)。

我自己有尝试过用俩CommonsChunkPlugin:

commonsChunkPluginForVendor = new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    filename: '[name].bundle.js',
    minChunks: Infinity,
});

commonsChunkPlugin = new webpack.optimize.CommonsChunkPlugin({
    name: 'commons',
    filename: '[name].bundle.js',
    minChunks: 5,
});

这样打包出来的效果是,第三方库的确是独立出来了打包到了vendor.bundle.js里,但是commons.bundle.js里却只有webpack的一些执行代码,并没有把公用业务逻辑库抽取出来,而是分散到各个entry.js里。

请教怎么才能分别打包第三方库和自己写的公用业务逻辑库呢?

阅读 22.3k
6 个回答
  1. 第三方库打包之后不想再编译可以使用 webpack 的 dll 功能,具体可以看这里:https://segmentfault.com/a/1190000005969643

  2. 公共的代码再加个 entry:

entry: {
    '公共页面': [
        '公共业务1','公共业务2',
    ]
}

这个问题我刚好处理过,但是我的处理办法比较 复杂。

我的把架构做得分成三层

  • lib层(也就是最底层依赖的第三方组件模块, npm包) 被打包在一起(lib.js)

  • framework层(这层是我自己项目框架层抽像实现,为应用提供最基础的服务模块), 被打包在一起(mao.js)

  • app层(这是具体的应用层,并且这一层可以有多个实例,因为我们架构是SPA应用,app之间是一个独立的程序,基于上面两层 framework和lib),单独app相关的代码单独打包

所以最后打包的文件会有
lib.js
lib.css

mao.js
mao.css

app1.js
app1.css

app2.js
app2.css

每个app只引入 lib.js, mao.js, 和自己相关的业务代码比如 app1.js

所以 lib.js, mao.js 在app之间是共用同一份代码

我是怎么实现的呢,方法比较奇葩,我自己写了2000多行的构造辅助工具和自己写webpack插件来完成这个任务。

我们项目在编译打包是 以分层打包的,也就是 lib, framework, app 这些层的代码分开打包,

这个分开打包最大问题是后面的合并,就是能让 require 找到正确的module, 要知道 webpack 编译出来的代码

require是通过一个module id(数字) 来查找对应的模块, webpack的实现在当前执行环境的内存里放了一个字典对象数据(id 跟 module代码实现对应的 map结构数据), 每一层打包 同一个模块的id 是有不一样的可能的,所以。这里我自己也加了一些hack级的代码在最终的执行环境上,为了让不同层的require通正确找到目标模块,我是在构造时候使用 文件系统的模块路径做唯一索引 来实现目标模块的查找, 整理的比较乱,有空我在分享下这个方案。

http://qmin91.com/manage/teac... 这个实现是 应用的其中一个

推荐问题
宣传栏