使用 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";
最后更新时间: 2019-7-16 12:54:06