Gulp+Babel實現ES6項目工程構建&踩坑記錄

前言

近期在開發Hybird新需求時用到了地圖,而因爲地圖的定位地址是異步拿到結果的,而多個點與定位地址的距離計算需要等到定位結束,所以這裏可以用async函數來做,但是以前項目用到gulp只停留在ES5階段,導致ES6語法打包出來的js在部分系統低的安卓機上不支持而報錯,所以這裏需要babel編譯

一、引入Babel進行ES6編譯

項目以前用的GulpV3,也趁這次終於升級到V4了

1. 依賴安裝

npm install -D gulp-babel  @babel/core @babel/preset-env

2. babel在gulp中的簡單配置

const gulp = require('gulp')
const {task,dest,src} = require('gulp')
const babel = require('gulp-babel')

task('testBabel', function () {
    let step =  src('./js/*.js')
                .pipe(babel({
                    presets:['@babel/preset-env']
                }))
                .pipe(dest('./test'))
    return step;
})

3. 拿一個js來測試下

// test.js
const a = 1;
const b = 2;

let foo = function () {
   return a+b
}
async function test() {
    let c = 10;
    let d = await foo() + c
    return d;
}
test().then(res => {
    console.log(res)
})
  • 通過運行gulp testBabel可以看到test文件夾下出現了(ES6轉ES5)編譯後的test.js文件。
  • 出現問題:用一個html來引用剛編譯後的js運行看,發現報錯Uncaught ReferenceError: regeneratorRuntime is not defined
    • 原因:在test.js中引用了async函數,而這是需要ES6新API部分,babel默認情況下是隻轉譯語法,而對新API的支持需要額外加入polyfill,現在polyfill其實有三種類型,區別可以看這篇文
    • 解決:
    • npm install -D @babel/plugin-transform-runtime,
    • npm install -S @babel/runtime
task('test', function () {
    let step =  src('./js/*.js')
                .pipe(babel({
                    presets: ['@babel/preset-env'],
                    plugins: ['@babel/plugin-transform-runtime']
                }))
                .pipe(dest('./test'))
    return step;
})

4. 再次測試,發現這次報錯不一樣了,Uncaught ReferenceError: require is not defined.

  • 原因:babel編譯後的代碼是遵循commonJS的模塊化規範的,所以這裏還需要引用一個模塊化bundler。
  • 解決:引入 browserify
npm install -D browserify vinyl-buffer vinyl-source-stream
const gulp = require('gulp')
const {task,dest,src,series} = require('gulp')
const babel = require('gulp-babel')
const browserify = require('browserify')
const buffer = require('vinyl-buffer')
const stream = require('vinyl-source-stream')

task('test', function () {
    let step =  src('./js/*.js')
                .pipe(babel({
                    presets: ['@babel/preset-env'],
                    plugins: ['@babel/plugin-transform-runtime']
                }))
                .pipe(dest('./test'))
    return step;
})
task('browserify', function (cb) {
    return browserify({
        entries: './test/test.js',
        debug: true
    })
        .bundle()
        .on('error', function (error) {
            console.log(error.toString())
        })
        .pipe(stream('test.js'))
        .pipe(buffer())
        .pipe(dest('./test/testBundle'));
    cb() //這一句其實是因爲V4不再支持同步任務,所以需要以這種方式或者其他API中提到的方式
})

exports.build = series('test','browserify') //series是gulpV4中新方法,按順序執行

5. 再次執行,瀏覽器終於不報錯啦~~

  • 但實際項目中,往往用到gulp也不是單文件入口編譯,所以在browserify的文件入口entry處可以通過編寫讀文件腳本的方式來對一個文件夾下的js進行模塊化打包
  • 例:
let enviroment = process.env.NODE_ENV || 'development'
const folder = {
    src:'src/',
    dist:'webapp/',
    temp:'./.tmp/'
}
// 文件讀取
const es = require('event-stream')
const fs = require('fs')
const join = require('path').join
function findSync(startPath){
    let result = []
    function finder(path){
        let files = fs.readdirSync(path)
        files.forEach(val=>{
            let fPath = join(path,val)
            let stats = fs.statSync(fPath)
            if(stats.isDirectory()) finder(fPath)
            if(stats.isFile()) result.push({path:'./'+fPath,name:val})
        })
    }
    finder(startPath)
    let res = result.map(item=>{
        item.path = item.path.replace(/\\/g,'/')
        return item
    })
    return res
}
// 模塊化打包
task('browserify',function(cb){
    let files = findSync(folder.temp+'js')
    var task = files.map(entry=>{
        return browserify({
            entries:entry.path,
            debug:true
        })
            .bundle()
            .on('error',function(error){
                console.log(error.toString())
            })
            .pipe(stream(entry.name))
            .pipe(buffer())
            .pipe(dest(folder.dist+'js'))
    })
     es.merge.apply(null,task)
    cb()  
})

二、整體Gulp工程構建

1. 一些常用gulp插件

  • gulp-htmlclean:HTML代碼壓縮
  • gulp-rev,gulp-rev-collector:爲資源加MD5後綴(防瀏覽器緩存)
  • gulp-useref:對HTML引用的資源進行合併(通過特定標籤註釋)
  • gulp-clean-css:CSS代碼壓縮
  • gulp-uglify:JS壓縮
  • gulp-imagemin:圖片壓縮
  • gulp-less:less預編譯
  • gulp-connect:本地網絡服務
  • gulp-postcss&autoprefixer:CSS自動前綴補全
  • gulp-clean:文件清理

2. 最後附上完整代碼,方便複用啦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章