blog
blog copied to clipboard
F.I.S 前瞻
我在 #2 里曾提到过:Require.js 不是最终解决方案。
为什么这样说呢?想一下这样的场景:
我有很多模块,某一天我更新了其中的 a.js。为了让用户的浏览器不去读缓存,比较 low 的做法是在网页里引用这个脚本的时候,手动带上版本号或时间戳,例如:
<script src="a.js?20150102"></script>
但是,模块是由 require.js 来加载的,不需要(也不能)由我们手动添加 script 标签。好在 require.js 提供了一个配置属性 urlArgs,但问题在于:这个设置是全局的,所有被加载的模块都会带上这个 urlArgs。
这意味着它没有_增量更新_的能力:我修改了一个模块,然后更新了这个设置,那么其它所有未修改的模块文件也会被用户的浏览器重新下载一遍。
其实不仅是 require.js ,其它所有在页面上被引用的静态文件都有同样的问题。只是,一些后端语言已经考虑到了这个问题,例如公司项目使用的 Spring 框架,会自动根据页面上引用的静态文件的内容生成一个 md5 字符串,写在文件名里(见 http://spring.io/blog/2014/07/24/spring-framework-4-1-handling-static-web-resources)。
举个例子,我在 jsp 模版里引用了一个脚本:
<script src="require.js"></script>
那么 jsp 会把它输出为:
<script src="require-d3jhi6s2.js"></script>
实际上,服务器并没有真的生成一个新的文件叫 require-d3jhi6s2.js,它仍然返回的是 require.js文件的内容,只是浏览器(或者 CDN )可能就需要去下载一个“新的”文件了;这种方式对 CSS 以及 CSS 里引用的图片同样有效。
问题似乎已经得到解决了,但这种 jsp 模版并不支持对 require.js 里的模块引用做同样的处理。
于是我找到了 F.I.S,不得不说,它真的是一个非常强大的系统。我花了半天时间去阅读了它的文档,又花了半天时间研究一个基于 require.js 的例子。
在上面的例子里,fis 对前端模块化构建给出了两种解决方案:
- 同步加载。分析出所有代码里引用到的模块,并在网页文件中我们指定的位置将模块文件写成 script 标签加载的方式。
- 异步加载。分析出模块的引用路径与处理后(压缩,加上md5等)的文件路径的映射表,并写在 require.js 的
paths设置里。
我个人比较喜欢第二种,因为第一种需要改动 html(或 jsp),而把现有项目完全融入 fis 的生态系统中有点困难,况且前面我分析过,我只需要处理 require.js 的模块部分就好了。
于是,在下班之前(也就是现在),我给了自己两种解决方案:
- 使用 fis 来生成映射表,并加到我自己的项目中去。
- 自己处理:自己给所有模块加上 md5、生成映射表并加入到 require.js 的 config 中。
第二种方案似乎是多余的,但考虑到 fis 文档写的太简陋,第一种方式的时间成本可能会比第二种还高。
但 fis 还是值得学习。如果以后开始一个新的项目,我就可以尝试使用它了。