天天看點

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