Webpack动态导入功能有BUG?部分资源竟没加载,来看看什么是webpackJsonp?

本文基于Webpack4,若是你遇到相似问题,又懒得看全文,请直接拖到文章底部查看 解决总结部分

事件描述

我作了个小工具(站点访问点击热力图查看工具),这个小工具经过Webpack进行打包,工具中用到了Webpack的动态导入(Dynamic Imports)功能,本地测试运行良好,上线成功!撒花🎉。javascript

很多天后...运营妹子找来:“小白,我那个网站的热力图怎么显示不出来!!!”java

我说:“清缓存再试”、“换浏览器再试”、“重启电脑再试”!webpack

数分钟后,妹子脑壳上着火了,金灿灿,无比耀眼,向我走来,我都快瞎了,啊,我两眼都看不见了。web

她说,“你本身看,根本不行!”面试

我一度操做猛如虎,F12开启,强制刷新,咦,控制台咋报错了。。。装逼失败!“妹子大怒,热力图呢!?”chrome

图片描述

问题分析

我忽然感受到,问题大了,我开发的工具竟然在某些场景下出现不可用!赶忙看看其余已用该产品的工具状况,都是好的!面对这样的状况,确实有点无从下手了。编程

从Network面板上观察,发现有个动态加载的js没有加载到!这个js就是控制热力图渲染逻辑的。资源都没加载到,程序确定出问题,那为啥资源莫名其妙的没有加载呢?想来想去也没想出来。json

既然这样,就只能从出问题的网站上的错误提示中找线索了。部分代码以下:跨域

Object(n.a)()).then(function(e) {
  if (200 === e.code)
    return document.getElementById("JlaHeatmapLayer").style.display = "none",
    new Promise(function(t, n) {
      t(r.e(0).then(r.bind(null, 9)).then(function(t) {
        var r = t.default;
        setTimeout(function() {
          r(e.data)
        }, 600)
      }))
    }
    );
  alert(e.msg)
}).catch(function(e) {
  alert(e),
  console.warn(e)
})

上面试压缩后的代码进行chrome的format后的结果,由于写这篇文章,生产线已经修复,只能简单描述下错误,错误出如今r(e.data),提示r未定义,这里动态导入功能利用promise,t其实就是resolve,里面执行了一个r.e(0),这个r方法,就是管理须要加载的文件。数组

这里面的细节我就很少说了,简单描述下:由于是动态载入,那确定有个数组或对象存放须要载入的文件id,在这个方法内他会在合适的时候取出对象中的对应的文件。

而在工具使用正常的页面中,发现这个对象,只有1个,确实是我须要用的文件,而出问题的页面中,这个对象竟然有10个!!!这就不对了!我没有写那么多动态导入,为啥出来这么多?

我通过断点反复分析,从Stack内查看运行逻辑,终于发现了相似的这段代码:
// 工具正常页面
(window.webpackJsonp = window.webpackJsonp || []).push([[0], [, , , , , , , , , function(e, t, n) {
// ...

// 工具异常页面
(window.webpackJsonp = window.webpackJsonp || []).push([[10], {
// ...

这个大大的window确实十分可疑!针对这个继续深刻研究一下!

这里插一段工具的动态导入的源码片断
window.onload = () => {
  // init方法用来鉴权的
  init()
    .then((result) => {
      if (result.code !== 200) {
        alert(result.msg)
        return
      }
      document.getElementById('JlaHeatmapLayer').style.display = 'none'
      return new Promise((resolve, reject) => {
        resolve(import(/* webpackChunkName: "draw" */ './draw').then((module) => {
          const draw = module.default
          setTimeout(() => {
            draw(result.data)
          }, 600)
        }))
      })
    }).catch((err) => {
      alert(err)
      console.warn(err)
    })
}

有兴趣能够看看~

解决

那遇到问题天然查文档,打开官网,搜索webpackJsonp,一下就找到了output.jsonpFunction

原来这是webpack打包输出选项中的一个配置。用来作什么的呢,jsonp一看还觉得是跨域有关的,哈哈。其实他是一个异步加载chunks的函数。看到这里再思考下为啥这个页面就出问题呢,哈!这个出问题的页面是用KOA + NUXT,Nuxt自带了动态加载的功能,到这里真相大白。Nuxt中的webpackJsonp全局变量和我工具中的webpackJsonp全局变量发生冲突,致使工具中的动态导入出现异常,工具就完蛋了。

因而赶忙打开工具项目,参考文档进行了修改:

output: {
  path: path.resolve(__dirname, 'dist/dist/client/'),
  publicPath: IS_DEV ? '' : `//${process.env.BUILD_HOST}.51.la/dist/`,
  filename: 'heatmapDraw.js',
  jsonpFunction: 'wpJsonp51LAHeatmapTool'
},

从新打包,更新上线(专一面向正式线编程、就是这么自信:P)。啊哈,一切正常,看看代码,已经变成了以下:

(window.wpJsonp51LAHeatmapTool = window.wpJsonp51LAHeatmapTool || []).push([[0], [, , , , , , , , , function(e, t, n) {
// ...

问题解决,简直完美,继续撒花🎉🎉🎉~开开心心找妹子原谅去咯。

总结

其实一直对Webpack都有不断的学习,可是Webpack功能太强大了,确实不少疏忽的地方,不过我我的感受Webpack之因此强大,真的是只要你想获得的需求配置几乎全都能知足,确实值得深刻研究。

另外Webpack这种会暴露全局变量的确实也让我意想不到,有遇到相似问题的朋友能够参考下咯~

相关文章
相关标签/搜索