当ArcGIS API for JavaScript遇见Webpack(二)

作者:liuyl 邮箱:[email protected]
关于作者:GIS从业者,主要在ArcGIS平台下做WebGIS开发


广告移到前面以免你看不到


公众号开通了,欢迎扫描下面二维码进行关注,我争取每周都写一两篇文章,记录和分享工作和学习中的收获。内容将主要是WebGIS开发方面的,欢迎在公众号中留言和我进行交流。


当ArcGIS API for JavaScript遇见Webpack(二)_第1张图片
请扫码关注我的微信公众号 幻想GIS

写在最前面


如果你还没有看过并理解了上一篇 当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为例、且不考虑把第三方库的代码直接一同打包的情况)

  1. 引入js文件



  1. 修改webpack配置externals
    将webpack的externals项配置成如下
externals: [
    {
        jquery: 'jQuery',
        lodash: '_',
        react: 'React',
    },
]

这一步的配置可以让我们在代码中使用import语句引入第三方库,比如:

    import $ from 'jquery'
    import _ from 'lodash'
    import React from 'react'
  1. 修改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页中的引入次序,主要是两类错误。

  1. multipleDefine错误


    当ArcGIS API for JavaScript遇见Webpack(二)_第2张图片

这主要是由于在html页中api的init.js在第三方库(如jquery.js)之前被引入。
具体成因我没有搞清楚,欢迎补充~

  1. 找不到库文件错误


    当ArcGIS API for JavaScript遇见Webpack(二)_第3张图片

当在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的深度用户,还是希望保持对其的绝对控制的,这两篇文章中的解决方案基本上满足了我工作中的需求,我觉得还是比较完善的。

如果你觉得这篇文章对你有帮助,请移动到文章顶部,关注我的微信公众号。
如果你有任何疑问和建议,欢迎留言和我交流。

你可能感兴趣的:(当ArcGIS API for JavaScript遇见Webpack(二))