自動化構建和構建工具Gulp

自動化構建

什么是構建
  • 構建是將源代碼轉換成生產代碼的過程
為什么構建
  • 一些代碼需要編譯(CSS,JS), 保證瀏覽器的兼容性
    將 Less 或 Sass 轉換成 CSS
    將 ES6+ 的新語法轉成 ES5
  • 有些代碼需要壓縮(CSS,JS,HTML,圖片等)
    壓縮之后的代碼體積更小,加載更快,節省帶寬
  • 有些代碼需要做格式化校驗,統一代碼風格
  • 構建過程:源代碼通過編譯、壓縮、格式化等等轉化成生成代碼
什么是自動化構建
  • 不管是代碼壓縮還是 less 轉換,通過手動方式進行工作量巨大,自動化構建是指將手動構建任務,進行排列組合,然后通過命令(或工具)自動執行的過程
  • 實現自動化構建最簡單的方式是 npm scripts (npm 腳本)
npm scripts
  • npm 在 package.json 文件里面,使用 scripts 字段定義腳本命令
{
  "scripts": {
    // 命令名稱: 任務
    "foo": "node bar.js"
  }
}
# `scripts` 字段是一個對象。它的每一個屬性,對應一段腳本。比如,`foo` 命令對應的腳本是`node bar.js`。

# 命令行下使用 npm run <命令>,就可以執行這段腳本。
$ npm run foo
# 等同于執行
$ node bar.js
  • npm 腳本就是 Shell 腳本,因為可以使用 Shell 通配符
"style": "lessc *.less"
"style": "lessc **/*.less"

* 表示任意文件名,** 表示任意一層子目錄

  • 執行順序
    如果是并行執行(即同時的平行執行),可以使用 & 符號
{
  "scripts": {
    "parallel": "node task1.js & node task2.js & node task3.js"
  }
}

如果是串行執行(前一個任務成功后,才執行下一個任務),可以使用 && 符號

{
  "scripts": {
    "series": "node task1.js && node task2.js && node task3.js"
  }
}

但是,& 符號在 Windows 操作系統下不起作用。此時,我們可以借助插件,在 Windows 下實現并行操作:npm-run-all

構建樣式文件
  • 構建樣式文件就是將開發環境下的 JavaScript 源代碼,轉成線上環境使用的代碼。這里的構建任務可能有多個。

  • 在開發過程中,經常使用 ES6+ 新特性時,一些舊的瀏覽器,不支持 JS 的新語法。所以,在項目上線之前,就需要將新的語法特性解析成兼容性更好的 ES5 。最常用的編譯工具是 Babel

  • Babel https://babeljs.io/

# 安裝 babel核心,Babel客戶端
npm i -g babel-core babel-cli

# 安裝轉碼規則
npm i -g babel-preset-env

# 在項目根目錄下,新建 .babelrc 文件(注意文件名前有一個點),并添加轉換規則
{
    "presets": [
      "env"
    ],
}

# 通過 babel 編譯單個 j s文件
babel input.js --out-file output.js
# 或者
babel input.js -o output.js
    
# 通過 babel 編譯整個目錄
babel js --out-dir scripts
# 或者
babel js -d scripts

# 在 package.json 中,添加 babel 解析命令
"scripts": {
    "script": "babel js -d scripts",
}

# 執行命令(自動編譯)
npm run script

# 如果 Babel 是局部安裝。則babel 的可執行路徑是:./node_modules/.bin/babel命令需要做相應的調整
# babel js -d scripts    ===>   ./node_modules/.bin/babel js -d scripts
  • 添加壓縮命令
# 在 package.json 中,添加 babel 解析和壓縮命令
"scripts": {
    "script": "babel js -d scripts && minify scripts/main.js > scripts/script.min.js",
}
代碼格式校驗

使用 ESLint 來檢測 JavaScript 代碼

# 配置檢測規則
{
    "env": {
        "browser": true,
        "commonjs": true,
        "es2021": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": 12
    },
    "rules": {
        "indent": [ "error", 2 ],       # 使用兩個空格縮進
        "quotes": [ "error", "double" ] # 使用雙引號包裹字符串
    }
}
StyleLint

