熟悉我的朋友都知道,在制造业网站开发过程中,除了内容、版式和 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
欢迎分享你的看法,也欢迎补充不同的实践经验。