前端構建工具webpack有什麼缺陷?
發現最近似乎webpack比較火,和requireJS和browserify相比,它也確實有一些獨到的優勢。
但是有沒有哪些場景是不適合用webpack的嗎?比如非SPA(Single Page Application)網站是否不適合webpack?另外它的工具鏈是否有Grunt/Gulp那麼成熟呢?大家在用的過程中遇到過哪些坑?
充斥著大量名字類似 what-the-fuck-is-this-plugin 的插件,以及這個插件附帶的一千種配置和一萬種副作用,以至於每次出現打包的問題都會產生哲學三問:
- 這個插件幹了什麼?
- 我的配置有錯誤嗎?
- 這個插件真的沒有bug嗎?
不知道是不是我的姿勢不對,Webpack 目前在做 Server-side render/Isomorphic/Universal 時真是坑得一比……
好不容易,你終於喜歡上了在 .js 里 require 一切資源的快感,無論 CSS,Sass 還是圖片,Webpack 都會用覆寫 require() 的黑魔法幫你搞定……現在你想在 Node 里也搞這些了,哪有這樣的 require 給你用啊!Build 出來的東西直接扔到 Node 里你就等著各種報錯吧……
為什麼會報錯?就算你配置成 `target: node` 還把 `CommonsChunkPlugin` 關掉,你要不要用 css-loader? css-loader 代碼里一堆堆的 document 和 window 你在 Node 環境哪裡找 DOM 和 BOM 啊;當然,url-loader 這種瀏覽器無關的倒是仍然可以用……
官方的案例 webpack/react-webpack-server-side-example · GitHub 簡直就是自己 hack 自己好嗎,css-loader 不能用了自己封裝一個然後把行內樣式吐到 react render 里,chunk 的 filename 加 hash 完拿不到了自己去 stats 里取,真開心……人家自己都說了:This example is meant as inspiration to develop an framework that can do server-side rendering of react with webpack. You shouldn"t use the code, only the idea.
至於這篇 Backend Apps with Webpack (Part I) ,教我們如何 hack 掉 node_modules 的問題,教我們如何把所有的 css 文件都忽略掉(喂)……最後還開心的問你「That wasn"t hard, was it?」,Fxxk off dude!
這大概也是為什麼在網上搜 Isomorphic React blah blah 基本都是用 gulp + browserify 來做構建工具的原因吧:webpack 在設計之初主要還是沖著瀏覽器端(尤其是 SPA)去的,牛逼在人家對依賴的理解上,也因此才打出 Unversial Bundler + Code Splitting + Load on demand 這種組合技;如果只是在 server 端用做工具流工具就毫無優勢了,強依賴靜態分析的做法在靈活性上被 gulp 與 browserify 這種小而美的工具完爆,比如你都不依賴一個 scss 你怎麼 transform 它,比如做持續集成需要 revision assets 用個 gulp-rev 好歹能給你吐出個 manifest 來給你做 map……當然畢竟 gulp 也就適合做那麼點事,主要還是對 webpack 萬物 require 的期望太高了……
說來說去,也就是處理靜態文件依賴的能力在 Server 端大打折扣了,只是編譯個 JSX/ES6 替代個 browserify 還是可以的,那 CSS 呢?老老實實當靜態文件搞吧,或者全部用 CSS in JS 就可以解決了……
哎呀我就是被坑了一晚上過來吐槽一下而已……以上太多黑魔法,
過於複雜了,很多時候會覺得怎麼突然就跑通了,然後配置就不敢改了。當然願意折騰的話,也可以多踩踩坑吧。
配置多的嚇人,devtool就有多少個值?還@#前綴。
另外輸出的文件實在是太丑了。沒壓縮都沒法讀。
以上。配置工程師血與淚的感悟。webpack的概念很牛逼,webpack的文檔很傻逼。
各plugin不管自帶的還是社區的文檔都不大好,看起來感覺你似乎應該是大師了,而且換個版本可能就出神秘bug,所以,摸出好使的配置之後,趕緊地,lock version,就用這個配置就用這些版本了,不要想太多,先搞個好使配置再說。1、如果沒有 babel, webpack 對 ES2015+ 的語法是不接受的,會提示用指定 loader
這意味著,在支持部分 ES2015 語法的 firefox 與 chrome 瀏覽器中能直接跑的代碼,無法用 webpack 編譯。
2、因為 webpack 是靜態編譯,需要在打包時就掃描到所有可能的模塊,所以想用 require(expression) 在運行時獲取模塊目前並不支持。
from 評論:
聽臨 :第二條,簡單的expression是可以被接受了,比如 require("/tests/" + x), 它會把 tests/ 下面的所有東西都打包一遍。3、由於 webpack 是為模塊化而生的工具,所以當你只想複製文件到另一個文件夾,順便對文件做一些文本補充、替換等工作,你用 webpack 不合適,用 gulp/grunt 更佳。這不算它的缺陷,而屬於 webpack 無法取代 gulp 的地方。
4、 webpack 的全局統籌使得你只改動一個文件里的一行代碼,也是整個項目全部重新分析與編譯,給各個模塊分配 webpack_id。
from 評論:
尤雨溪 : 模塊都是 cache 了的,只會重編譯改動的文件。這意味著,隨著項目複雜度的增加,編譯時長也會不斷增加。所以才有 webpakc_dev_server 之類的東西,但配置繁瑣,用起來也不美。
……暫時想到這些。最大的缺陷就是配置過於複雜..官網文檔混亂...但是,
像Vue這樣的MVVM框架,
官網還是推薦使用webpack+vue進行開發還是老老實實啃官網文檔吧用一次感覺跟做了一場外科手術似的
占坑 晚點來回答。
=======我是漂亮的分割線==========
好吧,占坑一年,慚愧慚愧。
既然題主說缺陷,那我就只說說缺陷。
1.文檔缺失,尤其中文文檔
長期以來webpack官方文檔和example匱乏,提供的一些例子都是很簡單那種,經常發現完全按照例子來配置但就是跑不起來,中文文檔就更不用說了,少的可憐。這個問題也直接導致下面的第2點。
當然,最近新版本的文檔 https://webpack.js.org/ 發布之後,可讀性有很大的改觀。
2.配置難難調試
稍微複雜一點的項目,如果使用webpack編譯,不經過一段痛苦不堪的配置調試過程是沒法正常跑起來的。這還沒完,在自己機器上跑起來之後可能到了另一個同事哪兒又報錯了等等。總之正如下面有人回答那樣,配置文件一旦跑起來,是根本不敢去改的,生怕又出錯。
webpack的錯誤提示也非常難看懂,基本不可能從錯誤很直觀的找到原因,長期以來碰到問題只能靠猜,你沒看錯,就是靠猜!!
3.編譯慢
經驗不足的同學很容易碰到這個問題,當然可以通過一些手段做優化,比如配置module的resolve、root等,使用happypack加速、dll提前編譯等等。但是筆者曾經嘗試過happypack,對編譯速度有提升但效果不明顯,dll的話我有按照官方文檔的做法去做,但是最終編譯出來又報了一些莫名其妙的錯(也有可能是代碼寫的有問題),總之心累,後來直接改成externals方式,全局script引入第三方庫。
4.對server-render不友好
webpack本質上還是靜態打包,意思就是打包完成之後其實文件的載入順序已經固定,只是被載入的時間不定而已。所以使用webpack原則上不存在按需載入之類的說法,code split其實是人工分隔,但是真實的按需載入場景豈是人工能枚舉完的 (下劃線這句話不太好解釋,也不想過多解釋,熟悉前端工程的人應該都明白啥意思)。
這方面FIS的做法比webpack要先進多了,具體請移步我的另一個回答:我想問下fis3和webpack有什麼區別?
在這裡我要說的對server-render不友好其實是指html的處理,webpack其實是通過在js里用require標記資源然後載入任意資源(css、圖片、fonts等等),但其實html文件才是頁面真實的入口,最終編譯出的js還是需要引入到html里,為了防止css懶載入導致頁面抖動,編譯完的css還需要從js裡邊提取出來放到html外鏈。
目前一般都是通過html-webpack-plugin來做這個事情,先搜集某個html所引用的靜態資源最終自動插入到html。這種方式對於前端渲染的應用沒有問題,但是對於server-render的那就不行了,因為server-render下html是作為模板由後端語言吐出,而開發模式下(例如webpack-dev-server)webpack是不會輸出任何文件的(開發環境webpack是將文件放到內存然後在路由層自動serve了),所以這會導致開發環境模板無法引用靜態資源。當然,有一種解決方案就是靜態資源不改變文件名稱,預先寫好路徑,開發環境和生產環境同名(即覆蓋式發布)。
react 的項目用 webpack 還不錯,目前非react 項目 還是以gulp+webpack 來搞,webpack僅被用來是代替 browerify 來做JS的模塊化
1. 配置多入口時,沒有glob的方式,需要額外處理。2. 目錄結構複雜時,file-loder裡面的path功能太弱,很多時候無法自定義構建後的目錄結構,只能放在一個目錄下。3. 源碼比較複雜,遇到問題看源碼,要花很長時間。
對於一個菜鳥來說,學習這種一次性配置文件的成本太大,用腳手架生成的配置文件升級的時候一臉懵逼,雖然有官方提示,但有時候一個小的配置錯誤要找半天。
當然是它是針對bundle的解決方案啊,http/2的年代我不願意bundle啊。。
其實答主對 webpack 的理解也不深,簡單地答一下自己的看法。我覺得 webpack 存在的一些問題也許和編譯器差不多:使用不當(比如優化過度),會導致一些意料之外的問題。
就像用 gcc 編譯你寫的 c++ 代碼,你使用了 -O3 的優化。結果你的代碼跑著跑著掛了,但換成 -O1,也許你的程序卻毫無問題。
在我看來 webpack 很黑盒,用起來很方便,但背地裡暗搓搓地做了很多優化,有時候遇到啥問題時,把優化關了看看也許就沒問題了。
說說今天遇到的一個小坑吧:
有這樣一段用於居中的 Less 代碼片段:.title {
margin-left: auto;
margin-right: auto;
.size(margin-top, 15px);
.size(margin-bottom, 15px);
}
稍微解釋一下,.size() 是個 mixin,可以把像素值翻譯成以 rem, vw, vh 為單位的數值,這樣就可以以 iPhone 5 的解析度來設計頁面,並適應其他的解析度。如果手機支持 vw, vh 則用這個單位,如果不支持,就退化成 rem 單位。
比如上面的代碼編譯成 CSS 的結果(可能)是這樣的:.title {
margin-left: auto;
margin-right: auto;
margin-top: 1.5rem;
margin-top: 2.6408vh;
margin-bottom: 1.5rem;
margin-bottom: 2.6408vh;
}
結果在手機上測試了一下,發現 iPhone 顯示的效果還行,Android 的兩個測試機顯示出的效果都是 .title 不居中了。
來探究一下原因,通過 webpack 優化後的 CSS 會變成這樣:.title {
margin: 2.6408vh auto 2.6408vh;
margin-top: 1.5rem;
margin-bottom: 1.5rem;
}
終於真相大白了,在安卓 4.3 及以下版本是不支持 vw, vh 單位的,所以在優化後的代碼中,第一條規則被忽略了;而用於居中的代碼也就一併被無視了。
所以使用一個工具的同時,也要花時間去了解它的原理。
(答主也屬於不夠了解的類型......?(? ???ω??? ?)?......)如果說 webpack 有缺陷的話,就是需要持久的學習,不斷的去更新版本 配置(webpack本身一直在改進,優化)。
Webpack 打包優化之體積篇
Webpack 打包優化之速度篇
我最不喜歡的構建工具就是幫你包辦一切的。webpack就是這樣一種工具。
webpack我覺得最大的亮點就是require anything和code splitting。
require anything 我還比較喜歡,可以去用來實現組件化,css, html, js等資源以組件的級別分離,但是沒有webpack也可以做到。webpack幫你生成了模塊化管理的代碼來實現require anything,就是幫你引入了類似seajs這樣的模塊化管理框架,減少了很多編碼工作。但我覺得這種保姆工作真是多餘,而且限制了項目架構的靈活性。code splitting 說到底已經是老梗,其實就是按需載入,然而webpack這保姆又幫你省了事,我在使用的過程發現生成的chunk還會有代碼冗餘-_-|||。
webpack的初衷就是為了大型SPA服務的,這個作者說的很清楚。webpack作為grunt的一個插件來用比較合適。
可能要習慣一切都在js中require,包括css,image等。
大js果然通吃一切哈項目大了首次編譯太慢……
1. 文檔爛。
2. 把所有的資源都 require 到 js 中,並不適合所有場景。
3. 1和2版本配置項不兼容,升級麻煩。
4. 沒有生成資源表,如果其他項目沒有用 webpack , 非同步載入模塊比較麻煩。
5. debug 依賴 source map, chrome devtool 首個斷點不能直接點,需要在代碼中加 debugger 關鍵字。
可以看 substack 的 gist browserify for webpack users 和它下面的評論
簡單來說,webpack 太複雜,是比較全面的解決方案(因此配置也比較複雜),而 browserify 只是一個核心,其本身也是由不同模塊組成的,更符合 unix 的干好一件事的哲學。用 webpack 的某些功能和 browserify 去比較是不太公平的,因為哲學不一樣。
browserify 核心代碼沒多少,都拆分成模塊了,你花一天時間大概過一篇,然後自己動手修改擴展需要的部分就好,這樣你能對你的項目有很強的把控。
而 webpack 是另一條路,相當於外包了前端構建這部分,雖然直接上手可能很方便,但是遇到坑的時候,或者需要自己實現一點什麼想法的時候,可能會比較困難和麻煩一點。感覺在使用webpack配置多入口的項目工程時,會遇上一些問題,比如無法保存項目結構路徑,生成的文件往往在同一級目錄下,使用webpack-dev-server時候多入口時候還沒找到合適的方法進行自動頁面刷新。
推薦閱讀:
※DocumentFragment真的能提高 JS 動態添加 DOM 的性能嗎?
※如何優化vue的內存佔用?
※能否用 JS 實現一個 CSS 解釋器?
※如何理解 Facebook 的 flux 應用架構?
※js中alert函數的實現原理是什麼?
TAG:前端開發 | JavaScript | 網頁應用 | Nodejs | webpack |