webpack externals 深刻理解

按照官方文檔的解釋,若是咱們想引用一個庫,可是又不想讓webpack打包,而且又不影響咱們在程序中以CMD、AMD或者window/global全局等方式進行使用,那就能夠經過配置externals。這個功能主要是用在建立一個庫的時候用的,可是也能夠在咱們項目開發中充分使用。javascript

假設:咱們開發了一個本身的庫,裏面引用了lodash這個包,通過webpack打包的時候,發現若是把這個lodash包打入進去,打包文件就會很是大。那麼咱們就能夠externals的方式引入。也就是說,本身的庫自己不打包這個lodash,須要用戶環境提供。css

使用lodashhtml

import _ from 'lodash';

配置externalsjava

externals: {
  "lodash": {
        commonjs: "lodash",//若是咱們的庫運行在Node.js環境中,import _ from 'lodash'等價於const _ = require('lodash')
        commonjs2: "lodash",//同上
        amd: "lodash",//若是咱們的庫使用require.js等加載,等價於 define(["lodash"], factory);
        root: "_"//若是咱們的庫在瀏覽器中使用,須要提供一個全局的變量‘_’,等價於 var _ = (window._) or (_);
  }
}

總得來講,externals配置就是爲了使import _ from 'lodash'這句代碼,在自己不引入lodash的狀況下,可以在各個環境都能解釋執行。react

有一點須要注意的是,假如lodash中在瀏覽器環境中不提供_的全局變量,那麼就沒有辦法使用。這個"_"是不能隨便亂寫的。若是外部庫lodash提供的是全局變量lodash,那你就得使用lodashjquery

若是你寫的庫要支持各類環境,你須要設置output中的libraryTarget爲umd,也就是將打包的文件,生成爲umd規範,適用於各類環境。libraryTarget和externals有藕斷絲連的關係,後面會提到。webpack

下面進入正題,externals的配置有如下幾種:array , object ,reg。這三種形式均可以傳入,前者實際上是對後者的包含。web

參考這裏數組

Array

數組內的每個元素又能夠是多種形式,包括object, reg, function, string瀏覽器

externals: [
    { // ① object形式
          jquery: 'jQuery', // 
        a: false, // 不是external,配置錯誤
        b: true, // b 是 external, `module.exports = b`,適用於你所引用的庫暴露出的變量和你所使用的庫的名稱一致的狀況,好比moment
        "./c": "c", // "./c" 是 external `module.exports = c`
        "./d": "var d", // "./d" 是 external `module.exports = ./d`  語法錯誤
        "./f": "commonjs2 ./a/b", // "./f" 是 external `module.exports = require("./a/b")`
        "./f": "commonjs ./a/b", // ...和 commonjs2同樣
        "./f": "this ./a/b", // "./f" 是 external `(function() { module.exports = this["./a/b"]; }())`
    },
    // abc -> require("abc")
    /^[a-z\-0-9]+$/, // ② reg形式
    function(context, request, callback) { // ③ function形式
        // Every module prefixed with "global-" becomes external
        // "global-abc" -> abc
        if(/^global-/.test(request))
            return callback(null, "var " + request.substr(7));
        callback();
    },
    "./e" // "./e" 是 external ( require("./e") ) // ④ string形式
]

Object

Object形式和上面相似,可是它裏面必定是key: value的形式,因此像上面那種string的形式就不可能出如今object形式中。這種狀況下使用的最多。

externals:{ 
          jquery: 'jQuery', // 
        a: false, // 不是external,配置錯誤
        b: true, // b 是 external, `module.exports = b`,適用於你所引用的庫暴露出的變量和你所使用的庫的名稱一致的狀況,好比moment
        "./c": "c", // "./c" 是 external `module.exports = c`
        "./d": "var d", // "./d" 是 external `module.exports = ./d`  語法錯誤
        "./f": "commonjs2 ./a/b", // "./f" 是 external `module.exports = require("./a/b")`
        "./f": "commonjs ./a/b", // ...和 commonjs2同樣
        "./f": "this ./a/b", // "./f" 是 external `(function() { module.exports = this["./a/b"]; }())`
    },

reg就不介紹了,也就是正則匹配的形式。能夠類比Array類型中的string。

externals引入jquery後,那麼無論在代碼中使用import $ from 'jquery'仍是var $ = require('jquery');,這些代碼都能在瀏覽器中很好的執行。這很好的驗證了使用externals的狀況。

想引用一個庫,可是又不想讓webpack打包,而且又不影響咱們在程序中以CMD、AMD或者window/global全局等方式進行使用

那若是想要這樣使用 import $ from 'jquery',而且想在Node環境中使用,那麼就必需要使用這樣 jquery: 'commonjs2 jquery'使用。這樣webpack就會把你所須要的模塊打包成module.exports = require('jquery'),能夠再Node環境中使用。

externals 支持如下模塊上下文(module context)

  • global - 外部 library 可以做爲全局變量使用。用戶能夠經過在 script 標籤中引入來實現。這是 externals 的默認設置。

  • commonjs - 用戶(consumer)應用程序可能使用 CommonJS 模塊系統,所以外部 library 應該使用 CommonJS 模塊系統,而且應該是一個 CommonJS 模塊。

  • commonjs2 - 相似上面幾行,但導出的是 module.exports.default

  • amd - 相似上面幾行,但使用 AMD 模塊系統。

不一樣環境設置externals方式

  1. 若是你的代碼想運行在Node環境中,那麼你須要在external中添加前綴commonjs2或者commonjs

externals:{
  react:'commonjs2 react',
  jquery:'commonjs2 jquery'
}
  1. 若是須要requirejs等符合AMD規範的環境中加載,那就要添加amd

externals:{
  react:'amd React',
  jquery:'amd jQuery'
}
  1. 若是要在瀏覽器中運行,那麼不用添加什麼前綴,默認設置就是global。

externals:{
  react:'React',
  jquery:'jQuery'
}

也能夠這樣

externals:["React","jQuery"]

這種方式配置下,就是配置你所引用你的庫暴露出的全局變量。上面兩種模式下或者說,若是你想運行代碼在瀏覽器中,你所引用的包,必須暴露出一個全局變量。若是沒有,這種方式不適合在瀏覽器下使用,能夠嘗試dll的方式。

這裏你能夠看出,不一樣模式下,value是不同的。2,3模式下,是要引入去全局變量,1模式是要加載包名。那若是這個包的包名和在瀏覽器下引入的全局變量一致,上面就能夠寫成同樣了,好比moment。

externalslibraryTarget的關係

  • libraryTarget配置如何暴露 library。若是不設置library,那這個library就不暴露。就至關於一個自執行函數

  • externals是決定的是以哪一種模式去加載所引入的額外的包

  • libraryTarget決定了你的library運行在哪一個環境,哪一個環境也就決定了你哪一種模式去加載所引入的額外的包。也就是說,externals應該和libraryTarget保持一致。library運行在瀏覽器中的,你設置externals的模式爲commonjs,那代碼確定就運行不了了。

  • 若是是應用程序開發,通常是運行在瀏覽器環境libraryTarget能夠不設置,externals默認的模式是global,也就是以全局變量的模式加載所引入外部的庫。

參考:

http://www.css88.com/doc/webp...

http://www.css88.com/doc/webp...

http://www.tangshuang.net/334...

相關文章
相關標籤/搜索