前言

前端發展越來越複雜,各種預處理器的使用,導致實際運行代碼不同於開發代碼,除錯(debug)變得困難重重,常見的例子為 Sass/SCSS、CoffeeScript 等預處理器,通常代碼出錯時,編譯器只會告訴你第幾行第幾列出現錯誤,但這對於編譯後的代碼是毫無作用的,我們需要得知的是尚未編譯代碼片段的錯誤,並不是以編譯代碼片段的錯誤;此篇將利用 gulp-sourcemaps 套件生成 SourceMap 文件改善此問題。

  • gulp-sourcemaps 安裝
  • gulp-sourcemaps 基本使用
  • gulp-sourcemaps 可傳遞選項
  • 補充:gulp-concat 生成 sourcemap
  • gulp-sourcemaps 安裝

    套件連結: gulp-sourcemaps

    1
    $ npm install gulp-sourcemaps

    我們可以使用 gulp-sourcemaps 套件生成 SourceMap 文件,不需要下載其他相依套件,開箱即可使用。

    gulp-sourcemaps 基本使用

    初始專案結構:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    gulp-demo/

    ├─── node_modules/
    ├─── source/
    │ │
    │ └─── scss/
    │ │
    │ └─── base
    │ │
    │ └─── _reset.scss
    │ │
    │ └─── component
    │ │
    │ └─── _button.scss
    │ │
    │ └─── helpers
    │ │
    │ └─── _variables.scss
    │ │
    │ └─── layout
    │ │
    │ └─── _footer.scss
    │ │
    │ └─── all.scss # SCSS 主檔案

    ├─── gulpfile.js # Gulp 配置檔案
    ├─── package-lock.json
    └─── package.json # 安裝 gulp、gulp-sass、gulp-sourcemaps

    ./source/scss/all.scss 載入所有組件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // base
    @import 'base/reset';

    // helpers
    @import 'helpers/variables';

    // component
    @import 'component/button';

    // layout
    @import 'layout/footer';

    載入並使用 gulp-sourcemaps:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const gulp = require('gulp');
    const sass = require('gulp-sass'); // 載入 gulp-sass 套件
    const sourcemaps = require('gulp-sourcemaps'); // 載入 gulp-sourcemaps 套件

    gulp.task('sass', function() {
    return gulp
    .src('./source/scss/*.scss')
    .pipe(sourcemaps.init()) // 初始化 sourcemaps
    .pipe(sass().on('error', sass.logError)) // 使用 gulp-sass 進行編譯
    .pipe(sourcemaps.write('./')) // 生成 sourcemaps 文件 (.map)
    .pipe(gulp.dest('public/css'));
    });

    執行指定任務:

    1
    $ gulp sass

    生成 ./public/css/all.css ./public/css/all.css.map 檔案,開啟 DevTool 工具並觀察 sourcemap 是否映射成功:

    從上圖可以發現,各元素映射的 Style 路徑從原本的 all.css 改為尚未編譯的 .scss 路徑,這樣的結果也就代表 sourcemap 映射成功,相同的原理也可套用在其他檔案類型身上,下面會再做補充。

    gulp-sourcemaps 可傳遞選項

    可參考 sourcemap Options 可傳遞參數列表,以下為常用的參數配置:

  • sourceMappingURLPrefix: String
    設定映射源的前綴,默認為 none
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    gulp.task('sass', function() {
    return gulp
    .src('./source/scss/*.scss')
    .pipe(sourcemaps.init()) // 初始化 sourcemaps
    .pipe(sass().on('error', sass.logError)) // 使用 gulp-sass 進行編譯
    .pipe(
    sourcemaps.write('./', {
    sourceMappingURLPrefix: 'scss',
    })
    ) // 寫入 sourcemaps
    .pipe(gulp.dest('public/css'));
    });

    補充:gulp-concat 生成 sourcemap

    gulp-concat 套件主要為合併檔案用,通常在開發專案時,我們會引入許多的套件,比如說 jquery、bootstrap 等等,這些分散的檔案我們需要一個一個引入,造成許多的麻煩,這時我們就可以利用合併檔案的方式彙整成一個檔案,供 HTML 引入,這時問題就來了,這一個彙整檔案是無法映射原始單獨檔案的,造成除錯(debug)較為困難,這一個問題也可以由 sourcemap 來解決,讓我們先從安裝開始。

    套件連結: gulp-concat jquery bootstrap

    gulp-concat:

    1
    $ npm install gulp-concat

    jquery:

    1
    $ npm install jquery

    bootstrap:

    1
    $ npm install bootstrap

    此次範例會結合 jquery 與 bootstrap 一起使用,說明如何使用 gulp-concat 合併檔案並生成 sourcemap。

    載入並使用 gulp-concat:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    gulp.task('vendorsJs', () => {
    return gulp
    .src([
    './node_modules/jquery/dist/jquery.slim.min.js',
    './node_modules/bootstrap/dist/js/bootstrap.bundle.min.js',
    './source/js/all.js',
    ])
    .pipe(sourcemaps.init()) // 初始化 sourcemaps
    .pipe(concat('vendors.js')) // 合併檔案,名稱為:vendors.js
    .pipe(sourcemaps.write('./')) // 寫入 sourcemaps
    .pipe(gulp.dest('./public/js'));
    });

    執行指定任務:

    1
    $ gulp vendorsJs

    生成 ./public/js/vendors.js ./public/js/vendors.js.map 檔案,開啟 DevTool 工具並觀察 sourcemap 是否映射成功:

    從上圖可以發現,頁面映射的 JavaScript 路徑從原本的 vendors.css 改為尚未編譯的各獨立檔案路徑,這樣的結果也就代表 sourcemap 映射成功。

    從前面的幾個範例可以發現,sourcemap 的生成主要是利用 sourcemaps.init() sourcemaps.write() 來完成,前者用來初始化,建議放置在第一個 pipe 節點,後者用來寫入 sourcemap,建議放在輸出文件的前一個 pipe 節點;事實上,gulp-sourcemaps 支援非常多種類型檔案生成 sourcemap,查詢檔案類型是否支援可參考下面連結:

    支援列表: Plugins with gulp sourcemaps support