
Vue項目兼容IE11
Vue 不支持 IE8 及以下版本,因為 Vue 使用了 IE8 無法模擬的 ECMAScript 5 特性。但對于 IE9+,Vue 底層是支持。
由于開發(fā)過程中,我們經(jīng)常會使用一些第三方插件或組件,對于這些組件,有時我們需要做一些處理。下述主要闡述如何使用 vue-cli3 腳手架搭建的工程支持 IE11。
現(xiàn)象
IE11 打開 Vue 工程(Vue CLI)構(gòu)建而來出現(xiàn)空白頁,控制臺告警、報錯。
如:
- DOM7011: 此頁上的代碼禁用了反向和正向緩存
- HTML1300:進行了導(dǎo)航
- app.js 各種語法錯誤

browserslist
項目中 package.json 文件里的 browserslist 字段 (或一個單獨的 .browserslistrc 文件),指定了項目的目標(biāo)瀏覽器的范圍。這個值會被 @babel/preset-env 和 Autoprefixer 用來確定需要轉(zhuǎn)譯的 JavaScript 特性和需要添加的 CSS 瀏覽器前綴。
- @babel/preset-env:將你使用最新 JavaScript 語法,靈活的轉(zhuǎn)化為目標(biāo)瀏覽器所支持的 polyfill。
- Autoprefixer:PostCSS 插件,為瀏覽器增加前綴。
.browserslistrc
> 1%
last 2 versions
not ie < 11
Polyfill
默認的 Vue CLI 項目會使用 @vue/babel-preset-app,它通過 @babel/preset-env 和 browserslist 配置來決定項目需要的 polyfill。
默認情況下,它會把 [useBuiltIns: 'usage'](https://link.zhihu.com/?target=https%3A//new.babeljs.io/docs/en/next/babel-preset-env.html%23usebuiltins-usage) 傳遞給 @babel/preset-env,這樣它會根據(jù)源代碼中出現(xiàn)的語言特性自動檢測需要的 polyfill。這確保了最終包里 polyfill 數(shù)量的最小化。然而,這也意味著如果其中一個依賴需要特殊的 polyfill,默認情況下 Babel 無法將其檢測出來。
Vue CLI 文檔 中,提供了三種方式:
-
如果該依賴基于一個目標(biāo)環(huán)境不支持的 ES 版本撰寫: 將其添加到
vue.config.js中的[transpileDependencies](https://link.zhihu.com/?target=https%3A//cli.vuejs.org/zh/config/%23transpiledependencies)選項。這會為該依賴同時開啟語法轉(zhuǎn)換和根據(jù)使用情況檢測 polyfill。 -
如果該依賴交付了 ES5 代碼并顯式地列出了需要的 polyfill: 你可以使用
@vue/babel-preset-app的 polyfills 選項預(yù)包含所需要的 polyfill。注意es6.promise將被默認包含,因為現(xiàn)在的庫依賴 Promise 是非常普遍的。
// babel.config.js
module.exports = {
presets: [
['@vue/app', {
polyfills: [
'es6.promise',
'es6.symbol'
]
}]
]
}
提示:我們推薦以這種方式添加 polyfill 而不是在源代碼中直接導(dǎo)入它們,因為如果這里列出的 polyfill 在 browserslist 的目標(biāo)中不需要,則它會被自動排除
- 如果該依賴交付 ES5 代碼,但使用了 ES6+ 特性且沒有顯式地列出需要的 polyfill (例如 Vuetify):請使用 useBuiltIns: 'entry' 然后在入口文件添加 import '@babel/polyfill'。這會根據(jù) browserslist 目標(biāo)導(dǎo)入所有 polyfill,這樣你就不用再擔(dān)心依賴的 polyfill 問題了,但是因為包含了一些沒有用到的 polyfill 所以最終的包大小可能會增加。
我們采用了最簡單最直接(但是性能不是最好)的第 3 種方式!
第一步: 在 babel 的相關(guān)配置文件(babel.config.js、.babelrc 或 package.json 的 babel 字段任一)中,增加 "useBuiltIns": "entry" 信息。babel 7 版本以后,會有差異 -- Here
babel.config.js
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
If
useBuiltIns: 'usage'is specified in.babelrcthen do not include@babel/polyfillin eitherwebpack.config.jsentry array nor source. Note,@babel/polyfillstill needs to be installed.If
useBuiltIns: 'entry'is specified in.babelrcthen include@babel/polyfillat the top of the entry point to your application viarequireorimportas discussed above.If
useBuiltInskey is not specified or it is explicitly set withuseBuiltIns: falsein your .babelrc, add@babel/polyfilldirectly to the entry array in yourwebpack.config.js.
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
!!! 網(wǎng)上信息比較混亂,經(jīng)常出現(xiàn)幾種方式混用,并不合理!
第二步: 安裝 '@babel/polyfill' ,并在入口文件添加 import '@babel/polyfill'
$ npm install --save @babel/polyfill
main.js
import '@babel/polyfill'
注意,Babel 7.4.0 以后,該包已被棄用(deprecated)。官方推薦使用 core-js/stable 和 regenerator-runtime/runtime 替代。 -- @babel/polyfill
至此,我們已按照官方要求做了配置,重新啟動項目,發(fā)現(xiàn)依然不行?。?/strong>
transpileDependencies
默認情況下 babel-loader 會忽略所有 node_modules 中的文件。如果你想要通過 Babel 顯式轉(zhuǎn)譯一個依賴,可以在 transpileDependencies 選項中列出來。
下一步:使用 babel 對 elementUI、vuex(需要 Promise polyfill -- Here) 進行轉(zhuǎn)換。
按照 Vue CLI 提供的 3 種方案的第 1種:
如果該依賴基于一個目標(biāo)環(huán)境不支持的 ES 版本撰寫: 將其添加到
vue.config.js中的[transpileDependencies](https://link.zhihu.com/?target=https%3A//cli.vuejs.org/zh/config/%23transpiledependencies)選項。這會為該依賴同時開啟語法轉(zhuǎn)換和根據(jù)使用情況檢測 polyfill。
vue.config.js
transpileDependencies: [/node_modules[/\\\\](element-ui|vuex|)[/\\\\]/],
根據(jù)你的項目實際情況,此處 element-ui 可能不需要
proxy
針對 Proxy 對象進行 polyfill。
下一步: 在 index.html 文件中引入 es6-proxy-polyfill.js
<script src = "https://cdn.jsdelivr.net/npm/proxy-polyfill@0.3.0/proxy.min.js"></script>
根據(jù)項目實際情況,看是否有必要引入。如果引入,建議下載到本地,再引入。
至此,項目終于不是空白頁了?。?/strong>
但是,出現(xiàn)了大量排版錯誤!
css polyfill
由于我們項目中,大量使用了 CSS var() ,IE11 不兼容導(dǎo)致,思路相同,尋找相應(yīng)的 polyfill 即可。這里我們使用了 [css-vars-ponyfill](https://link.zhihu.com/?target=https%3A//github.com/jhildenbiddle/css-vars-ponyfill)
$ npm install --save css-vars-ponyfill
main.js
import cssVars from 'css-vars-ponyfill'
cssVars({})
大功告成!
總結(jié)
總之,所有的處理都是圍繞轉(zhuǎn)換成 IE11 可以兼容的方式去處理。對于 JavaScript 語法,即是對 babel 的控制;對于 CSS 語法,需要特定分析。