Webpack 异步模块实现

时间:2018-03-2 作者:剧中人

继上一篇 Odeon的前后端分离之路已经三个多月了。在经历了数次版本迭代后,all in one 的打包方式使得项目初始加载的资源越来越大。

特别是在 Hive Editor 重构时,为 SQL 的输入功能引入了在线代码编辑类库:Ace。经过此次迭代,项目的静态资源体积上升了四百多K。

Odeon 作为一个复杂应用场景的平台类产品,首屏加载时长并不是一个重要的考量指标。并且目前资源的总体积尚在合理范围内,因此长期以来并没有处理静态资源的拆分。

2018年的春节是我工作以来第一次全勤工作。春节过后并无具体工作安排,借此机会就尝试处理下静态资源的拆分。

项目背景什么样?

正如上一篇文章介绍,Odeon 的前端部分正由原来的 HUE 逐步演进为前后端分离的结构。

为提升项目的交互体验,整体使用单页方式实现。主框架使用 vue,由 webpack 实现模块组织及静态资源管理。资源打包为两份,一份为公共资源 vendor.js,包含 vue 和 UI 框架。另一份为 index.js,包含所有的业务代码和用到的其他类库。

虽然代码经过打包压缩并且有拆分,但是页面在初始化时,这些资源都会一股脑地被加载到页面中。随着项目越来越大,滚雪球效应导致首屏加载时长的问题会越来越明显。

因此适当的剥离部分模块,在需要使用的时候按需加载显得格外重要。

如何操作?

经过一番查找,发现 webpack 已经提供了异步模块加载的方法,而且使用起来异常简单。具体可参考 webpack#require-ensure

简单介绍下如何动手配置并使用异步模块。

第一步:创建一个模块文件

此文件即为异步模块的入口文件,这个模块内部引用的资源都会被打包进来。  模块一

模块二

第二步:创建别名

这一步为非必需步骤,为了后面调用方便,资源管理的一致性建议使用此配置。  webpack配置

第三步:加载模块

到这一步几乎就要成功了,在业务代码中使用 require.ensure 加载需要的资源别名。注意到这为止只是把 JS 资源加载到浏览器中,并不能直接使用异步模块内的方法。

具体的模块使用需要借助 require 方法获取。

使用

到此为止,创建一个简单异步模块就已经完成了,通过浏览器查看,异步模块的确在触达具体的业务逻辑时才会被加载,并且能够正确获取模块内容。

控制台结果

当然这部分应该还可以玩出更多的花样,期待后面的深度使用吧。

经验感悟

关于模块管理的讨论,在2012年前后requirejs、seajs流行时就已经被争论很久了。主流声音有两个,一个种是 all in one 实用主义,另一种是最小颗粒化的理想主义。

当然最终都被糅合成了,根据首屏加载以及网络性能优化套路的见招拆招。

再来看我们现在对项目资源的管理,虽然场景和使用的工具已经千差万别,但是思考方式依然是一样的。

无论是拆分还是合并,都是资源优化的一种手段,前提是我们要知道这样能否解决项目潜在的问题。

后续

经过实践,将 Ace 相关的资源进行剥离,并使用异步模块的方式进行加载管理,Odeon 在初始加载时减少了 1/4 的体积,整体加载时间也减少了 20% 左右。

算是为接下来可以预想到的类库引入,提供了异步加载方案预演。