爲了上線以後用戶能使用到最新的靜態資源,大部分人會使用添加時間戳來清掉緩存,相似於下面這樣的代碼。讀過張雲龍的「大公司裏怎樣開發和部署前端代碼」,意識這種方法有幾個弊端。一則是每次修改一下時間戳所有的靜態資源都會從新被下載一次,沒有修改過的文件又從新下載一遍明顯是一種浪費。二則是這種方法是一種覆蓋式發佈,不管先部署頁面仍是先部署靜態資源,期間均可能有用戶訪問到頁面,都有可能形成了頁面顯示錯亂問題,因此須要一種非覆蓋式的發佈方法來避免這種狀況。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