Gulp(1): 打包壓縮小程序 小程序瘦身


在當今前端技術愈加成熟的環境下,小程序的壓縮瘦身,相對變得容易多了。
webpack 中一切皆模塊,基於其豐富的自由配置,會從入口處對所有依賴進行整合並重新分配,本是一個極大的優勢,但在小程序中卻也是一個弊端。
相比較而言,gulp 任務規划,功能明確,運行可控,對於小程序這樣的對文件索引更嚴格的模式下,更顯得得心應手。

1. 安裝 gulp

選擇一個目錄,安裝 gulp

npm i -D gulp

創建配置文件 gulpfile.js,輸入:


function defaultTask(cb) {
  // task
  console.log('hello gulp')
  cb();
}
exports.default = defaultTask

在 package.json 中添加腳本命令 "dev": "gulp" , 然后命令行執行 npm run dev,就會執行默認任務,並打印 ' hello gulp '。
創建文件夾 demo,並在其中創建 test.js、common.css 等測試文件,填充基本內容。為后續操作做准備。

2. 基本配置

可以說,gulp是面向任務的工具,所有功能都由一個個任務組合而成,每個任務都是一個函數。
處理小程序中的文件,最主要的api 是 src()讀取文件流、 dest()輸出文件流、 pipe()處理數據流。
如下,先安裝 gulp-babelgulp-uglify兩個插件用於轉義es6 並壓縮js。

npm i -D gulp-babel @babel/core @babel/preset-env gulp-uglify

gulpfile.js 中改為:


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

exports.default = function() {
  return src('demo/*.js')
    .pipe(babel())
    .pipe(uglify())
    .pipe(dest('dist/'));
}

src()dest()都是接受 glob 參數,傳入地址目錄,此處不再展開。
值得注意的是,gulp 不支持同步任務,意味着,所有的任務必須使用 callback 或 async函數,或返回 stream、promise、event emitter、child process、observable。若在使用中出現 "Did you forget to signal async completion?" 警告,表示未使用前面提到的返回方式。
執行 npm run dev即可看到,同級目錄內出現 dist 文件夾,內部包含前面提到的測試文件的壓縮版js。
隨后引入 gulp-clean-css用於壓縮 wxss 文件,gulp-htmlmin用於壓縮 wxml,同時需要 gulp-iflazypipe 進行條件編譯,對js、wxss、wxml 文件進行分別處理。

npm i -D gulp-clean-css gulp-htmlmin gulp-if lazypipe

gulp-if 第一個參數為判斷條件,第二參數為判斷為 true 時,執行的任務,第三參數為判斷為 false 時,執行的任務,可不傳。
對js的處理需要兩步操作,首先進行 babel轉換,然后 uglify壓縮,在這里就需要用 lazypipe 把這兩個操作轉化為操作鏈。
注意,lazypipe 實例在調用 pipe() 時,pipe 中函數的參數,需緊跟 pipe 中函數的后面:
lazypipe().pipe(fn[, arg1[, arg2[, ...]]])

Vinyl 是描述文件的元數據對象,同樣存在於文件流中,可以使用 Vinyl api 獲取文件流的文件類型,如:file.extname = '.js';


const { src, dest} = require('gulp');
const gulpif = require('gulp-if');
const lazypipe = require('lazypipe');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
const cleanCss = require('gulp-clean-css');
const htmlmin = require('gulp-htmlmin');

const isJS = (file) => file.extname === '.js';
const isCSS = (file) => file.extname === '.wxss' || file.extname === '.css';
const isWXML = (file) => file.extname === '.wxml';

const jsChannel = lazypipe()
  .pipe( babel, { presets: ['@babel/env'] } )
  .pipe( uglify, {
    // 壓縮配置
    compress: {
      drop_console: true,
    },
    // 輸出配置
    output: {
      comments: false,    // 移除注釋
    },
    toplevel: false,    // 混淆最高作用域中的變量和函數名
  })

async function fileHandle() {
  src('demo/**/*', {
    allowEmpty: true
  })
  // 分別處理 js、wxss
  .pipe(gulpif( isJS, jsChannel()))
  .pipe(gulpif( isCSS, cleanCss()))
  // 取消對 wxml 的處理,<input></input>等與 html 中存在沖突
  // .pipe(gulpif( isWXML, htmlmin({
  //   caseSensitive: true,    // 大小寫敏感
  //   removeComments: true,   // 刪除HTML注釋
  //   keepClosingSlash: true, // 單標簽上保留斜線
  // })))
  .pipe(dest('dist/'))
}
exports.default = fileHandle

引入 del 庫,
npm i -D del
在編譯前,清空輸出目錄,這里涉及到順序執行,所以還需使用 gulp.series組合任務。

const { series} = require('gulp');
const del = require('del');

// 清理
async function clean(){
  await del(output);
}

exports.clean = clean
exports.default = series( clean, fileHandle)

另外,把輸入輸出目錄 提取出來,統一配置
最后,gulpfile.js 源碼如下:


const { src, dest, series} = require('gulp');
const gulpif = require('gulp-if');
const lazypipe = require('lazypipe');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
const del = require('del');
const cleanCss = require('gulp-clean-css');
const htmlmin = require('gulp-htmlmin');

// const entry = '../wx'    // 小程序地址
const entry = './demo'      // 示例地址
const output = './dist'     // 輸出目錄


const isJS = (file) => file.extname === '.js';
const isCSS = (file) => file.extname === '.wxss' || file.extname === '.css';
const isWXML = (file) => file.extname === '.wxml';

const jsChannel = lazypipe()
  .pipe( babel, { presets: ['@babel/env'] } )
  .pipe( uglify,  )

// 清理
async function clean(){
  await del(output);
}
async function fileHandle() {
  src([ 
    `${entry}/**/*`,
    `!${entry}/**/.*`,
    `!${entry}/node_modules/*`,
    `!${entry}/**/*.md`,
  ], {
    allowEmpty: true
  })
  // 分別處理 js、wxss、wxml
  .pipe(gulpif( isJS, jsChannel()))
  .pipe(gulpif( isCSS, cleanCss()))
  // 取消對 wxml 的處理,<input></input>等與 html 中存在沖突
  // .pipe(gulpif( isWXML, htmlmin({
  //   caseSensitive: true,    //  大小寫敏感
  //   removeComments: true,   // 	刪除HTML注釋
  //   keepClosingSlash: true, // 單標簽上保留斜線
  // })))
  .pipe(dest(output))
}

exports.clean = clean
exports.default = series( clean, fileHandle)

package.json

{
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/preset-env": "^7.11.0",
    "del": "^5.1.0",
    "gulp": "^4.0.2",
    "gulp-babel": "^8.0.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-htmlmin": "^5.0.1",
    "gulp-if": "^3.0.0",
    "gulp-uglify": "^3.0.2",
    "lazypipe": "^1.0.2"
  },
  "scripts": {
    "dev": "gulp",
    "clean": "gulp clean"
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM