使用gulp解決RequireJS項目前端緩存問題(一)javascript
使用gulp解決RequireJS項目前端緩存問題(二)css
前端緩存一直是個使人頭疼的問題,你有可能見過下面博客園首頁的資源文件連接:html
有沒有發現文件名後面有一串不規則的東東,沒錯,這就是運用緩存機制,咱們今天研究的就是這種東西。前端
先堵爲快,猛戳連接下載Demo :https://github.com/hua126mail/gulpRequireJsCachejava
以dist爲根目錄,運行http://localhost/html/index.html,若是出現「Good!成功加載index.js」,則表示成功了。node
不熟悉gulp的同窗,能夠參考這個比較詳細的教程:http://www.ydcss.com/archives/18git
不熟悉RequireJS的同窗,能夠參考官方教程:http://www.requirejs.cn/github
gulpRequireJsCache
|
|-- dist //存放發佈的文件
|
|-- rev //存放控制版本號的 rev-manifest.json
|
|-- src //項目源文件
|
|-- gulpfile.js //gulp主文件,定義的任務都在這裏
|
|-- package.json //gulp依賴包配置文件
|
|-- landing.html
根據執行命令npm install --save-dev後,主目錄下會多一個node_modules文件夾,至此,gulp基本配置完成。
gulpfile文件:
var gulp = require('gulp'), sass = require('gulp-sass'), //編譯sass cssmin = require('gulp-clean-css'), //壓縮css autoprefixer = require('gulp-autoprefixer'), //添加瀏覽器前綴 rev = require('gulp-rev'), //添加版本號 revCollector = require('gulp-rev-collector'), //添加版本號 clean = require('gulp-clean'), //清理文目標文件夾 csso = require('gulp-csso'), //合併css屬性 csslint = require('gulp-csslint'), //css語法檢查 csscomb = require('gulp-csscomb'), //css 樣式表的各屬性的順序 imagemin = require('gulp-imagemin'), //圖片壓縮 cache = require('gulp-cache'), //緩存處理 htmlmin = require('gulp-htmlmin'), //壓縮html replace = require('gulp-replace'), //替換路徑 uglify = require('gulp-uglify'), //壓縮js jshint = require('gulp-jshint') //js語法檢查 ; gulp.task("cleanCss",function(){ return gulp.src('dist/css',{read:false}) .pipe(clean()); }); gulp.task('sass', ['cleanCss'],function () { //執行完cleanCss任務後再執行sass任務 gulp.src('src/sass/**/*.scss') .pipe(sass()) .pipe(cssmin()) .pipe(autoprefixer()) //.pipe(csscomb()) .pipe(csso()) .pipe(csslint()) .pipe(rev()) .pipe(gulp.dest('dist/css')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/css')); }); gulp.task("cleanImg",function(){ return gulp.src('dist/img',{read:false}) .pipe(clean()); }); gulp.task('imgmin',['cleanImg'], function () { gulp.src('src/img/**/*.{png,jpg,gif,ico}') .pipe(cache(imagemin())) //沒有修改的圖片直接從緩存文件讀取 .pipe(rev()) .pipe(gulp.dest('dist/img')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/img')); }); gulp.task("cleanJs",function(){ return gulp.src(['dist/js/*','!dist/js/lib'],{read:false}) .pipe(clean()); }) gulp.task('jsmin', ['cleanJs'], function () { gulp.src(['src/js/**/*.js','!src/js/**/*.min.js']) .pipe(jshint()) .pipe(uglify()) .pipe(rev({merge:true})) .pipe(gulp.dest('dist/js')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/js')); gulp.src(['src/js/lib/**/*.js']) .pipe(gulp.dest('dist/js/lib')) }); gulp.task('htmlmin',function () { var options = { removeComments: true,//清除HTML註釋 //collapseWhitespace: true,//壓縮HTML removeEmptyAttributes: true,//刪除全部空格做屬性值 <input id="" /> ==> <input /> minifyJS: true,//壓縮頁面JS minifyCSS: true//壓縮頁面CSS }; gulp.src('src/html/**/*.html') .pipe(htmlmin(options)) .pipe(rev()) .pipe(gulp.dest('dist/html')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/html')); }); gulp.task('replaceURL', function(){ gulp.src(['dist/html/**/*.html']) .pipe(replace('../css', '/css')) .pipe(replace('../js', '/js')) .pipe(replace('/src', '/dist')) .pipe(gulp.dest('dist/html')); gulp.src(['dist/css/**/*.css']) .pipe(replace('../css', '/css')) .pipe(replace('../js', '/js')) .pipe(replace('/src', '/dist')) .pipe(gulp.dest('dist/css')); gulp.src(['dist/js/**/*.js']) .pipe(replace('../css', '/css')) .pipe(replace('../js', '/js')) .pipe(replace('/src', '/dist')) .pipe(gulp.dest('dist/js')); }); gulp.task('revUrl', function() { gulp.src(['rev/{css,img,js}/*.json', 'dist/html/**/*.html']) //- 讀取 rev-manifest.json 文件以及須要進行css名替換的文件 .pipe(revCollector()) //- 執行文件內css名的替換 .pipe(gulp.dest('dist/html')); //- 替換後的文件輸出的目錄 gulp.src(['rev/{css,img,js}/*.json', 'dist/css/**/*.css']) //- 讀取 rev-manifest.json 文件以及須要進行css名替換的文件 .pipe(revCollector()) //- 執行文件內css名的替換 .pipe(gulp.dest('dist/css')); //- 替換後的文件輸出的目錄 gulp.src(['rev/{css,img,js}/*.json', 'dist/js/**/*.js']) //- 讀取 rev-manifest.json 文件以及須要進行css名替換的文件 .pipe(revCollector()) //- 執行文件內css名的替換 .pipe(gulp.dest('dist/js')); //- 替換後的文件輸出的目錄 }); gulp.task("autowatch",function(){ gulp.watch(['src/sass/**/*.scss'],['sass']); //監聽sacc文件改變後,編譯、去緩存 }); /* * 單步步驟: * 1.gulp sass 編譯scss文件 * 2.gulp jsmin 壓縮js * 3.gulp imgmin 壓縮圖片 * 4.gulp htmlmin 壓縮HTML文件 * 5.gulp replaceURL 替換相對路徑爲絕對路徑 * 6.gulp revUrl 引用manifest給HTML添加版本號 * * * gulp sass jsmin htmlmin imgmin replaceURL revUrl * * * * 若是改了scss文件:則執行:gulp sass * 若是改了js文件:則執行:gulp jsmin * 若是改了img文件:則執行:gulp imgmin * * 只要改了HTML引用到的資源文件,最後都須要執行gulp htmlmin,gulp replaceURL,gulp revUrl,以清理緩存 * */
根據最後的單步步驟,咱們來一步步解剖說明:npm
var gulp = require('gulp'), sass = require('gulp-sass'), //編譯sass cssmin = require('gulp-clean-css'), //壓縮css autoprefixer = require('gulp-autoprefixer'), //添加瀏覽器前綴 rev = require('gulp-rev'), //添加版本號 revCollector = require('gulp-rev-collector'), //添加版本號 clean = require('gulp-clean'), //清理文目標文件夾 csso = require('gulp-csso'), //合併css屬性 csslint = require('gulp-csslint'), //css語法檢查 csscomb = require('gulp-csscomb'), //css 樣式表的各屬性的順序 imagemin = require('gulp-imagemin'), //圖片壓縮 cache = require('gulp-cache'), //緩存處理 htmlmin = require('gulp-htmlmin'), //壓縮html replace = require('gulp-replace'), //替換路徑 uglify = require('gulp-uglify'), //壓縮js jshint = require('gulp-jshint') //js語法檢查 ;
這些都是執行任務時要用到的插件,看註釋大概就知道是幹嗎的了。json
gulp.task("cleanCss",function(){ return gulp.src('dist/css',{read:false}) .pipe(clean()); }); gulp.task('sass', ['cleanCss'],function () { //執行完cleanCss任務後再執行sass任務 gulp.src('src/sass/**/*.scss') .pipe(sass()) .pipe(cssmin()) .pipe(autoprefixer()) //.pipe(csscomb()) .pipe(csso()) .pipe(csslint()) .pipe(rev()) .pipe(gulp.dest('dist/css')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/css')); });
gulp.task("autowatch",function(){
gulp.watch(['src/sass/**/*.scss'],['sass']); //監聽sacc文件改變後,編譯、去緩存
});
由於公司項目用的是sass,因此加了一個監放任務,去編譯生成css文件,css發生更改以後先執行「cleanCss」任務,清空dist文件夾下的css文件,重點是後面的.pipe(rev.manifest()),這一步將生成一個資源文件路徑的rev-manifest.json文件,裏面的內容是這樣的:
{ "base/base.css": "base/base-c1e638e1f6.css", "controller/index.css": "controller/index-1454781768.css" }
沒錯,這是用來最後在HTML文件替換css引用路徑的。
同時,dist/css目錄下也生成對應的文件:
gulp.task("cleanImg",function(){ return gulp.src('dist/img',{read:false}) .pipe(clean()); }); gulp.task('imgmin',['cleanImg'], function () { gulp.src('src/img/**/*.{png,jpg,gif,ico}') .pipe(cache(imagemin())) //沒有修改的圖片直接從緩存文件讀取 .pipe(rev()) .pipe(gulp.dest('dist/img')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/img')); });
過程就很少說啦,同樣的先清空dist的圖片文件夾,壓縮圖片,生成rev-manifest.json,生成的文件以下:
{ "push-bg.jpg": "push-bg-6179117417.jpg" }
gulp.task('jsmin', ['cleanJs'], function () { gulp.src(['src/js/**/*.js','!src/js/**/*.min.js']) .pipe(jshint()) .pipe(uglify()) .pipe(rev({merge:true})) .pipe(gulp.dest('dist/js')) .pipe(rev.manifest())//- 生成一個rev-manifest.json .pipe(gulp.dest('rev/js')); gulp.src(['src/js/lib/**/*.js']) .pipe(gulp.dest('dist/js/lib')) });
過程就是檢查語法,壓縮,生成rev-manifest.json,要注意的地方是min類型的文件是放在lib目錄下,是不須要壓縮處理的,直接拷貝過去便可。生成的rev-manifest.json文件以下:
{ "base/cal.js": "base/cal-2e41f44581.js", "base/require-config.js": "base/require-config-3c5aeda076.js", "controller/index.js": "controller/index-d14ed3eca8.js" }
gulp.task('htmlmin',function () { var options = { removeComments: true,//清除HTML註釋 //collapseWhitespace: true,//壓縮HTML removeEmptyAttributes: true,//刪除全部空格做屬性值 <input id="" /> ==> <input /> minifyJS: true,//壓縮頁面JS minifyCSS: true//壓縮頁面CSS }; gulp.src('src/html/**/*.html') .pipe(htmlmin(options)) .pipe(rev()) .pipe(gulp.dest('dist/html')) });
過程省略一百字。。。
gulp.task('replaceURL', function(){ gulp.src(['dist/html/**/*.html']) .pipe(replace('../css', '/css')) .pipe(replace('../js', '/js')) .pipe(replace('/src', '/dist')) .pipe(gulp.dest('dist/html')); gulp.src(['dist/css/**/*.css']) .pipe(replace('../css', '/css')) .pipe(replace('../js', '/js')) .pipe(replace('/src', '/dist')) .pipe(gulp.dest('dist/css')); gulp.src(['dist/js/**/*.js']) .pipe(replace('../css', '/css')) .pipe(replace('../js', '/js')) .pipe(replace('/src', '/dist')) .pipe(gulp.dest('dist/js')); });
過程就是替換全部文件的相對路徑爲絕對路徑。
gulp.task('revUrl', function() { gulp.src(['rev/{css,img,js}/*.json', 'dist/html/**/*.html']) //- 讀取 rev-manifest.json 文件以及須要進行css名替換的文件 .pipe(revCollector()) //- 執行文件內css名的替換 .pipe(gulp.dest('dist/html')); //- 替換後的文件輸出的目錄 gulp.src(['rev/{css,img,js}/*.json', 'dist/css/**/*.css']) .pipe(revCollector()) .pipe(gulp.dest('dist/css')); gulp.src(['rev/{css,img,js}/*.json', 'dist/js/**/*.js']) .pipe(revCollector()) .pipe(gulp.dest('dist/js')); });
打開dist/html/index.html
<!doctype html> <html> <head> <title>requirejs</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="/css/base/base-c1e638e1f6.css"> <link rel="stylesheet" type="text/css" href="/css/controller/index-1454781768.css"> <!--[if IE]> <link rel="stylesheet" type="text/css" href="/csstest/main.css"/> <![endif]--> </head> <body> <div class="main border-grey" id="name1"> <div class="wrapper">未加載 index.js</div> </div> <script type="text/javascript" src="/js/base/require-config-3c5aeda076.js" defer="true"></script> <script data-main="/js/controller/index-d14ed3eca8.js" src="/js/lib/require.min.js" defer="true"></script> </body> </html>
能夠看到,css和js文件引用的路徑都替換成了相應rev-manifest.json中的值。
訪問一下頁面:
控制檯也顯示資源文件引用正常:
修改base.scss中body{font-size: 14px;}的字體爲20px,從新執行gulp,再截圖看下控制檯:
能夠發現,除了base.css引用變了以外,其餘保持不變。
按上面的步驟走完,gulp已經知足項目基本須要了,但仍存在兩點問題:
上面這3點,將在下一節中詳解。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
歡迎轉載,轉載請註明做者:飄飛的夏秋 和出處 http://www.cnblogs.com/chenchenghua/p/5953767.html