SeaJS 里版本号和时间戳管理的最佳实践
用 seajs 组织项目,上线后,经常需要更新特定文件或所有文件的时间戳,以清空浏览器缓存。最简单的方式是:
define(function(require, exports) { var a = require('path/to/a.js?20110801'); });
这种方式很简单直观,弊端也很明显:文件一多,时间戳会分散在各个文件,维护起来不方便。
第二种方式是利用 alias:
seajs.config({ alias: { 'jquery': 'jquery/1.6.2/jquery', 'backbone': 'backbone/0.5.1/backbone', 'a': 'a.js?20110801', 'b': 'b.js?20110801' } });
这种方式用来维护 jquery 等类库模块的版本号是非常方便的。但用来加时间戳,文件一多时,依旧不方便。
第三种方式是利用 map:
seajs.config({ 'map': [ [ /^(.*\.(?:css|js))(.*)$/i, '$1?20110801' ] ] });
这种方式,用来批量更新时间戳是最方便的。
最佳实践
假设文件存放路径如下:
http://example.com/libs/seajs/1.0.0/sea.js http://example.com/libs/jquery/1.6.2/jquery.js http://example.com/libs/backbone/0.5.1/backbone.js http://example.com/app/xxx/a.js http://example.com/app/xxx/b.js http://example.com/app/xxx/c.css
为了方便版本和时间戳管理,建议配置如下:
config.js:
seajs.config({ alias: { 'jquery': 'jquery/1.6.2/jquery', 'backbone': 'backbone/0.5.1/backbone' }, map: [ [ /^(.*\/app\/xxx\/.*\.(?:css|js))(?:.*)$/i, '$1?20110802' ] ] });
这样配置好后,在具体模块代码里,就不再需要考虑时间戳了:
define(function(require, exports) { var $ = require('jquery'); var BB = require('backbone'); var a = require('./a'); var b = require('./b'); require('./c.css'); // ... });
还是楼主厉害啊,现在我也同样的问题,我修改的seajs的源码,感觉不妥,以后的版本升级会是一件麻烦的事,正在纠结时,看到楼主的这篇文章,楼主的办法真实赞啊
decadeofsword
August 1, 2011 at 11:05
tornado 框架里有个 static_url() 方法来引用静态文件, 加时间戳这事它自己搞定, 每次代码有改动也自动更新了. 不用手动去改那个 config
evan
August 1, 2011 at 11:05
@evan: 这个要配合后端服务一起来搞定。目前淘宝内部正在通过 RMS (资源管理系统)来自动更新时间戳,等开发完毕后,会有和 seajs 的配合解决方案。届时分享给大家。
lifesinger
August 1, 2011 at 11:12
这个好… 正则的应用….
…顺便问下… backbone 怎样包装成seajs的模块? 我照jq同样的方式貌似木成功…
而且backbone还得依赖underscore….
潇洒
August 1, 2011 at 11:21
看这里,有封装好的:http://modules.seajs.com/backbone/0.5.1/backbone.js
lifesinger
August 1, 2011 at 11:25
看懂鸟~ 多谢~ 原来得这么折腾下…
潇洒
August 1, 2011 at 11:30
玉伯会将 seajs 应用到 淘宝的项目中吗?
木元
August 1, 2011 at 17:52
会的。目前已经有不少项目在用的。
lifesinger
August 1, 2011 at 18:12
玉伯 有用 seajs 封装过的 kissy 吗? 在淘宝 cdn 上的
sado
August 10, 2011 at 16:21
目前淘宝 cdn 上还没有封装过的 kissy
kissy 的封装,直接封装成一个大文件意义不大,kissy 本身也有自己的一套 loader 机制。
计划在 KISSY 2.0 里,会将 kissy 拆开(core + components),等那时会有 seajs 的封装并放到 cdn 上。
lifesinger
August 10, 2011 at 22:30
求助 玉伯 seajs 的打包问题, spm 可以在 windows 下打包吗?
在 nodejs 官网下载了 v0.5.3 的 node.exe, 将 spm/bin 加入到 path 里
运行 spm build init.js –combo ,然后提示 unknown action “node.exe”
雕刻
August 11, 2011 at 13:47
很抱歉,目前 spm 正在火热重构,目前还不支持 window. 等半个月内会支持。
lifesinger
August 11, 2011 at 15:31
用时间戳的方式还是相当不靠谱的。
1、一方面只要有1个文件发生了改动,所有文件的缓存都被清掉了
2、虽然可以用正则匹配,但还要修改一处,如果忘记修改还是要悲剧的。
可以结合一些编译工具,使用文件的md5值作为query,我们这边已经全部使用这种方式
welefen
August 13, 2011 at 19:21
如果是这样的话可以使用第二种别名的方法啊,所有的文件都用别名,改了哪个改时间的时间戳或者直接用文件的版本号。
Kidwind
August 22, 2011 at 12:21
所有都用别名会很麻烦的,比如模块经常会上百。
lifesinger
August 22, 2011 at 12:30
玉兄,关于时间戳的方式,小弟有不明之处,在此请教了,当然也许问题本身和seajs本身没有太大的联系,但还是希望玉兄不吝赐教。
问题主要是关于浏览器缓存的,本人对浏览器缓存理解不是很深。在测试有时间戳和无时间戳的静态文件(css、js之类)时,浏览器对这两种形式似乎使用了不同的缓存方式,通过Firebug工具可以看到,无时间戳的静态文件只要本地存在缓存,其状态码为200,但如果使用了时间戳的话,本地存在缓存,其状态码为304。查看了一下状态码的解释,304状态码是文件未改变。给我的理解是不是不使用时间戳的文件只要本地有缓存,就直接使用本地缓存,而不管其是否改变;使用时间戳的文件中果本地有缓存,仍然需要向服务器请求缓存文件是否更改,如果未更改,则直接使用本地缓存,如果更改了,则重新下载文件。简单来讲就是无时间戳的文件只要有缓存了,就直接使用缓存,无论是否更改;有时间戳的文件如果有缓存,仍然需要向服务器确认缓存文件是否更改。这样想来有时间戳的其实每次都要向服务器发送请求了,如果网络状况不佳的话,是否意味着更长的等待时间呢,如果即使用时间戳来确定缓存过期,又能使用非时间戳的缓存方式呢?谢谢!!!!
Kidwind
August 22, 2011 at 12:49
Kidwind: 不要用 F5 刷新页面,选中地址栏,回车看效果。有缓存时,不会发请求的。普通用户的使用场景是通过链接打开页面,和在地址栏回车最接近。F5 会强制浏览器请求服务器,不是真实场景。
lifesinger
August 22, 2011 at 13:50
以下测试对C.css文件进行了时间戳的设置。
不用时间戳的话是直接返回200的状态。
测试地址:http://old.rosin-china.com/test.htm
用时间戳的话无论我是F5刷新的,还是直接地址栏回车的,都是返回304哦,意思是说都要向服务器发送请求。
测试地址:http://old.rosin-china.com/test2.htm
难道是我的服务器问题吗?
Kidwind
August 22, 2011 at 14:16
@Kinwind: 肯定是缓存设置有问题,建议 google 下。
lifesinger
August 22, 2011 at 15:11
是吗?那我再看看啥原因,难道是IIS不支持不成。
Kidwind
August 22, 2011 at 15:52
有个问题,关于一些经常用的库,如jquery,显然如果将每个类都独立到一个文件里,有可能每个文件都要用到$这个变量,但如果每个模块里都require一次的话,显然会出现很多重复代码,如何避免这个问题呢?
大凶毅
March 4, 2012 at 17:34
一个小问题:这段代码放哪。。。。
苗威
March 13, 2012 at 18:10
放在 main.js 起始处
lifesinger
March 13, 2012 at 19:44
谢谢
苗威
March 14, 2012 at 09:46
[…] SeaJS 里版本号和时间戳管理的最佳实践 […]
SeaJS快速入门,让js代码模块化 | 南龙的小站
July 6, 2012 at 04:46