假如你正在开发一个单页应用,随着项目功能的不断增加,打包后的文件也越来越大,此时为减少页面的初始加载时间和避免不必要的多余加载,我们就需要实现动态加载,或者叫按需加载。

翻一下webpack的官网,很容就会发现2个方法:

require.ensure

require.ensure(dependencies: String[], callback: function([require]), [chunkName: String])
  • dependencies:是一个数组指明所依赖的文件
  • callback:是一个回调函数,在callback执行前其内部的依赖会被提取出来和dependencies中的依赖合并到一起提前加载。在webpack内部这些模块会被包装成CommonJs模块存储到模块队列,按需执行。
  • chunkName:块文件名

require.ensure方法会创建一个块文件,文件名可以自定义,如果块文件名已经存在,则此方法中的依赖会被合并到已经存在的块文件依赖中。

Style:CommonJs

Example:

// in file.js
var a = require("a");
require.ensure(["b"], function(require) {
    var c = require("c");
});
require.ensure(["d"], function() {
    var e = require("e");
}, "my chunk");
require.ensure([], function() {
    var f = require("f");
}, "my chunk");
/* This results in:
    * entry chunk
        - file.js
        - a
    * anonymous chunk
        - b
        - c
    * "my chunk"
        - d
        - e
        - f
*/

require

require(dependencies: String[], [callback: function(...)])

require方法和require.ensure方法很像,如果你熟悉RequireJS一眼就会明白其用法。dependencies中的每个依赖都会把执行结果当作参数传给callback,此方法不能指定块名。

Style: AMD

Example:

// in file.js
var a = require("a");
require(["b"], function(b) {
    var c = require("c");
});
/* This results in:
    * entry chunk
        - file.js
        - a
    * anonymous chunk
        - b
        - c
*/

实战中遇到的问题

动态加载的块文件因为不在浏览器默认请求队列,不管如何刷新F5或ctrl+F5(command+F5),块文件在第一次加载后再次请求始终返回304状态码(从浏览器缓存读取),此时可以在修改webpack.config.js的配置,每次生成不同文件名的块文件:

output: {
    //...
    chunkFilename: outputDir + "/[id].[name]-[chunkhash].js"
},

如果你并不想生成太多的版本文件,可以给文件增加动态参数

output: {
    //...
    chunkFilename: "[name].chunk.min.js?ver=[chunkhash]"
}