關於 webpack 你可能忽略的細節(附源碼分析)

注:本篇不是入門教程,入門請直接查看官方文檔。本篇的主要目標是經過實際問題來介紹 webpack 中容易被人忽略的細節, 以及源碼分析(以最新發布的 release 版本1.14.0的源碼爲例), 而且提供幾種解決方案。javascript

webpack from the official website

隨着前端技術的火熱發展,工程化,模塊化和組件化的思想已逐步成爲主流,與之相應的,就須要有一整套工具流能夠支撐起它。前端

如今比較熱門的前端資源模塊化管理和打包工具應該非 Webpack 莫屬了。java

Webpack 是什麼

它能夠將許多鬆散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還能夠將按需加載的模塊進行代碼分隔,等到實際須要的時候再異步加載。經過 loader 的轉換,任何形式的資源均可以視做模塊,好比 CommonJs 模塊、 AMD 模塊、 ES6 模塊、CSS、圖片、 JSON、Coffeescript、 LESS 等。
--引自 Webpack 中文指南webpack

使用舉例

咱們來看一下官方文檔中的最小用例,新建並寫入如下內容到這兩個文件:git

cats.jsgithub

var cats = ['dave', 'henry', 'martha'];
module.exports = cats;

app.js (Entry Point)web

cats = require('./cats.js');
console.log(cats);

這個時候,就可使用 webpack 進行打包了:shell

webpack ./app.js app.bundle.js

咱們來看一下發生了什麼, 目錄下生成了一個打包後的文件 app.bundle.js ,這就是最基礎的打包過程。npm

提出問題

如何判斷打包是否成功?bash

通用方案

下面是咱們經常使用的兩種判斷任務是否執行成功的方案

經過 return code

經過命令執行後的 return code 來判斷(在 shell 中使用 $? 得到)。 而且一般狀況下 0 是執行成功, 非 0 是未成功。 咱們以上面的例子來測試一下:

webpack-demo.png

能夠看到 $? 的值爲 0 , 且打包後的文件運行正常。

那麼咱們來修改一下 app.js 文件的內容, 將 require 引入的模塊路徑故意寫錯,來測試一下:

webpack-error.png

注意:箭頭處 $? 的值仍然爲 0, 且生成的打包後的文件運行出錯。

這就說明,根據 return code 的值判斷任務是否執行成功, 不可行!

經過標準錯誤輸出

咱們也會經過標準錯誤輸出stderr)來判斷一個任務執行過程當中是否有錯誤輸出。仍是使用上面的例子作示範:

webpack-stderr.png

根據這個例子,能夠看到 webpack 並無標準錯誤輸出!因此這個方法也不可行。

探究緣由及源碼分析

這裏以最新發布的 release 版本 1.14.0 的源碼做爲分析。 在 lib/Compilation.js 中咱們能夠看到這樣一段代碼:

var errorAndCallback = function errorAndCallback(err) {
  err.dependencies = dependencies;
  err.origin = module;
  module.dependenciesErrors.push(err);
  _this.errors.push(err);
  if(bail) {
    callback(err);
  } else {
    callback();
  }
};

在源碼中能夠看到這個函數其實被調用的還比較多, 例如:在模塊爲可選的時候, 會判斷只是拋出警告仍是處理錯誤, 而上面這段代碼天然也沒必要多數, 關鍵點在於 bail 的值, 而咱們繼續找, 能夠看到在 bin/config-optimist.js 中有對 bail 參數的解析, 這是一個布爾值。而由於沒有太多描述, 因此這個參數就常常容易被忽略。

解決方案

1. 加 bail 參數

基於上面簡要的分析, 咱們來嘗試下 bail 參數的做用。 仍然使用上面的例子:

咱們使用 webpack --bail true app.js app.bundle.js 進行測試

webpack-bail.png

能夠看到, 使用 bail 參數並傳遞 true 進去, 在遇到錯誤的時候,打包過程將會退出, return code1 且把錯誤信息打印到 stderr .

2. 使用 webpack-fail-plugin

webpack-fail-plugin 是專爲解決這個問題而生的,它會在錯誤發生的時候 return 1. 使用方法也很簡單:

安裝:

npm install webpack-fail-plugin

使用:

var failPlugin = require('webpack-fail-plugin');
 
module.exports = {
    //config 
    plugins: [
        failPlugin
    ]
}

3.使用 done plugin

具體用法以下:

// ...
plugins: [ 
  // ... 
  function() { 
    this.plugin("done", function(stats) {
      if (stats.compilation.errors && stats.compilation.errors.length) {
        console.log(stats.compilation.errors); 
        process.exit(1); 
      }
      // ... 
    }); 
  }
// ...
],
// ...

4. 使用 webpack 2

不過 webpack 2 如今還在 beta 階段,能夠期待下。 (webpack 2 也仍然是使用 bail 參數)


能夠經過下面二維碼訂閱個人文章
公衆號【MoeLove】

公衆號:MoeLove

相關文章
相關標籤/搜索