【深刻理解webpack】library,libraryTarget,externals的區別及做用

通過前端框架的迅猛發展,你們開始慢慢對模塊化習覺得常但殊不知道經過script引入和require(import)引入的區別。如何引入取決於以前如何導出,在重構一個驗證碼老項目時,不知如何把項目導出爲可經過script引入後使用內部方法?css

情景簡化爲以下:

  • 插件代碼
import {util} from 'util'
import styles from 'css'
export function initA(){
	console.log('it is init')
	...
}
複製代碼
  • 經過常見webpack打包爲bundle.js,在html中引入
<script src="bundle.js"></script>
<script>
//在這裏想要調用內部initA方法,報錯initA undefined
initA()
</script>
複製代碼

分析緣由

頁面報錯initA undefined,顯然此時調用initA,表明在window對象上面尋找initA方法,由於模塊化開發,杜絕一切全局變量,因此在全局找不到該對象,它是局部變量,打包以後代碼簡化以下:html

(function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.initA = initA;
function initA() {
    console.log('it is initA');
}
})
複製代碼

那如何能夠導出變量並掛載在全局對象之下,看下常見的jquery是如何操做的前端

//jQuery 1.2.6(新版已經支持模塊化)
var _jQuery = window.jQuery,
        _$ = window.$;
    var jQuery = window.jQuery = window.$ = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        return new jQuery.fn.init( selector, context );
    };
複製代碼

通過多番尋找在webpack配置中用output.libraryTarget參數能夠配置輸出模塊規範。node

webpack libraryTarget 參數說明

官網說明中敘述libraryTarget 有以下參數可選:(不指定 output.library 將取消這個 "var" 配置)中文說明jquery

  • libraryTarget: "var"(default) output.library 會將值做爲變量聲明導出(當使用 script 標籤時,其執行後在全局做用域可用)。
  • libraryTarget: "window" 當 library 加載完成,入口起點的返回值將分配給 window 對象。
window["MyLibrary"] = _entry_return_;
// 使用者將會這樣調用你的 library:
window.MyLibrary.doSomething();
複製代碼
  • libraryTarget: "assign"
  • libraryTarget: "this"
  • libraryTarget: "global"
  • libraryTarget: "commonjs" 當 library 加載完成,入口起點的返回值將分配給 exports 對象。這個名稱也意味着模塊用於 CommonJS 環境
exports["MyLibrary"] = _entry_return_;
// 使用者將會這樣調用你的 library:
require("MyLibrary").doSomething();
複製代碼
  • libraryTarget: "commonjs2"
  • libraryTarget: "amd"
  • libraryTarget: "umd" 這是一種能夠將你的 library 可以在全部的模塊定義下均可運行的方式(而且導出的徹底不是模塊)。它將在 CommonJS, AMD 環境下運行,或將模塊導出到 global 下的變量 最終輸出:
(function webpackUniversalModuleDefinition(root, factory) {
  if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if(typeof define === 'function' && define.amd)
    define([], factory);
  else if(typeof exports === 'object')
    exports["MyLibrary"] = factory();
  else
    root["MyLibrary"] = factory();
})(this, function() {
  //這個模塊會返回你的入口 chunk 所返回的
});
複製代碼
  • libraryTarget: "jsonp"

對比var,window,global,umd區別

因爲瀏覽器環境和node環境的區別,因此產生了window(客服端瀏覽器)和global(node服務端)的區別。 我理解的var即在script導入時和window一致,是否能夠經過import導入,導入以後的使用還待解釋。 umd即支持全部狀況的自定義。 總的說設置library即在當前環境的全局引入庫文件。webpack

externals的簡單使用

那externals又是如何使用的?和模塊導出有什麼區別? 先看定義:externals 配置選項提供了「從輸出的 bundle 中排除依賴」的方法。也就是說webpack打包時不會把庫打入bundle中,因此須要開發者在html中經過script標籤引入。 例如,從 CDN 引入 jQuery,而不是把它打包:web

index.htmljson

<script src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"></script>
複製代碼

webpack.config.js瀏覽器

externals: {
  jquery: 'jQuery'
}
複製代碼

有心的同窗可能要想了,我都從script標籤引入了那麼全局就均可以使用了,爲何還要設置這個配置吶? 爲了避免改動原來的依賴模塊!以下bash

import $ from 'jquery';

$('.my-element').animate(...);
複製代碼

具備外部依賴(external dependency)的 bundle 能夠在各類模塊上下文(module context)中使用,例如 CommonJS, AMD, 全局變量和 ES2015 模塊。這裏所說的模式就是上文libraryTarget的模式。 外部 library 多是如下任何一種形式:

  • root - 外部 library 可以做爲全局變量使用。用戶能夠經過在 script 標籤中引入來實現。這是 externals 的默認設置。
  • commonjs - 用戶(consumer)應用程序可能使用 CommonJS 模塊系統,所以外部 library 應該使用 CommonJS 模塊系統,而且應該是一個 CommonJS 模塊。
  • commonjs2 - 相似上面幾行,但導出的是 module.exports.default。
  • amd - 相似上面幾行,但使用 AMD 模塊系統。

以前只看掘金,歷來不發,歡迎關注的個人博客啊。

相關文章
相關標籤/搜索