webpack之深刻淺出externals

咱們一般在作項目時可能會把第三方庫打包到bundle中,好比下面這張圖html

 

若是不想把第三方庫打包到bundle中,這就有了externals。官方的使用externals比較簡單,只需三步——node

1.在HTML中引入第三方庫的cdnjquery

2.在webpack中配置externalswebpack

externals: {
    jquery: "jQuery",
}

3.在js中引用web

const $ = require("jquery");
$("#content").html("<h1>hello world</h1>");

好,如今咱們能夠爲所欲爲的使用jquery插件並保證不會打包到bundle中。external是怎麼辦到的呢?下面咱們經過bundle的源碼來分析下原理。npm

這裏的/* 0 */和__webpack_require__分別指打包前js對應的模塊函數(詳細過程見我上一篇博客),這裏就不細說了。這裏能夠看到module.exports = jQuery,就是說咱們externals中的key指的是require的東西,value指的就是它,就是說「當require的參數是jquery的時候,使用jQuery這個全局變量引用它」。這種最簡潔的externals配置方式爲默認的global模式,就是在window上掛一個全局變量,而後直接可使用這個變量。具體的流程是這樣,咱們在源碼中使用require('jquery')後,能夠直接把jquery加到externals中,獲得一個打包的trunk.js,可是在引入這個trunkjs以前,確定要先引入jquery這個庫文件,這個庫文件會建立一個全局變量jQuery,而我們的trunkjs中externals的jquery是global模式,因此實際上trunkjs引入jquery的時候,就會從全局變量中引用,即module.export = jQuery瀏覽器

 

固然,既然是經過這種externals方式,其實咱們能夠不用require引入,直接使用全局變量也是能夠的。echarts

jQuery("#content").html("<h1>hello world</h1>");

 你們若是注意到我剛說過的global模式的話,沒錯,你也許已經猜到了,我能夠任意的使用不一樣的輸出方式。若是打包文件我想運行到node環境下,我得使用commonjs規範,因此你要這麼寫。ssh

externals: {
    jquery: "commonjs2 jQuery",
}

打包後會是這樣子。jquery插件

而後個人項目中還用到了lodash,也想把它從bundle中移除,以前個人代碼是這樣子,引的是npm包

 

 

 

 如今咱們的externals配置以下

externals: {
        jquery: "jQuery",
        _: "lodash"

}

咱們必需要去掉這個const ,不然的話會報一個錯誤 lodash is not defined。爲何會這樣呢?由於咱們的lodash輸出是global格式的,我在這裏先賣一個關子,咱們先統一一下輸出格式,加一個libraryTarget字段

 

這個東西是幹嗎用的呢?

他是咱們輸出文件的模塊化規範,想一想咱們上面配置的commonjs jquery是運行在node下,總之記住一句話——咱們最長使用的模塊化方案是commonjs2和umd,前者是爲node環境,後者是爲瀏覽器環境。一共有這幾種規範:

"var" - Export by setting a variable: var Library = xxx (default)

"this" - Export by setting a property of this: this["Library"] = xxx
"commonjs" - Export by setting a property of exports: exports["Library"] = xxx
"commonjs2" - Export by setting module.exports: module.exports = xxx
"amd" - Export to AMD (optionally named - set the name via the library option)
"umd" - Export to AMD, CommonJS2 or as property in root

 

而後報這個錯誤,也就是說咱們的模塊沒有正確的輸出,回到咱們的externals,它更多的是指定當你引用一個包的時候,這個包(lodash)應該遵循哪一種模塊化方式(common,root,amd等等)引入,這意思就是說,打包的時候不須要關心他到底怎麼輸出。

externals: {
        jquery: "jQuery",
        lodash: {
            commonjs: 'lodash',
            commonjs2: 'lodash',
            amd: 'lodash',
            root: '_'
        }
    },

 

ok,記得要將以前的覆蓋掉,替換成下面的require,由於在externals中咱們規範的commmonjs規範爲lodash

 

也就是說,這就是咱們最初的代碼,即沒有用過externals時候的代碼,看,也就是說咱們只須要配置externals和libraryTarget就能夠,其餘的業務邏輯代碼不須要改變。包括咱們的項目中還用了echarts,這個統統不用改變!!!!!

也就是說最終的代碼是externals配合libraryTarget一塊兒使用,若是去掉umd的話,會報這個錯誤

相應的源碼是這樣子

 

  就是說我不知道經過那種方式輸出,因此我應該告訴webpack,我經過umd方式輸出,即將你的 lodash 暴露爲全部的模塊定義下均可運行的方式。它將在 CommonJS, AMD 環境下運行,或將模塊導出到 global 下的變量.加上umd的源碼以下

 

 看到了吧,我經過require('lodash')引入模塊,輸出走的是commonjs規範,貼下最終的配置

entry: {
        main: './src/index.js'
    },
    externals: {
        jquery: "jQuery",
        lodash: {
            commonjs: 'lodash',
            commonjs2: 'lodash',
            amd: 'lodash',
            root: '_'
        }
    },
    output: {
        filename: '[name].[chunkhash].js',
        path: path.resolve(__dirname,'dist'),
        libraryTarget: 'umd'
    },
相關文章
相關標籤/搜索