webpack引入第三方库方案总结

webpack引入第三方库方案总结

在使用webpack打包项目时,最好尽量使用import的方式引入第三方库,但有些情况又必须使用其他方式引入第三方库…

要项目上必须要用一个 jQuery 插件形式的库

而引入这个库之前必须要引入jQuery,因为插件里面可能会出现这样的代码

1
2
3
4
5
6
7
8
9
(function() {
var jQuery = window.jQuery,
\\ ...
\\ ...
if (!jQuery) throw 'MathQuill requires jQuery 1.4.3+ to be loaded first';
\\ ...
\\ ...
\\ ...
})();

所以需要在webpack构建的项目中引入 第三方 js库,一般情况下引入第三方库有以下几种方式

直接引入

直接引入的关键在于输出的配置,这里以var为例,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 output : {
filename : '[name].js',
// devServer不可配置为绝对路径
//publicPath: "http://localhost:8080/dist/",
publicPath: "/dist/",
path : build,
// umd包含了对amd、commonjs、var等多种规范的支持
// 关键在于这里
libraryTarget : 'var'
},
// 其他配置略
resolve: {
//extensions: ['', '.js', '.es6', '.vue'],
alias: {
// 也可以不写
jquery: 'jquery/dist/jquery.min.js',
}
}

这样,在编译代码时,webpack会自动将jQuery打进代码,现在就可以引入代码了

1
2
3
4
5
// 可以直接引入jquery
import $ from 'jquery'
// 因为是commonjs规范,所以会按顺序加载,引用成功,如果是output为amd,则必须在requirejs中配置shim,否则失败

import 'jquery-ui'

2. ProvidePlugin[难以引入插件]

在webpack中添加插件ProvidePlugin

1
2
3
4
5
6
7
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
]
// $函数会自动添加到当前模块的上下文,无需显示声明

问题是依旧没有全局的$函数,所以导入插件依旧会失败,并且如果有eslint这样的preLoads,调用语句也难以通过语法校验(因为没有声明$就直接使用),仅这一点,对于我这样的代码处女座就难以接受。

3. expose-loader[推荐使用]

不需要任何其他的插件配合,只要将下面的代码添加到所有的loader之前

1
2
3
4
{
test: require.resolve('jquery'),
loader: 'expose?jQuery!expose?$'
}

引用时改为如下方式

1
2
import $ from 'expose?$!jquery'
import 'jquery-ui' //插件可用

imports-loader、script-loader同样可达到此效果,配置与功能都非常相似,在此不一一说明。

4. 包装jquery[推荐使用]

此方法只依赖于自己,完全不需要任何其他插件与加载器,创建jquery的包装对象jquery-vendor.js

1
2
3
4
import $ from 'jquery'
window.$ = $
window.jQuery = $
export default $

以后引用jquery时指向jquery-vendor.js

1
2
3
import $ from '../assets/jquery-vendor.js'
import 'jquery-ui'
// 此时UI的方法全部可用,如果需要引用bootstrap,可参照此方法

为了调用方便,可在webpack配置文件中创建jquery-vendor.js的别名

1
2
3
alias: {
jquery : 'src/assets/jquery-vendor.js' // 将其指向jquery-vendor.js所在位置
}

2. 第三方库需要通过 类似requirejs机制 异步加载其他依赖库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 这是 MathJax 数学表达式解析库 加载扩展的一段代码
// 该库需要加载 extensions 而且是通过在页面插入script的方式加载的
loader: {
JS: function (k, m) {
var j = this.fileName(k);
var i = document.createElement("script");
var l = a.Callback(["loadTimeout", this, k]);
this.loading[k] = {
callback: m,
timeout: setTimeout(l, this.timeout),
status: this.STATUS.OK,
script: i
};
this.loading[k].message = a.Message.File(j);
i.onerror = l;
i.type = "text/javascript";
i.src = k + this.fileRev(j);
this.head.appendChild(i)
}, CSS: function (j, l) {
var i = this.fileName(j);
var k = document.createElement("link");
k.rel = "stylesheet";
k.type = "text/css";
k.href = j + this.fileRev(i);
this.loading[j] = {callback: l, message: a.Message.File(i), status: this.STATUS.OK};
this.head.appendChild(k);
this.timer.create.call(this, [this.timer.file, j], k)
}
},

遇到这种情况,就不能用常规的方法引入第三方依赖,以上的方法都不适用,因为在编译期间不会再报错 但是在运行期间会报一个js文件加载404的错误。

因为这是在运行之后通过注入script标签 加载插件 。而在编译时webpack不会检测到这种异步加载逻辑 并导入。

我的解决方案:
要使能够通过异步加载 ,必须保证 映入的库 和他的依赖文件 相对文章不变 ,整体放到 编译后的目录。
以引入 MathJax 数学表达式解析库为例 由于MathJax 的加载扩展(MathMenu)是用到 类似 requirejs的异步加载机制 ,所以需要引入mathquill 只能通过 script 标签引入,不能通过 import 引入 mathquill

修改文件如下:

1. webpack.config.js:

1
2
// 在编译打包时 把 /src/lib/下的 js文件复制到 www(编译输出目录)/lib 目录
new CopyWebpackPlugin([ {from: './src/lib', to: 'lib'}]),

2. index.html:

1
2
3
4
5
6
<script src="./lib/polyvplayer/polyvplayer.min.js"></script>
<script src="./lib/jquery/dist/jquery.min.js"></script>
<script src="./lib/cat_mathjax/dist/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script src="./lib/cat_mathquill_build/mathquill.js"></script>
<link rel="stylesheet" href="./lib/cat_mathquill_build/mathquill.css">

3. 添加文件夹:/src/lib

1
2
/src/lib/jquery/ 
/src/lib/mathjax/