天天看点

webpack+babel+transform-runtime, IE下提示Promise未定义?

知识要求

  • babel

    的基础知识(推荐阮一峰的babel入门教程)
  • 充分理解

    babel-plugin-transform-runtime

    babel-runtime

    的作用(推荐github项目首页)
  • webpack2

    基础用法(https://webpack.js.org/)
  • webpack2

    babel-loader

    作用,

    import

    异步加载

问题说明

webpack

+

babel-loader

transform-runtime

正常来讲应该能实现在没有原生支持

Promise

的浏览器(如

IE

)下正常运行,但是实际在

IE11

下,还是提示

Promise

未定义的错误。网上找了一圈,没有切中要害的,于是干脆自己分析。

webpack+babel+transform-runtime, IE下提示Promise未定义?

分析

首先确认

babel

transform-runtime

是否生效,在自己的

js

代码中编写

var promise = new Promise(resolve, reject)

的示例代码,发现

Promise

是有被替换的。所以问题的关键在于什么东西超出了

babel

的控制?

我想到的是

node_modules

webpack

本身生成的代码。

在使用

babel

转换

ES6

之前, 通过

node_modules

引用的第三方包都能正常使用,因此可以排除。

那么

webpack

呢,在

GOOGLE

中搜索

webpack promise not defined

,还真找到了原因,如下图所示:

webpack+babel+transform-runtime, IE下提示Promise未定义?

图片来源: https://webpack.js.org/guides/migrating/#require-ensure-and-amd-require-are-asynchronous

当使用了

webpack

的异步加载时,

webpack

要求原生支持

Promise

,刚好我们的代码有用到。至此,原因就找到了:

webpack

生成的

new Promise

相关代码, 超出

babel

transform-runtime

的控制范围,只有导出全局的

Promise

才能解决此问题。

解决方案1

  • 引入

    babel-polyfill

    导出全局

    Promise

    ,这种方法并不好;不仅

    Promise

    被导出,还抛出大量其他的全局对象,可能存在冲突风险,同时文件体积比较大。

解决方案2

js

文件开头添加

window.Promise = Promise

这一句即可,示例代码:

import 'jquery'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap'

// 将Promise抛出为全局对象
window.Promise = Promise
。。。
           

原理:当

babel

检查到

js

Promise

时,

transform-runtime

会将

Promise

做转换,然后将其抛出为全局对象即可达到跟

babel-polyfill

一样的效果。

参考资料

  • github上babel-runtime没有正常工作的讨论
  • I use ‘runtime’, but get Promise is not defined