edp icon indicating copy to clipboard operation
edp copied to clipboard

edp静态资源添加版本号处理方案思考

Open wuhy opened this issue 10 years ago • 6 comments

使用版本化目的:

  1. 避免浏览器端缓存需要重新请求的静态资源;
  2. 更好版本号机制,可以确保每次上线,浏览器端不会重复请求没有变化的静态资源。

目前edp提供了如下几种添加版本号方式:

通过配置

// SvnRevision函数请自己实现
{ 
    "to": "asset-" + SvnRevision()
}

优点:使用简单,能够多版本并存 缺点:浏览器无法充分利用缓存的机制,由于这种方式默认所有静态资源都发生变化, 其次服务端静态资源随着上线次数增多,静态资源文件夹数量也会越来越多

  • <a href="https://github.com/ecomfe/edp/wiki/Build-Processors#variablesubstitution target="_blank">VariableSubstitution处理器
new VariableSubstitution({
    files: ['*.html'],
    variables: {
        version: '1.0.0'
    }
});

/* 
html里:
<link rel="stylesheet" href="main.css?{edp-variable:version}">
会被替换成:
<link rel="stylesheet" href="main.css?1.0.0">

对于amd模块:
require.config({
        'baseUrl': 'src',
        'urlArgs': '{edp-variable:version}'
});
*/

优点:使用简单 缺点:

  1. 需要在开发代码里,加上一些版本化的占位符,感觉不是特别好。而且当需要加上版本号的地方比较多,这种情况感觉会比较乱,而且容易不小心把某个需要加上版本号的地方漏掉了;
  2. 同样这种方法,没法充分利用浏览器缓存特性;
  3. 没法多版本并存。
new MD5Renamer( {
    files: [ 
        "src/common/css/main.less"
    ],
    replacements: {
        html: [
            "index.html"
        ]
    }
} )

优点:可以充分利用浏览器缓存,由于每次都是基于内容计算md5值作为版本号; 缺点:

  1. 只支持样式文件及普通的js文件,对于amd模块包括其它通过require的资源比如模板不支持;
  2. 要计算的md5值的文件是用md5值作为名称重命名的,这样不好辨识原来的文件, 比如上面例子的main.less,可能就变成b74e3635.css文件了;
  3. 同样如果有新的引用样式或者文件名修改了,需要同时更新上述配置,这也会同样造成容易遗漏的风险。

期望的方案(是否有更好?)

  1. 首先不需要每次有新增文件或者修改文件名,需要重新修改配置;
  2. 能够利用md5值作为静态资源的版本号

针对第二点,目前最大问题在于amd模块包括其它require的静态资源,现在想到的一个方案,利用前面提到的require.config的urlArgs参数,通过计算模块的md5值生成如下结果:

'urlArgs': {
            '0287cc87.tpl': 'v=0287cc8700d7468d',
            'actionConf': 'v=368cf7e5ee0583d1',
            'main': 'v=a57286b9402c25fd',
            'account/index': 'v=d41d8cd98f00b204',
}

当然这里有个问题,就是如果每个模块文件多生成上面的md5版本号的话,无疑index.html包含的上面的这个配置文件后,会变得非常大,其次也会影响require的效率。 一个折中方案,就是生成一定深度的路径前缀的md5值版本号,带来缺点是可能没法确保所有未变化的静态资源都不会重复请求,举个例子: 如果生成a/b前缀的版本号,如果a/b下面包含c.js和d.js文件,如果c.js变化了,那么d.js即便没变化,也会重复请求,因为版本号变化了。

wuhy avatar Apr 17 '14 05:04 wuhy

我们现在是方案1即svn号管理,但是确实缓存有效性太低,后续打算把主要文件(管家build后会有4个大的js文件,包含了60%以上的模块)用md5管理,剩下的继续用svn版本号

otakustay avatar Apr 17 '14 05:04 otakustay

md5rename纯粹的md5做名字其实还是有点问题,不利于线上查看

这个东西最好搞成可定制的,默认是md5,但是我想要 originName_md5这种形式也能做到

在 2014年4月17日,下午1:53,Gray Zhang [email protected] 写道:

我们现在是方案1即svn号管理,但是确实缓存有效性太低,后续打算把主要文件(管家build后会有4个大的js文件,包含了60%以上的模块)用md5管理,剩下的继续用svn版本号

— Reply to this email directly or view it on GitHub.

leowang721 avatar Apr 17 '14 06:04 leowang721

最好是MD5RenamerTplMerge这种会生成新文件的,都能有个filename属性配置一个文件名模板,比如{rawName}-{md5}.{ext}这样

otakustay avatar Apr 17 '14 06:04 otakustay

@wuhy 如果新增一个Processor,支持这样的参数如何?

new XXXProcessor({
    entryFiles: [
        '*.html'
    ],
    modules: [
        'main',           //  具体的amd模块
        'foo/bar/dir',    //  某个目录
    ]
})

leeight avatar Apr 28 '14 10:04 leeight

最近用edp的时候也遇到了这个问题,同时增量编译有没有好的解决方案?

Fenixgo avatar Aug 12 '15 02:08 Fenixgo

require.config({
  urlArgs: {
    "mod1": "v=xxx",
    "mod2": "v=yyy",
  }
});

可以通过自定义的 Processor,扫描 ProcessContext 里面你所期望的文件,然后输出一个 urlArgs 的配置?

leeight avatar Aug 12 '15 03:08 leeight