自从决定将公司的网站改用AMD的方式开发之后,积攒了不少 RequireJS 的使用心得,于是在博客里简单的描述一下。
为什么使用RequireJS
在为公司开发网站时,一开始的页面结构是很简单的:
<script src="libs/jquery.js"></script>
<script src="app.js"></script>
后来,公司要求在页面上加一个图表。自己做不来,只好找一个插件,于是页面变成了这样子:
<script src="libs/jquery.js"></script>
<script src="libs/jquery.chart.js"></script>
<script src="app.js"></script>
再后来,公司觉得浏览器的alert()与confirm()样式太丑了,所以我又写了一个公共组件;组件依赖jQuery,并且在每一个网页里都可能用到,于是页面结构成了这样子:
<!-- 组件还带有css -->
<link rel="stylesheet" href="common/alert.css">
<script src="libs/jquery.js"></script>
<script src="common/alert.js"></script>
<script src="libs/jquery.chart.js"></script>
<script src="app.js"></script>
那么问题来了。
- js 文件之间的依赖关系太杂乱。一些插件依赖 jQuery,但一些插件又依赖另一个插件—所以最终,我需要小心翼翼的按照正确的顺序依次列出那些script标签,这肯定是不利于日后维护的。
- 命名空间混乱。为了避免全局变量污染,一些插件会将自己的接口挂载在 jQuery 这个变量上,但这样仍然会污染 jQuery 的命名空间。日后我调试一段代码,发现一个不属于 jQuery 的方法—那这个方法到底是在哪个 js 文件里实现的呢?
为了解决上面这两个问题,我找到了 RequireJS :它正是我需要的解决方案。无需手动维护代码之间的依赖关系,并且不会出现变量污染;由 css、html 与 js 组合起来的组件也可以很容易的合并成一个单独的 js 文件,避免发起多次 http 请求。
最终,上面复杂的页面变成了下面这个样子:
<script src="libs/require.js"></script>
<script src="app.js"></script>
RequireJS与SeaJS,AMD与CommonJS
说起CommonJS就不得不提到NodeJS了,但我仍然认为,在浏览器环境中,AMD才是更合理的开发方式。浏览器毕竟不能像NodeJS那样直接读写硬盘,网页用到的文件都需要下载,所以这必定是一个异步的过程;而var module = require('module');这样的同步加载方式是不适合浏览器环境的。
RequireJS与缓存
缓存的重要性不言而喻,浏览器会缓存请求过的静态文件,避免再次下载,这样可以大大提高页面加载速度。但是在RequireJS中,每次更改js文件之后,文件的路径仍然是一样的,这会导致改动不生效;使用它提供的urlArgs设置虽然能解决这个问题,却又会带来一点浪费:其它未改动的文件也会被重新下载—在不考虑其它解决方案的情况下,这大概是唯一能使改动生效的办法了。
RequireJS不是最终解决方案
在企业级网站的开发过程中,代码开发只是一小部分:部署也同样重要。文件精简、压缩、使用 CDN 都是必不可少的。Grunt、Gulp等工具就是因此被开发出来,但是单靠这些工具仍然不能掌控整个前端开发到部署流程,所以我又开始了新一轮的寻找。
最近了解到了百度开发的 F.I.S ,它解决了企业级网站的很多问题,所以我想,不久之后,我又会写一篇关于FIS的博了 :)