Gulp&Webpack搭建屬於本身的特性化前端腳手架

前言

以前看了不少教程,好比vue的腳手架,gulp的腳手架和大牛本身寫的腳手架。發現沒有什麼是銀彈可以知足公司業務的須要又可以開發的爽。因此結合公司業務的特性,本身動手用gulp和webpack寫了一套適合我司的腳手架。css

使用範圍

  • 專題等靜態頁面多
  • 後臺主導邏輯業務,前端主導交互等
  • 須要整合es6,scss,eslint等

上面只列出了三點。其實適用範圍還有挺多。html

技術棧

  • 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文件的生成。vue

babel

這個沒什麼好說的,babel也提供了cli的形式,但這裏整合進了webpack當中。webpack

gulp-sourcemaps&gulp-sass&gulp-postcss&autoprefixer

這些都是用來處理sass的相關,好比 sass的編譯,css的瀏覽器兼容性處理,css的sourcemap對應。git

browser-sync

webpack也提供了靜態服務器而且支持增量刷新,可是這裏我選擇使用browser-sync提供了靜態服務器。 browser-sync能夠快速的搭建起一個靜態服務器而且支持api級別的接口刷新。因此我能夠很方便的去自動或者手動調用刷新頁面功能es6

eslint&eslint-config-alloy

這裏使用的是騰訊alloy團隊的eslint檢測配置,我的比較喜歡此方案。github

gulp

最後說說gulp,全部的模塊都是由gulp來主導而且粘合的。爲何這麼說。 由於全部的模塊都不知道啥時候去調用啥時候去作該作的事情,那麼這裏就用到了gulp.watch和gulp.src。 簡單來個例子web

/**
 *
 * 監聽文件
 *
 */
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。npm

使用問題

  1. gulp-webpack編譯每次都是從新編譯

gulp-webpack每次調用webpack都須要從新編譯,因此時間會很長很長很長。其實還好 我的測試中,webpack增量編譯時間爲1s的話,gulp-webpack編譯時間爲2s-3s左右。若是對時間不是特別敏感的能夠忽略。 固然這個問題仍是有解決方案的,也是以前看的某篇文章提出的 使用proxy機制, webpack的增量編譯刷新調動browserSync的刷新。 這樣一來能夠作到同步刷新 而且不適用gulp-webpack來從新編譯轉而使用webpack的增量編譯和靜態服務器功能。固然具體怎麼實現尚未研究 可是能夠得出的結論就是 不難。

  1. 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`;
複製代碼

使用額外的配置文件來作到按需編譯和加載

  1. 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';
複製代碼
  1. 報錯退出機制

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

相關文章
相關標籤/搜索