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...

相关文章
相关标签/搜索