作者:liuyl 邮箱:[email protected]
关于作者:GIS从业者,主要在ArcGIS平台下做WebGIS开发
广告移到前面以免你看不到
公众号开通了,欢迎扫描下面二维码进行关注,我争取每周都写一两篇文章,记录和分享工作和学习中的收获。内容将主要是WebGIS开发方面的,欢迎在公众号中留言和我进行交流。
写在最前面
如果你还没有看过并理解了上一篇 当ArcGIS API for JavaScript遇见Webpack(一) 的内容的话,请移步第一篇。
为什么写这篇文章
在上一篇中,我们成功的让ArcGIS API for JavaScript和Webpack和谐地相处了。
如果是个Demo的话,这就算是成功了。不过我们是要做项目的,第三方库比如jquery、lodash甚至是react之类的,总是要用到一些。甚至更进一步,我们要开发一个基于ArcGIS API for JavaScript的组件库,并希望像其他第三方库一样用import
语句引用。
这时你会发现,ArcGIS API for JavaScript和Webpack的相处并不如表面上那么和谐,问题一个接一个出现……现在,我们来一个个地解决这些问题。
下面是正文
正常情况下引入第三方库
关于正常情况下,也就是不引入ArcGIS API for JavaScript,或是dojo,又或是AMD时,第三方库的引用还是比较简单的,有大量教程可供参考,这里简单列一下。
(以下均以从CDN引入jquery、lodash和react.js为例、且不考虑把第三方库的代码直接一同打包的情况)
- 引入js文件
- 修改webpack配置
externals
项
将webpack的externals
项配置成如下
externals: [
{
jquery: 'jQuery',
lodash: '_',
react: 'React',
},
]
这一步的配置可以让我们在代码中使用import
语句引入第三方库,比如:
import $ from 'jquery'
import _ from 'lodash'
import React from 'react'
- 修改webpack配置
plugins
项(可选)
在webpack的plugins
项配置中添加如下代码
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
_: 'lodash',
}),
]
这一步的配置可以让我们不需要再通过import
语句引入jquery和lodash,而是可以直接在全局使用$和_符号
在引入ArcGIS API for JavaScript的情况下引入第三方库
假设按照第一篇中我们引入了ArcGIS API for JavaScript,并按照上面所述引入第三方库、修改webpack配置。然后写一个例子,比如这样:
import Map from 'esri/Map'
import MapView from 'esri/views/MapView'
const $mapDom=$('').appendTo($('body'))
var map = new Map({
basemap: 'streets'
})
var view = new MapView({
container: yourDom,
map: map
})
直接访问应用,喜闻乐见地在控制台看到了错误信息。
这里我们同时引用了jquery和api,这个错误信息取决于jquery和api在html页中的引入次序,主要是两类错误。
-
multipleDefine错误
这主要是由于在html页中api的init.js在第三方库(如jquery.js)之前被引入。
具体成因我没有搞清楚,欢迎补充~
-
找不到库文件错误
当在html页中api的init.js
在第三方库(如jquery.js
)之后被引入时,就会导致这个错误。
第一篇时我们讨论过webpack的externals
项配置,它是用来标明外部引用的。
externals: [
{
jquery: 'jQuery',
},
]
这个配置会让打包生成的js文件的最前面生成类似这样的代码
define(["jQuery", ……],
function (__WEBPACK_EXTERNAL_MODULE_3__,……){
...
})
对dojo比较熟的同学会看出来,当AMD不认识jQuery
时,就会在其工作路径下寻找jQuery.js
文件,找不到的话就会报上面的错误。
如何避免错误
针对上述第1个错误,我们需要在html文件中将api的init.js
文件放在其他第三方库的后面引入。
针对第2个错误,我们可以在api的init.js
文件引入后,人为地将第三方库的全局名称define
到AMD中,html文件中大致这样:
webpack的配置按上面说的正常情况进行修改即可。
写一个基于ArcGIS API for JavaScript的组件库
正常情况下写一个类库时,webpack的output
配置项,应该配置成如下的样子
output: {
libraryTarget: 'umd',
library: 'YourLib',
……
}
libraryTarget: 'umd'
意味着我们的库可以通过输出全局变量引入,也支持commonJs或AMD方式引入,大部分我们常使用的第三方库都是这样的。但正如前所说,这样的库在ArcGIS API for JavaScript的init.js
文件之后引入时会导致multipleDefine
错误。
我们的库是基于ArcGIS API for JavaScript的,也就是不得不在api后面引入,如果我们设置了libraryTarget: 'umd'
,那么就同样会遇到multipleDefine
错误。
解决这个问题,就把webpack的output
项设置成如下所示
output: {
libraryTarget: 'var',
library: 'MyLib',
……
}
libraryTarget: 'var'
其实是默认值,就是向全局输出一个MyLib
变量,在应用中引入这个库时,同样需要手动define
一下,整个引入流程大致如下:
webpack配置
externals: [
{
mylib: 'MyLib',
},
]
html文件
应用调用文件
import myLib from 'mylib'
myLib.testFun()
最后,这个库如何封装和调用ArcGIS API for JavaScript
function createMap(dom){
window.require(['esri/Map', 'esri/views/MapView'], (Map, MapView) => {
var map = new Map({
……
})
this.view = new MapView({
container: dom,
map: map,
})
})
}
export default createMap
上面只是个示例,这里就不能用import
语句调用api了,而是使用传统的require
语句。但是要注意的是不能直接写require
,因为webpack会对require
语句进行编译,用window.requrire
不会被编译。
当然,我感觉通过webpack的适当配置,还是有可能实现使用import
语句调用api的,欢迎有兴趣的同学继续探索。
写在最后
关于ArcGIS API for JavaScript和Webpack之间的纠葛就写到这了。
这两篇里面的内容实际上折腾了我挺长时间,当然也是在这个过程中才逐渐理解了webpack的核心逻辑,还是挺值得的。
ArcGIS API for JavaScript和Webpack之间的集成,其实还有一些其他的解决方案,比如esri-loader。我没有尝试去用过,据说有坑,有兴趣的同学倒也不妨一试。对于我这个ArcGIS API for JavaScript的深度用户,还是希望保持对其的绝对控制的,这两篇文章中的解决方案基本上满足了我工作中的需求,我觉得还是比较完善的。
如果你觉得这篇文章对你有帮助,请移动到文章顶部,关注我的微信公众号。
如果你有任何疑问和建议,欢迎留言和我交流。