为了上线以后用户能使用到最新的静态资源,大部分人会使用添加时间戳来清掉缓存,相似于下面这样的代码。读过张云龙的「大公司里怎样开发和部署前端代码」,意识这种方法有几个弊端。一则是每次修改一下时间戳所有的静态资源都会从新被下载一次,没有修改过的文件又从新下载一遍明显是一种浪费。二则是这种方法是一种覆盖式发布,不管先部署页面仍是先部署静态资源,期间均可能有用户访问到页面,都有可能形成了页面显示错乱问题,因此须要一种非覆盖式的发布方法来避免这种状况。javascript
<!-- css --> <link rel="stylesheet" type="text/css" href="index.css?t=20160121" /> <!-- js --> <script type="text/javascript" src="index.js?t=20160121"></script>
总结上诉理论,此刻咱们须要一种非覆盖式发布的方法,而此时这种方法就是将静态资源的内容hash后修改其文件名,作到文件名不一样从而起到相似于时间戳的做用。如如下静态资源hash后的文件名发生的变化:css
css/index.css -> css/index.aa59f6ab.css img/demo.png -> img/demo.aa59f6ac.png
接下要怎么实现以上方法呢?要用的工具是Grunt,使用到的插件以下:html
"devDependencies": { "grunt": "^0.4.5", "grunt-contrib-clean": "^1.0.0", "grunt-contrib-copy": "^1.0.0", "grunt-filerev": "^2.3.1", "grunt-usemin": "^3.1.1" }
这里暂时不涉及到js文件,处理js文件跟处理css文件相似。使用了「grunt-filerev」即可以很轻松地生成hash后的静态文件。前端
// 静态文件hash filerev: { img: { src: 'src/img/**/*.png', dest: 'dest/img/' }, css: { src: 'src/css/**/*.css', dest: 'dest/css/' } }
静态文件生成后即可以使用「grunt-usemin」对使用到这些静态文件的文件里进行文件名替换,改为hash后的静态文件名。java
// 替换 usemin: { options: { assetsDirs: [ 'dest', 'dest/img', 'dest/css' ] }, css: 'dest/css/**/*.css', html: 'dest/html/**/*.html' }
如下的步骤都会避免修改到源文件。具体步骤则是先将图片hash后放置于dest目录(发布目录)。而后将css代码都复制到一个tmp目录(临时目录),替换里面变动的图片名字,再将css文件hash后放置于dest目录。接着将html代码复制到dest目录,替换里面引用到的图片和css文件名。最后将tmp目录删除。具体代码实现以下:git
// 步骤一:对图片进行处理 grunt.registerTask('img', [ 'filerev:img' ]); // 步骤二:对css进行处理 grunt.registerTask('css', [ 'copy:css', 'usemin:css', 'filerev:css' ]); // 步骤三:对html进行处理 grunt.registerTask('html', [ 'copy:html', 'usemin:html', 'clean:tmp' ]);
未解决的问题:如上代码,我把它分红了三份分别按步骤运行,可是放在一个任务里却会遇到问题,好比css里的图片名称没有被替换等。如哪位朋友有解决办法,不妨传授我一下,感激!github