什么是code splitting
首先说,code splitting
指什么。我们打包时通常会生成一个大的bundle.js
(或者index
,看你如何命名)文件,这样所有的模块都会打包到这个bundle.js
文件中,最终生成的文件往往比较大。code splitting
就是指将文件分割为块(chunk
),webpack
使我们可以定义一些分割点(split point
),根据这些分割点对文件进行分块,并实现按需加载。
code splitting
的意义
第三方类库单独打包。由于第三方类库的内容基本不会改变,可以将其与业务代码分离出来,这样就可以将类库代码缓存在客户端,减少请求。
按需加载。
webpack
支持定义分割点,通过require.ensure
进行按需加载。通用模块单独打包。我们代码中可能会有一些通用模块,比如弹窗、分页、通用的方法等等。其他业务代码模块常常会有引用这些通用模块。若按照
2
中做,则会造成通用模块重复打包。这时可以将通用模块单独打包出来。
下文将详细说明。
如何进行code spliting
第三方类库
我们项目中常常会用到一些第三方的类库,比如jquery
,bootstrap
等。可以配置多入口来将第三方类库单独打包,如下:
//在entry中添加入口
entry: {
index: './index',
vendor: ['jquery', 'bootstrap']
},
//在plugins中配置
plugins: [
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.bundle.js"),
]
说明 CommonsChunkPlugin
提供两个参数,第一个参数为对应的chunk
名(chunk
指文件块,对应entry
中的属性名),第二个参数为生成的文件名。
这个插件做了两件事:
将
vendor
配置的模块(jquery
,bootstrap
)打包到vendor.bundle.js
中。将
index
中存在的jquery
,bootstrap
模块从文件中移除。这样index
中则只留下纯净的业务代码。
按需加载
以基于backbone
的单页面应用为例,可以在router
中进行配置实现按需加载,如下:
router.js
var Router = Backbone.Router.extend({
routes: {
'a': 'a',
'b': 'b'
},
a: function() {
require.ensure(['./a'], (require) => {
let a = require('./a');
//do something
})
},
b: function() {
require.ensure(['./b'], (require) => {
let b = require('./b');
//do something
})
}
})
说明
如上方式将打出两个文件,a.js
和b.js
(当然名字会有所不同),且为按需加载。只有在访问a
时,a.js
才会被加载,b
同理。但是这种做法存在两个问题:
若路由分配不合理,会打包出很多很小的文件,每个文件或许只有几
k
,却多了很多网络请求,得不偿失。会造成通用模块的重复打包,比如
a
模块和b
模块都引用了c
模块,
a
import 'c' from './c'
b
import 'c' from './c'
这样我们会发现打包出的a.js
和b.js
中都包含c
模块的代码,造成了代码冗余。
对于问题1
,可以通过webpack
提供的插件来解决:
//在plugins中添加该插件:
plugins: [
new webpack.optimize.AggressiveMergingPlugin()
]
对于问题2
:
可以按照下文中所说方式解决。
通用模块打包
这个问题我再网上查阅了一些资料,没有发现特别好的方案,以下所述为自己的一些尝试,但是也并非最优解,希望有更好解决方案的同学能够指出。
同样是利用entry
和commonsChunkPlugin
来处理的。如下:
//在entry中添加入口
entry: {
index: './index',
common: ['./c', './d'], //其中c,d模块为通用功能模块
vendor: ['jquery', 'bootstrap']
},
//在plugin中
plugins: [
new webpack.optimize.CommonsChunkPlugin(["common", "vendor"], "[name].js") //[name]对应'common'和'vendor'
]
这样则会打包出common.js
和vendor.js
两个文件。common
为通用功能模块。
但是这种方式在项目依赖复杂情况下的效果还是不太理想,无法做到某段代码只加载一次。
希望有更好方案的同学能够不吝赐教。
(本文完)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。