這篇文章不那麼有趣,只是解決了一個bug
。但對我來講,因爲後面還要用Vue
做很多項目,而且可以預見幾乎每一個項目都會遇到這個問題,所以記錄在案是有用的。
一個bug
你用Vue
做了一個單頁面應用,它在一切設備上都工作正常,但是突然有一天,你的測試和你說,這個網站在iOS 10
上跑不起來,怎麼辦?
於是你打開你電腦上的Chrome
瀏覽器,工作正常;打開Safari
瀏覽器,工作正常;打開iOS 11
手機,工作正常;打開各種安卓手機,工作正常。但是在iOS 10
的手機上,不論是微信瀏覽器,還是Safari
瀏覽器,都只能看見一個白白的屏幕。
於是你把手機連上電腦,在電腦端的Safari
裏,看到了如下的錯誤:
SyntaxError: Cannot declare a let variable twice: 'e'.
可是你沒有寫過這樣的代碼,你怎麼可能把一個名爲e
的變量定義兩次?你打開代碼,看到了這樣美麗的代碼:
let e = e => {
console.log(e);
for (let e of [1, 2, 3])
console.log(e);
};
雖然這段代碼看上去比較奇怪,但是語法上有任何問題嗎?哥就願意定義一個名爲e
的函數,而這個函數的唯一入參名稱也爲e
,並且哥的for
循環體裏還願意再定義一個名稱爲e
的變量,es6
的變量作用域允許我們這樣做,此e
和彼e
互不干擾,不對嗎?況且很顯然,這段代碼不是人寫的,而是我們在執行npm run build
的時候編譯產生的。
其實我們都沒有錯,我們也沒寫錯,uglify
也沒搞錯,錯的是Safari
本身。他們在第十七萬一千零四十一號bug中承認了自己的錯誤:
We incorrectly throw a syntax error when declaring a top level for-loop iteration variable the same as a parameter
當你定義一個與參數同名的for循環迭代變量時,我們錯誤地認爲這是一個語法錯誤。
看,多麼謙遜的態度。所以你也不用太糾結於一個白屏幕,只要找到解決方法就好了。方法其實很簡單:
- 進入
build
文件夾; - 找到
webpack.prod.conf.js
文件; - 在
UglifyPlugin
的定義裏添加關於mangle
的選項,使它變成下面這個樣子:
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
},
mangle: {
safari10: true
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
然後這個世界就太平了。
爲了避免所有這些不必要的麻煩,我給vue-cli
提的一個PR
已被接受,在工具裏缺省加入了這個選項,這樣大家以後就不會遇到這個問題了。
關於這個bug
的問題描述在這裏,解決方案在這裏,給vue-cli
提的PR
在這裏,供深挖細掘的人蔘考。
另一個bug
實際上,除此之外,還有另外一個bug
也會影響到vue
網頁在iOS 10
上的展現,特別是當你用到廣爲流傳的Swiper插件的時候。這是因爲Swiper
插件中用到了ES6
的語法a = b ** c
,a
是b
的c
次方,而iOS 10
的Safari
裏不認識這樣的語法,認爲這是一個錯誤,所以你需要讓Swiper
經過babel
的包裝,而缺省狀態下babel
是不對node_modules
裏的模塊進行編譯的。相關的issue
見這裏。
解決方法是在項目根目錄下新建一個文件vue.config.js
,在裏面添加如下語句:
module.exports = {
chainWebpack: config => {
config.rule('js').include.add(/node_modules\/(dom7|swiper)\/.*/)
}
}
至止爲止,通常情況下你的vue
網頁已經可以完美地在iOS 10
上的Safari
裏展現了。