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'
    },
相关文章
相关标签/搜索