提及ugilfy,這是目前前端工程化裏最重要的夥伴之一,經過對代碼的壓縮混淆,它給咱們帶來了多種好處:前端
而前端工程化的象徵——webpack
,從1.0時期起就內置了uglify插件,簡單的配置便可使用該功能。webpack
webpack 1.0~3.0均內置的插件,它伴隨前端工程的服役時間最長,同時期也沒有太多的競爭者,Closure
一直被批評過於激進,使用者寥寥。git
可是,它有一個從誕生起就伴隨的缺陷,僅支持ES5代碼。隨着瀏覽器的兼容性需求愈來愈低,不少非現代瀏覽器都已經逐步被市場淘汰,chrome近幾年每一年都會升4個大版本。github
慢慢的,原生的簡潔ES6代碼已經能夠在瀏覽器裏運行了,這時候uglify-js
就顯的有點笨重。對於ES5代碼再壓縮,可能也比不上直接輸出ES6代碼呀。web
此外,還有一個危險的信號:chrome
在前端界,你們都會去研究和討論類庫的實現,但對於工程上的工具項目,卻知之甚少。對於開源項目,輸入越多,它越健壯;相反的,關注的少,場景輸入少,項目變得黑盒化的同時,也埋下了致命bug的種子。前端工程化
在時代推進下,迫切須要uglify-js
能夠解析ES6代碼,因而uglify-es
誕生。webpack 4.0隨着自身內部的一次大革新,將uglify-es
內置,並於今年初面世。api
可是。。。我用了還不到半年就遇到一個致命bug。瀏覽器
詭異的是,由於沒有深究uglify源碼,構建出的簡單示例並不會出現該問題。網絡
示例代碼以下:
// Parent.jsx
import Child from './Child'
class Parent extends React.PureComponent {
onChange = () => {
// 觸發rerender
}
render() {
return <div><Child onChange={this.onChange} /></div> } } // Child.jsx class Child extends React.PureComponent { componentWillMount() { fetch('/api').then(this.props.onChange) } render() { return <div /> } } 複製代碼
最終壓縮後的代碼形如:
// Parent.js的render函數
return React.createElement(
'div',
null,
React.createElement(class Child extends PureComponent {})
)
複製代碼
能夠看到,Child因爲只被一處引入,因此再也不是獨立模塊,甚至被處理成了內聯。
在js語法裏這樣處理,彷佛沒什麼問題,可是當處理的是包含生命週期的組件時,就觸發了嚴重的問題,該Child組件會被不斷的銷燬和建立,引發死循環。
因爲部分「玄學」緣由,我沒找到穩定復現該bug的寫法。。。
解決方式是在uglify配置中關閉reduce_vars和reduce_funcs:
uglifyOptions: {
compress: {
reduce_vars: false,
reduce_funcs: false,
},
}
複製代碼
這僅僅是我碰到的問題,搜一下uglify-es
的bug,會發現,這項目確實有點嗶——(消音),它已經從並肩做戰的戰友成功升級成4v6了。。。
隨着uglify-es
再也不維護(我用着的時候都不知道= =!),webpack也悄悄的更改了內置uglify依賴:
uglify-es is no longer maintained
其實還有不少項目也進行了調整:
Switch minifier from uglify-es to terser
看樣子terser是從uglify-es
fork出來的項目,目前看來,該項目維護者很是活躍,在不少uglify-es
的bug issue下都會看到他宣傳terser沒有bug的身影~
但願該項目能夠從新贏回開發者們的信任,讓前端工程更完善,效率更高!