【深刻理解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 模块系统。

以前只看掘金,历来不发,欢迎关注的个人博客啊。

相关文章
相关标签/搜索