StyleLint 是檢測 CSS 代碼格式的插件
官網:https://stylelint.io/

  • 在項目的根目錄下,創建 .stylelintrc.json 文件,添加如下配置
{
  "extends": "stylelint-config-standard",
  "rules": {
    # 除了使用 stylelint-config-standard,我們還可以在 rules 字段中自定義校驗規則
    "block-no-empty": true # 代碼塊不能為空
  }
}

自動化構建工具Gulp

自動化構建工具,可以幫我們又快又好的完成自動化構建任務。相比有 npm scripts,自動化構建工具,功能更為強大。更簡單易學

  • Gulp 的構建是基于內存實現的,其構建速度比 Grunt 快,而且,Gulp 的生態也很完善,插件質量很高。目前最為流行

Gulp

Gulp 是基于 的自動化構建系統。

  • Gulp 的特點:
  • 任務化
    所有的構建操作,在 gulp 中都稱之為任務
  • 基于流
    gulp 中所有的文件操作,都是基于 方式進行 ( Gulp有一個自己的內存,通過指定 API 將源文件流到內存中,完成相應的操作后再通過相應的 API 流出去)
Gulp 使用
  1. 使用 Gulp 之前,先在全局安裝 gulp-cli
    命令:npm i -g gulp-cli
  2. 初始化項目
    npm init --yes
  3. 安裝 Gulp 包
# 安裝 gulp 包,作為開發時依賴項
npm i gulp -D
  1. 創建 gulpfile 文件
    gulpfile 文件是項目根目錄下的 gulpfile.js在運行 gulp 命令時會被自動加載。在這個文件中,你經常會看到類似 src()dest()series()parallel() 函數之類的 Gulp API,除此之外,純 JavaScript 代碼或 Node.js 模塊也會被使用。任何導出( exports )的函數都將注冊到 Gulp 的任務(task)系統中

報錯:The following tasks did not complete: task
Did you forget to signal async completion?
解釋:在最新的 Gulp 中,取消了同步代碼模式。約定每個任務都必須是一個異步任務
解決:再函數參數中,設定回調函數(回調函數是異步操作)

  1. 在 gulpfile.js 中注冊 Gulp 任務

  2. 運行 Gulp 任務

# 運行 foo 任務
# 如需運行多個任務(task),可以執行 gulp <task> <othertask>
gulp foo
  1. 創建默認任務
# 默認任務的名稱是 default
exports.default = cb => {
    console.log('default task is running')
    
    cb()
}

# 運行默認任務, gulp 后無需指定任務名稱
gulp # 效果等同于 gulp default
組合任務
  • 按順序執行,請使用 series() 方法
  • 并行執行,可以使用 parallel() 方法將它們組合起來
const gulp = require('gulp')
# 串行方式執行任務,先執行task1, 然后執行task2, 然后執行task3
exports.foo = gulp.series(task1, task2, task3)

# 并行方式執行任務,同時執行task1,task2,task3
exports.bar = gulp.parallel(task1, task2, task3)

# 執行命令
gulp foo # 串行執行
gulp bar # 并行執行
文件操作

gulp 暴露了 src()dest() 方法用于處理計算機上存放的文件。在代碼構建過程中,需要將源文件,寫入到目標目錄。

# 通過 解構 的方式引入 gulp 中的函數
const { src, dest } = require('gulp')

exports.default = () => {
  // 文件操作
  // 將 src/styles 目錄下的 main.css 文件,復制到 dist/styles 目錄下
  return src('src/styles/main.less', { base: 'src' }).pipe(dest('dist'))
}

# 執行命令
gulp default
# 或直接執行
gulp

樣式文件構建

  • 對樣式文件進行轉換、壓縮、重命名。
  • 添加 CSS 屬性前綴的操作,之前是通過程序員手動添加的。這類重復性操作,我們可以通過插件完成。
  • 在 Gulp 中 gulp-autoprefixer 插件,可以根據 caniuse.com 上提供的 CSS 兼容性數據,自動地給 CSS 屬性加前綴,以保證 CSS 代碼的兼容性問題。

腳本文件構建

  • 對 JS 代碼進行 Babel 轉換和壓縮

