岁月如歌

用开放的心态,打造专业的人生。

SeaJS 里版本号和时间戳管理的最佳实践

with 25 comments

用 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');

  // ...
});

Written by lifesinger

August 1, 2011 at 10:44

Posted in Articles

25 Responses

Subscribe to comments with RSS.

  1. 还是楼主厉害啊,现在我也同样的问题,我修改的seajs的源码,感觉不妥,以后的版本升级会是一件麻烦的事,正在纠结时,看到楼主的这篇文章,楼主的办法真实赞啊

    decadeofsword

    August 1, 2011 at 11:05

  2. tornado 框架里有个 static_url() 方法来引用静态文件, 加时间戳这事它自己搞定, 每次代码有改动也自动更新了. 不用手动去改那个 config

    evan

    August 1, 2011 at 11:05

    • @evan: 这个要配合后端服务一起来搞定。目前淘宝内部正在通过 RMS (资源管理系统)来自动更新时间戳,等开发完毕后,会有和 seajs 的配合解决方案。届时分享给大家。

      lifesinger

      August 1, 2011 at 11:12

  3. 这个好… 正则的应用….

    …顺便问下… 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

  4. 玉伯会将 seajs 应用到 淘宝的项目中吗?

    木元

    August 1, 2011 at 17:52

  5. 玉伯 有用 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

  6. 求助 玉伯 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

  7. 用时间戳的方式还是相当不靠谱的。
    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

  8. 玉兄,关于时间戳的方式,小弟有不明之处,在此请教了,当然也许问题本身和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

  9. @Kinwind: 肯定是缓存设置有问题,建议 google 下。

    lifesinger

    August 22, 2011 at 15:11

    • 是吗?那我再看看啥原因,难道是IIS不支持不成。

      Kidwind

      August 22, 2011 at 15:52

  10. 有个问题,关于一些经常用的库,如jquery,显然如果将每个类都独立到一个文件里,有可能每个文件都要用到$这个变量,但如果每个模块里都require一次的话,显然会出现很多重复代码,如何避免这个问题呢?

    大凶毅

    March 4, 2012 at 17:34

  11. 一个小问题:这段代码放哪。。。。

    苗威

    March 13, 2012 at 18:10

  12. 谢谢

    苗威

    March 14, 2012 at 09:46

  13. […] SeaJS 里版本号和时间戳管理的最佳实践 […]


Leave a reply to decadeofsword Cancel reply