知識要求
-
的基礎知識(推薦阮一峰的babel入門教程)babel
- 充分了解
與babel-plugin-transform-runtime
的作用(推薦github項目首頁)babel-runtime
-
基礎用法(https://webpack.js.org/)webpack2
-
中webpack2
作用,babel-loader
異步加載import
問題說明
webpack
+
babel-loader
transform-runtime
正常來講應該能實作在沒有原生支援
Promise
的浏覽器(如
IE
)下正常運作,但是實際在
IE11
下,還是提示
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
,還真找到了原因,如下圖所示:
圖檔來源: 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