使用 webpack 进行代码分割和懒加载(单页应用)
作者:Seiya
时间:2019年07月09日
代码分割的意义
对于大的 Web 应用来讲,将所有的代码都放在一个文件中显然是不够有效的,特别是当你的某些代码块是在某些特殊的时候才会被使用到。webpack 有一个功能就是将你的代码库分割成 chunks(语块),当代码运行到需要它们的时候再进行加载。
适用的场景
抽离相同代码到一个共享块;
脚本懒加载,使得初始下载的代码更小;
不同于多页面应用的提取公共代码,单页面的代码分割和懒加载不是通过 webpack 配置来实现的,而是通过 webpack 的写法和内置函数实现的。
准备
这里我们拿第三篇文章中使用的例子进行修改,如下所示:
module.js
export default "module";
subPageA.js
import "./module"; console.log("I'm subPageA"); export default "subPageA";
subPageB.js
import "./module"; console.log("I'm subPageB"); export default "subPageB";
注意:subPageA.js 和 subPageB.js 两个文件中都执行了 console.log()语句。之后将会看到 import()和 require()不同的表现形式:是否会自动执行 js 的代码?
编写 webpack 配置
const path = require('path');
module.exports = {
entry: {
page: './src/page.js' //
},
output: {
publicPath: __dirname + '/dist/',
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js'
}
};
require 编写 page.js
require.ensure(
['./subPageA.js', './subPageB.js'], // js文件或者模块名称
function() {
var subPageA = require('./subPageA'); // 引入后需要手动执行,控制台才会打印
var subPageB = require('./subPageB');
},
'subPage' // chunkName
);
require.ensure(
['lodash'],
function() {
var _ = require('lodash');
_.join(['1', '2']);
},
'vendor'
);
export default 'page';
根据我们编写的代码,subPageA.js 和 subPageB.js 共同引用了 module.js 文件,我们可以将 module.js 体现抽离出来:
// 将subPageA 和 subPageB 共用的 module.js 打包在此 page 中
require.include("./module.js");
import 编写 page.js
动态 import(⽬前还没有原生支持,需要 babel 转换),需要安装 @babel/plugin-syntax-dynamic-import
这个插件,然后在 babelrc 文件中进行配置:
{
"presets": [
[
"@babel/preset-env"
],
"@babel/preset-react"
]
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
配置完成后,我们可以这样进行使用:
import("./subPageA").then(function(subPageA) { console.log(subPageA) })
import() 可以通过注释的方法来指定打包后的 chunk 的名字,如果通过注释指定的名称一致,表示两个文件将合并到一起。除此之外,vue-router 官方文档的路由懒加载的配置也是通过 import() 来书写的。
import(/* webpackChunkName: 'subPageA'*/ "./subPageA").then(function(subPageA) {
console.log(subPageA);
});
import(/* webpackChunkName: 'subPageB'*/ "./subPageB").then(function(subPageB) {
console.log(subPageB);
});
import(/* webpackChunkName: 'lodash'*/ "lodash").then(function(_) {
console.log(_.join(["1", "2"]));
});
export default "page";