教你用正确的方式在webpack里引入jQuery、eCharts等lib

前注:

关于webpack的文档全文(我本身写的教程)请查看 根目录的文档说明html

若是能够,请给本项目加【Star】和【Fork】持续关注。webpack

有疑义请点击这里,发【Issues】。git

点击这里查看DEMOgithub

九、外部扩展(Externals)

9.0、DEMO使用说明

安装:web

npm i
复制代码

运行:npm

npm run dev
复制代码

打包(生产模式):缓存

npm run build
复制代码

9.一、应用场景

当咱们加载一个外部库,好比 jQuery,好比 echarts 等,为了节约流量,咱们每每会使用 CDN 来加载这些东西。bash

这和咱们日常进行模块化开发就有了必定的矛盾:服务器

  1. 需求:咱们须要引入一个全局变量(实质是引入一个模块);
  2. 常规作法:因此正常来讲,咱们应该经过 import 来引入这个模块;
  3. 问题:但因为经过CDN来加载,显然咱们不能这么作;

解决方案:

一、通常解决方案:app

咱们能够直接经过使用这个全局变量来使用这个变量,例如:

// globalVariableName 经过CDN引入js文件,这个变量名其该js文件暴露出来的全局变量名(类型是一个函数)
document.getElementById("root").innerText = globalVariableName(1, 2, 3)
复制代码

这个不是不行,但容易形成一个问题就是,容易在一不当心的状况下,篡改了原有的变量。

而且,这种方式是高耦合度的,不推荐使用。

二、模块化解决方案:

按照正常的开发方式,咱们一般是使用 外部扩展 来实现。

他具备如下特色:

示例代码:

// ``webpack.config.js`` 文件里的配置代码

// 指定别名
externals: {
    // 后面是本来使用的全局变量名,前面的是引入的包名(就是import xx from 'echart'),而后咱们实际写代码时候,用的是xx这个变量名。
    "moduleName": 'globalVariableName'
}

// app.js 里的业务代码
import add from 'moduleName'
document.getElementById("root").innerText = add(1, 2, 3)
复制代码
  1. webpack.config.js 里进行配置;
  2. 一般使用 kv 模式,而且 v 通常是字符串(就像 "moduleName": 'globalVariableName' 这样);
  3. 效果是当引入某个模块时(k 决定),将不会像常规处理那样去加载他,而是排除掉(就像 import add from 'moduleName' 这段代码,不会去找 moduleName 这个模块);
  4. 排除掉后怎么处理呢,运行时从外部获取这个扩展;
  5. 具体作法是(须要必定程度上知晓 webpack 打包后如何加载模块,才能理解如下内容):获取时,像正常导入一个模块同样,加载一个模块;
  6. 但这个模块作的事情,是将一个外部变量,经过 AMD 规范赋值给 module.exports(咱们使用 require 加载模块时,获取的值,就是 AMD 规范的模块,经过这个属性导出的值);
  7. 从而让加载 moduleName 模块时,实际加载到的是这个全局变量(5-7这个过程,实际体现的就是如下这段代码)。
// 其余代码略
"moduleName": (function (module, exports) {
    module.exports = globalVariableName;
})
复制代码

9.二、简单来讲(使用说明)

【需求】

假如我须要经过 CDN 加载一个我自定义的库,示例我用的是:<script src="http://www.jianwangsan.cn/looksLikeCDN.js"></script>

这个库就作了一件事情,暴露了一个全局变量 window.globalVariableName,这个变量是一个函数,他会将全部参数的和相加,并返回。(固然实际应用中,这个多是一个对象,有 N 个属性,很是复杂,但原理是同样的)

【第一步,修改html源文件】

我如今经过 CDN 来加载这个库,所以个人 html 源文件是这样的(固然实际上我不是CDN,所以用的是我我的服务器上的一个js文件,但道理也是同样的):

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="http://www.jianwangsan.cn/looksLikeCDN.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
复制代码

【第二步,配置webpack】

我如今须要使用这个方法,又不想经过模块化引入(由于这个是固定不变的,没有必要每次重复打包,这样不利于缓存,就像 jQuery 库同样)。

因而我首先编辑 webpack.config.js 文件,给打包配置对象添加一个属性,具体配置以下:

// 指定别名
externals: {
    // 后面是本来使用的全局变量名,前面的是引入的包名(就是import xx from 'echart'),而后咱们实际写代码时候,用的是xx这个变量名。
    "moduleName": 'globalVariableName'
}
复制代码

将你想使用的全局变量,做为 kv 键值对的 v,而 k 做为在 js 文件中引入的模块名使用(参考第三步)。

不想看解释的跳过下面这段话,直接看第三步

以上配置意味着:

  1. moduleName 不会被正常加载:当我须要加载 import add from 'moduleName' 这个模块时,webpack 不会像以前去找对应模块那样而处理(找到对应模块,加载对应模块,将模块的返回值赋值给 add),而是采用一种新的机制来处理;
  2. 创造出的模块:新的机制意味着,将创造一个 'moduleName' 模块(注意,实际上这个模块在工程里并不存在);
  3. globalVariableName 全局变量:创造出来的模块作了一件事情,他返回了一个值,这个值是 globalVariableName 这个全局变量的值。(想一想 AMD 规范中,module.exports = globalVariableName; 这段代码表示什么?);

因而体现的效果,就至关于如下代码:

// app.js
import add from './moduleName'

// moduleName.js
export default window.globalVariableName
复制代码

【第三步,在工程中引入】

上面咱们得到一个 k(moduleName),做为模块名,所以在 app.js 这个工程中查看:

// app.js
import add from 'moduleName'

// 这里的 moduleName 模块,返回 window.globalVariableName 这个值
// 因此就意味着 add 的值等同于 globalVariableName 的值
document.getElementById("root").innerText = add(1, 2, 3)
复制代码

【结束】

这样就能够了,如今能够尝试进入命令行,输入 npm run build 打包,并查看一下效果啦。

相关文章
相关标签/搜索