数字营销 · Web开发 · 基础设施

制造业网站性能优化:前端功能模块化

制造业网站功能越来越丰富,但并不是每个页面都需要加载全部前端代码。本文结合实际网站开发经验,介绍如何通过前端模块化和按需加载,让页面只加载真正需要的功能,在减少资源请求和运行开销的同时,也让长期维护更加简单。

熟悉我的朋友都知道,在制造业网站开发过程中,除了内容、版式和 SEO 之外,网站性能一直是我非常关注的一件事情。因为对于制造业企业来说,网站很多时候并不只是一个简单的“展示页面”。它可能同时承担企业品牌窗口、客户信任入口、广告着陆页以及客户转化入口。

尤其是中小制造业企业,很多客户第一次接触一个品牌,就是从网站开始。页面打开速度、滚动是否流畅、交互是否顺畅,这些看起来比较细节的问题,实际上都会影响用户对企业的第一印象。特别是在广告着陆页场景中,用户可能只停留几十秒。

这个时候,网站性能就更加重要。但制造业网站还有一个特点:页面又不能为了追求速度,做得过于简单。

很多时候,丰富的内容展示本身就是用户体验的一部分。比如:产品轮播、图库、数字增长、标签切换、滚动动画、视频模块……

这些功能可能只在某一个页面使用,也可能被多个页面重复使用。这就带来了一个很现实的问题:一个网站到底应该怎么管理这些前端功能?

早期网站功能放到一个文件

以前很多网站的做法都比较简单。所有页面统一加载 jQuery,然后各种页面效果全部基于 jQuery 开发,这种方式在当年非常流行。一方面是因为开发比较快,另一方面是因为当时的插件生态也非常丰富。但随着网站越来越复杂,问题也慢慢暴露出来。首先,jQuery 本身就有一定的体积,而很多页面实际上只使用了非常少的一部分能力。

更常见的问题是,很多项目会把所有前端逻辑全部放进:

main.js
app.js
common.js

之类的统一文件里。这样做虽然简单,但一个页面即使只需要一个轮播,也可能把其他功能一起加载进来。很多代码当前页面根本用不到。但浏览器还是需要:下载、解析、执行。页面上的功能越来越多,公共 JS 也会越来越大,最后一个看起来并不复杂的企业网站,前端资源反而变得越来越重。

后来开始拆 JS 功能文件

再后来,有些项目开始按照页面拆分。哪个页面需要什么功能,就引入对应的 JS 文件。这样确实比全部打包在一起更合理。但管理上的问题也随之出现了,页面模板开始变得越来越复杂。开发人员需要不断记住:

  • 这个页面要加载哪个 JS?
  • 那个页面还需要哪个文件?
  • 以后增加一个功能,又应该放在哪里?

时间一长,前端的依赖关系就会越来越混乱。还有一些项目,直接把功能逻辑写进页面模板或者页面模块内部。刚开始开发的时候很方便。但是网站运行几年之后,通常就会遇到:功能无法复用、升级困难、配置混乱、维护成本越来越高。

而企业网站恰恰又是生命周期很长的一类网站。一个项目可能运行很多年。前端代码如果没有一个比较清晰的结构,时间越长,越容易失控。

RequireJS模块化加载方案

后来,为了解决前端模块之间的依赖问题,也出现了RequireJS 这样的模块化加载方案。RequireJS 可以根据页面需要动态加载不同的 JavaScript 模块,也能够处理模块之间的依赖关系。相比把所有代码都塞进一个main.js,这种方式已经先进了很多。

RequireJS 解决了当时前端开发中很重要的模块化和依赖管理问题,但对于现在的企业网站来说,它所提供的完整机制,很多时候并不需要全部使用。

随着浏览器本身的能力不断完善,很多过去需要依赖额外库,甚至需要专门处理浏览器差异的功能,现在已经可以直接通过原生 JavaScript 完成。主流浏览器的更新也越来越及时,过去为了兼容不同浏览器而增加的大量处理,现在也没有必要全部保留下来。

基于此,我们可以根据模块化加载思维,同时根据制造业网站的特点,设计一个机制:

让 HTML 自己声明需要什么功能

我们给网站设计一个主功能文件app.js, 它本身除了统一处理页面公共逻辑、初始化逻辑以及基础功能管理之外,还负责异步加载html文件里头指定的功能模块,HTML 依然按照正常方式编写,只是需要某个功能的时候,在对应元素上声明一个模块:

<div component="gallery"></div>

页面加载之后,app.js会异步解析当前页面。发现:

component="gallery"

就知道这个页面需要 gallery 模块,然后自动加载:

gallery.js

如果页面没有这个模块,就不会去请求对应的 JS 文件。也就是说页面需要什么,就加载什么。

没有出现的功能,就不加载。这样,一个只使用了图库功能的页面,不需要为了一个图库,把轮播、视频、动画等其他代码一起加载进来。

按模块加载之后,前端资源自然会变轻。但对我来说,这还不是最重要的一点。真正让我觉得这种方式适合企业网站的,是HTML 结构和前端功能之间建立了非常直接的关系。看到:

<div component="gallery"></div>

基本就知道这个页面使用了 gallery 功能。后期维护的时候,不需要再去翻各种 JS 文件,才能判断某个页面到底依赖了什么。甚至删除 HTML 模块之后,对应的功能也就不会再被加载。这样可以避免网站运行多年之后,留下大量已经没人使用的历史代码。对于生命周期特别长的企业网站来说,我认为非常重要。

现成的 Demo

这套模块化加载方式,实际上现在这个网站就在使用。比如你正在看的评论功能,就不是所有页面统一加载 comment.js。你可以直接查看网站源代码,在评论区域的 section 上,可以看到:

component="comment"

这个属性就是模块声明,网站主要的app.js在加载运行之后,会自动检查页面中有没有需要加载的组件,如果发现:

component="comment"

代表当前需要加载comment.js模块。所以整个网站需要哪些功能,其实从 HTML 结构本身就能够很直观地看出来。这也是我采用这种方式的一个原因:功能跟着页面走,需要什么加载什么,不需要的就不加载。

有兴趣的同学可以直接研究我的网站源代码,或者评论区交流。

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。