頁面模板構建

  • 對 html 文件的構建,主要指壓縮 html 文件。其中 gulp-htmlmin 插件可以完成壓縮任務
  • gulp-htmlmin 插件的解析器是:https://github.com/kangax/html-minifier
  • 我們可以將 style,script 和 html 任務組合起來。因為 style,script 和 html 之間沒有明確的前后順序,所以,可以進行并行執行,并行執行可以提升構建效率
# 引入 parallel 函數
const { src, dest, parallel } = require('gulp')

// 任務的并行執行
const build = parallel(style, script, html)

module.exports = {
  build
}

# 運行命令
gulp build

圖片(字體)文件轉換

  • 對圖片文件的構建,主要是指圖片的壓縮。通過 gulp-imagemin 插件可以完成圖片的壓縮任務
報錯處理:
gulp-imagemin: Couldn't load default plugin "gifsicle"
gulp-imagemin: Couldn't load default plugin "optipng"
原因:npm 安裝依賴失敗
解決:
1. 配置 hosts
2. 重新安裝 npm i gulp-imagemin -D

文件清除

  • 有時候,我們需要刪除一些構建的歷史文件,然后再重新構建。刪除文件操作,可以通過 del 插件完成

開發服務器

  • 通過web服務器插件,將 dist 下的代碼,發布到瀏覽器查看效果。發布web服務的插件有很多。推薦功能強大的 browser-sync
# 安裝 browser-sync 插件
npm i browser-sync -D

# 在 gulpfile.js 中添加開發服務器的內容
const browserSync = require('browser-sync')
const bs = browserSync.create()

// 聲明 web 服務構建任務
const serve = () => {
  bs.init({
    server: {
      baseDir: './dist' // 指定服務啟動的目錄
      routes: {
        '/node_modules': 'node_modules' // 引入 Bootstrap 是設置路徑映射
      }
    }
  })
}

module.exports = {
  clean,
  build,
  serve
}

# 運行命令,然后在瀏覽器查看效果
gulp serve
  • 服務發布成功后,之前學習的內容,也可以拿過來使用,例如:Bootstrap
  1. 下載插件
# 因為 Bootstrap 和 jQuery 上線之后還要使用,所以,采用 -S 參數(上線依賴)
npm i bootstrap@3.4.1 jquery -S
  1. 引入文件
    Bootstrap 和 jQuery 下載后,文件位于當前目錄的 node_modules 下
# 在 HTML 中引入
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css">
......
<script src="/node_modules/jquery/dist/jquery.min.js"></script>
<script src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
  • 引入路徑,需要在 browser-sync 中,通過 routes 參數映射后,才能正確引入
  1. 使用 Bootstrap

監視變化(熱更新)

  • 監視 src 下文件變化的頁面更新,代碼一旦更新,瀏覽器上的頁面效果也隨之更新。

  • 此時,我們需要監視兩個目錄的變化,一個是 dist 目錄,一個是 src 目錄。

  • 監視 dist 目錄下代碼的變化

    # 通過 browser-sync 中的 files 字段
    files: 'dist/**'
    
  • 監視 src 目錄下代碼的變化

    # 通過 gulp 中的 watch 函數
    watch(被監視的文件,對應的任務)
    

最終的代碼如下:

# 在 gulpfile.js 中添加監視文件變化的代碼
const serve = () => {
  // watch(被監視的文件,對應的任務)
  watch('src/index.html', html)
  watch('src/styles/*.less', style)
  watch('src/js/*.js', script)
  watch('src/images/**', image)

  // 初始化服務
  bs.init({
    notify: false,      // 禁用瀏覽器右上角的 browserSync connected 提示框
    files: 'dist/**',   // 監視 dist 下 文件的變化,然后在瀏覽器上實時更新
    server: {
      baseDir: './dist', // 指定服務啟動的目錄
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}

// 組合任務
const build = parallel(style, script, html, image)
const dev = series(clean, build, serve)

// 導出任務
module.exports = {
  build,
  dev,
  serve
}

# 運行命令,更新代碼文件,查看頁面變化
gulp dev

此時,不管是 dist 目錄下,還是 src 目錄下。只要代碼發生變化,我們就可以在瀏覽器上實時看到效果。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容