前言
之前看了很多教程,比如vue的腳手架,gulp的腳手架和大牛自己寫的腳手架。發現沒有什麼是銀彈能夠滿足公司業務的需要又能夠開發的爽。所以結合公司業務的特性,自己動手用gulp和webpack寫了一套適合我司的腳手架。
使用範圍
- 專題等靜態頁面多
- 後臺主導邏輯業務,前端主導互動等
- 需要整合es6,scss,eslint等
上面只列出了三點。其實適用範圍還有挺多。
技術棧
- webpack^3
- gulp-webpack^1.5
- gulp-pug^3.3
- gulp^3.9
- eslint^4
- eslint-config-alloy^1.4
- babel^6.5
- gulp-postcss^6.2
- autoprefixer^6.4
- browser-sync^2.1
- gulp-sass^2.3
當然還有一些就不一一列出了,這裡只列出幾個主要的模組 下面來解釋一下上述模組對應的功能。s
webpack
我個人是比較討厭webpack做除了js以外的事情,包括打包css,copy等。 我不否認webpack的強大,但是我還是更希望術業有專攻,webpack只負責js相關的事情就好。 所以webpack負責的範圍為 es6->es5,eslint的檢測,js的sourcemap檔案的生成。
babel
這個沒什麼好說的,babel也提供了cli的形式,但這裡整合進了webpack當中。
gulp-sourcemaps&gulp-sass&gulp-postcss&autoprefixer
這些都是用來處理sass的相關,比如 sass的編譯,css的瀏覽器相容性處理,css的sourcemap對應。
browser-sync
webpack也提供了靜態伺服器並且支援增量重新整理,但是這裡我選擇使用browser-sync提供了靜態伺服器。 browser-sync可以快速的搭建起一個靜態伺服器並且支援api級別的介面重新整理。所以我可以很方便的去自動或者手動呼叫重新整理頁面功能
eslint&eslint-config-alloy
這裡使用的是騰訊alloy團隊的eslint檢測配置,個人比較喜歡此方案。
gulp
最後說說gulp,所有的模組都是由gulp來主導並且粘合的。為什麼這麼說。 因為所有的模組都不知道啥時候去呼叫啥時候去做該做的事情,那麼這裡就用到了gulp.watch和gulp.src。 簡單來個例子
/**
*
* 監聽檔案
*
*/
gulp.task("watch", () => {
let bs = browserSync.init({
server: {
baseDir: "./",
directory: true,
},
open: false,
ui: {
port: 3008,
weinre: {
port: 3009
}
},
port: devConf.gulp.webPort?devConf.gulp.webPort:3012,
ghostMode: false
});
gulp.watch(["dev/jade-html/**/*.pug", "dev/jade-component/**/*.pug"], ["compile:pug"]);
gulp.watch(["dev/js/**/*.js"], ["compile:js"]);
gulp.watch(["dev/sass/**/*.scss"], ["compile:sass"]);
gulp.watch(["dev/img/**/*.*", "dev/lib/**/*.*"], ["copy"]);
});
複製程式碼
比較簡單,大意就是監聽某些檔案變動的時候執行對應的task。
使用問題
- gulp-webpack編譯每次都是重新編譯
gulp-webpack每次呼叫webpack都需要重新編譯,所以時間會很長很長很長。其實還好 個人測試中,webpack增量編譯時間為1s的話,gulp-webpack編譯時間為2s-3s左右。如果對時間不是特別敏感的可以忽略。 當然這個問題還是有解決方案的,也是之前看的某篇文章提出的 使用proxy機制, webpack的增量編譯重新整理調動browserSync的重新整理。 這樣一來可以做到同步重新整理 並且不適用gulp-webpack來重新編譯轉而使用webpack的增量編譯和靜態伺服器功能。當然具體怎麼實現還沒有研究 但是可以得出的結論就是 不難。
- pug,sass檔案過多每次都編譯出額外的檔案
這個什麼意思呢?看程式碼說話
gulp.task("compile:sass", (event) => {
return gulp.src('dev/sass/output/**/*.scss')
//.pipe(changed("dist/css")) disabled changed sass需要全部編譯..
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on("error", sass.logError))
.pipe(gulpif(extBase64File,base64({
maxImageSize: 15*1024, // bytes 15KB
})))
.pipe(postcss([autoprefixer()]))
.pipe(sourcemaps.write("./"))
.pipe(gulp.dest("dist/css"))
.pipe(gulp.dest(copyCssPath))
.on("finish", () => {
browserReload()
})
});
複製程式碼
這裡如果編譯的話 每次都會把output下面所有的scss檔案編譯出來,同理 編譯pug的時候也是一樣會把某個資料夾下面的所有pug全部編譯出來。當然解決辦法也很簡單
配置檔案,沒錯,再使用額外的配置檔案,比如
const devConf=require("./dev-conf");
let compilePugFile= devConf.gulp.compilePugFile?devConf.gulp.compilePugFile:["dev/jade-html/**/*.pug"];
let compileSassFile= devConf.gulp.compileSassFile?devConf.gulp.compileSassFile:["dev/sass/output/**/*.scss"];
let copyJsPath=devConf.gulp.copyJsPath?devConf.gulp.copyJsPath:`/public/dist/js`;
let copyCssPath=devConf.gulp.copyCssPath?devConf.gulp.copyCssPath:`/public/dist/css`;
let copyImgPath=devConf.gulp.copyImgPath?devConf.gulp.copyImgPath:`/public/img`;
複製程式碼
使用額外的配置檔案來做到按需編譯和載入
- prod和dev如何區分。
這個其實很簡單 可以使用npm run 也可以使用gulp的多個任務方式
gulp.task('default::production',['set-env::production','watch']);
/**
* 設定環境變數
*/
gulp.task('set-env::production',()=>{
webpackEnv='production';
return Promise.resolve(true);
});
複製程式碼
需要dev模式那麼直接 gulp就好 需要生產模式就 gulp default::production 這裡的設定變數可以通過process.env來設定,這樣就可以在全域性拿到引數了。
process.env.NODE_ENV = 'dev'||'prod';
複製程式碼
- 報錯退出機制
gulp的每次報錯都會導致gulp退出,比如呼叫gulp-webpack編譯js的時候 某個js錯誤導致整個gulp退出, 當然解決辦法也很簡單
const plumber = require('gulp-plumber');
const webpackFile=require("./webpack.config.js");
gulp.task("compile:js", () => {
return gulp.src("dev/js/main.js")
.pipe(plumber({errorHandler:function () {
}}))
.pipe(webpack(webpackFile({env:webpackEnv})))
.pipe(gulp.dest("dist/js/"))
.pipe(gulp.dest(copyJsPath))
.on("finish", () => {
browserReload()
})
});
複製程式碼
使用gulp-plumber便可以解決問題了, 因為webpack自帶錯誤提示功能 所以不需要gulp-plumber再次報錯, 這裡就把errorHandler給定義了空函式不做處理。
改進
基本上說到這裡整個方案就差不多了。 這一套方案的好處就是 html,css,js分離並且互不影響。 html,css,js都使用了代替品來方便開發 比如html使用了pug(說pug不好的同學,你們有巢狀過10層以上的html嗎?),css使用了sass,js使用了es6,並且三者可以快速替換和代替 比如 我哪天不想使用pug了 那麼可以快速使用ejs等其他模板 只需要改改gulp的task, 哪天我想使用vue了 那麼只需要改改webpack的配置檔案,並且增加gulp.watch範圍就可以了。 是不是聽著很強大?難道就沒什麼弊端麼?
答案是....沒有...哈哈哈哈 有點狂。 不過其實還是有很多問題的,比如webpack的效能,在檔案量大的話 其實會編譯的比較久,會影響開發效率,這個問題在後期是不可忽視的。 耦合過大也是個問題,所有的編譯都是依靠檔案目錄來做分配的,如果某個目錄變了那麼很多東西都需要修改重來。 等等... 不過後面再慢慢改進吧,畢竟從一開始自己搭建腳手架到現在公司中穩定使用也經歷了重構—>改版->抽離->放棄(???什麼鬼)。
這裡給出一個vue2.0的demo