文章目录
  1. 1. 路由懒加载
    1. 1.1. Webpack 代码分割功能
    2. 1.2. Vue 异步组件
    3. 1.3. 调整项目配置
  2. 2. 结束语

最近在使用 Vue2 作为项目中前端的框架,《Vue2 使用笔记》系列用于记录过程中的一些使用和解决方法。本文记录配置路由懒加载,分块打包文件的过程。

路由懒加载


当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

Webpack 代码分割功能

这里我们依赖了 Webpack 的代码分割功能,主要通过 require.ensure() 进行代码拆分。

webpack 在编译时,会静态地解析代码中的 require.ensure(),同时将模块添加到一个分开的 chunk 当中。这个新的 chunk 会被 webpack 通过 jsonp 来按需加载。

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

几个参数分别如下:

  • 依赖dependencies
    这是一个字符串数组,通过这个参数,在所有的回调函数的代码被执行前,我们可以将所有需要用到的模块进行声明。

  • 回调callback
    当所有的依赖都加载完成后,webpack 会执行这个回调函数。require 对象的一个实现会作为一个参数传递给这个回调函数。因此,我们可以进一步 require() 依赖和其它模块提供下一步的执行。

  • chunk 名称chunkName
    chunkName 是提供给这个特定的 require.ensure() 的 chunk 的名称。通过提供 require.ensure() 不同执行点相同的名称,我们可以保证所有的依赖都会一起放进相同的 文件束(bundle)。

Vue 异步组件

Vue.js 允许将组件定义为一个工厂函数,异步地解析组件的定义。Vue.js 只在组件需要渲染时触发工厂函数,并且把结果缓存起来,用于后面的再次渲染。

可以将异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件本身):

1
2
3
4
const Foo = () =>
Promise.resolve({
/* 组件定义对象 */
});

结合 Webpack 的代码分割,我们可以这样去定义异步组件:

1
const Foo = r => require.ensure([], () => r(require("./Foo.vue")), "Foo");

所以我们的路由文件将会变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// router/routes.js
import App from "../App";
const Services = r =>
require.ensure([], () => r(require("components/Services")), "Services");
const ServiceList = r =>
require.ensure(
[],
() => r(require("components/Services/ServiceList")),
"ServiceList"
);
const ServiceEdit = r =>
require.ensure(
[],
() => r(require("components/Services/ServiceEdit")),
"ServiceEdit"
);
const Products = r =>
require.ensure([], () => r(require("components/Products")), "Products");
const ProductList = r =>
require.ensure(
[],
() => r(require("components/Products/ProductList")),
"ProductList"
);
const Logs = r =>
require.ensure([], () => r(require("components/Logs")), "Logs");
const NoAuth = r =>
require.ensure([], () => r(require("components/NoAuth")), "NoAuth");
const NotFound = r =>
require.ensure([], () => r(require("components/NotFound")), "NotFound");
import Login from "../Login";

调整项目配置

由于我们在使用 babel,所以要加个 babel 插件syntax-dynamic-import

1
npm install --save-dev babel-plugin-syntax-dynamic-import

调整配置文件:

1
2
3
4
# .babelrc
{
"plugins": ["syntax-dynamic-import"]
}

另外,如果我们要根据模块名字chunkName来生成文件名字的话,还需要在 webpack 配置里面加个调整:

1
2
3
4
5
6
7
// webpack.prod.conf.js
config = {
output: {
// 这里'js/[id].[chunkhash].js'换成'js/[name].[chunkhash].js'
chunkFilename: utils.assetsPath("js/[name].[chunkhash].js")
}
};

打包后,生成的文件如下:
image

大家会发现,除了我们上面单独打包的文件,还有:

  • app
    我们正常的 bundle 文件,这里因为使用了filename: utils.assetsPath('js/[name].[chunkhash].js')命名,所以我们会根据 entries 名字 app 来命名。
  • vendor
    使用 CommonsChunkPlugin 打包生成的文件。允许我们从不同的 bundle 中提取所有的公共模块,并且将他们加入公共 bundle 中。

在最终打包的页面中,我们能看到,当我们点击某个模块的时候,才会异步请求对应的 bundle 文件:
image

结束语


关于代码的打包和分割,不仅能减轻应用运行的负荷,还能在一定程度上方便我们进行维护。如果说我们需要远程定位一些问题,分块的打包还是有帮助的呢。
此处查看项目代码
此处查看页面效果

查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢

码生艰难,写文不易,给我家猪囤点猫粮了喵~

作者:被删

出处:https://godbasin.github.io

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

文章目录
  1. 1. 路由懒加载
    1. 1.1. Webpack 代码分割功能
    2. 1.2. Vue 异步组件
    3. 1.3. 调整项目配置
  2. 2. 结束语