Webpack 4.0 學習(轉)


原文地址:https://segmentfault.com/a/1190000013608316javascript

官方已經發布了Webpack 4.0。有哪些新特性?有哪些改進?學着使用這個新版本,來構建更快的應用吧。
2018年2月25日星期天,Webpack 4.0向公衆發佈。代號爲Legato,是Javascript模塊打包器的一個主要版本。繼3.0版本以後,4.0花了將近八個月的時間來發布。在這篇文章中,覆蓋了Webpack 4.0的主要新特性以及改進和棄用。
Webpack是一個實用的JavaScript程序打包工具。它能把每一個模塊打包在至少一個文件中(一般只有一個文件),而且提供給瀏覽器運行。不管如何,Webpack不只僅是一個打包的工具。在各類loaders和plugins的幫助下,他能改變、縮小和優化文件,而後在瀏覽器上運行。它須要不一樣的資源,好比JavaScript、CSS、字體、圖片和HTML,而後將這些資源放進配置中,以便瀏覽器使用。Webpack的高明之處,在於它的總體。
好了,接下來簡單的介紹下webpack。
What’s new in Webpack 4.0?
1.再也不支持Node.js 4
再也不支持Nodes.js 4。由於源碼已經更新到一個更高的ECMAScript版本。html

Webpack的創始人之一,Tobias,建議用戶使用Node >= 8.94,以便使用最優的性能,是由於源代碼使用了JavaScript新特性。
2.告別CommonChunkPlugin,迎接SplitChunksPlugin
再見了,CommonChunkPlugin。臭名昭著(infamous)的CommonChunkPlugin被移除了,替代的是兩個新API:optimize.splitChunks和optimization.runtimeChunk。接下來我會解釋一下。
Webpack 4對塊圖進行了巨大改進,並使用了新的塊拆分技術。在新的改進過程當中,誕生了新的插件---SplitChunksPlugin。這個插件可以自動識別哪些模塊須要拆分爲啓發式的(heuristics),哪些須要拆分爲塊。另外,它還有一些極好的特性,好比在異步chunks的高效,以及把vender拆分紅不一樣的vender塊。
默認狀況下,Webpack 4會默認爲你建立共享塊。它經過optimize.splitChunks進行配置。optimization.runtimeChunk: true選項只在運行時在每一個入口添加額外的chunks。
3.支持WebAssembly
WebAssembly(wasm) 是一個新的移動的、高效加載的可供web使用的工具。它確實很快,開發者社區也很快擁抱了這個技術。所以,Webpack 4 已經提供了wasm的支持。在Webpack 4,你能夠引入和導出任何一個Webassembly的模塊。同時,你也能夠寫一個loaders來直接引入C++、C和Rust。
Note: WebAssembly 模塊只能在異步chunks中使用。
4.支持多種模塊類型
Webpack 4.0如今支持如下五種模塊類型:
?javascript/auto: Webpack 3.0在多種模塊系統中支持了這種模塊類型,好比CommonJS, AMD, ESM.
?javascript/esm: 只支持ECMAScript模塊
?javascript/dynamic: 只支持CommonJS 和AMD.
?json: 支持JSON數據,能夠經過require和import使用
?webassembly/experimental: 只支持WebAssembly,目前只是試驗階段
5.用mode點燃火焰
在此刻,對於這個新特性,我比任何都激動。webpack團隊引入了一個叫作mode的配置屬性來實現零配置(#oCJS)的模塊打包。mode能夠設置爲以下值:development和production。開箱即用,默認爲production。
production選項提供了一系列默認配置,它能夠:
?更小的輸出尺寸
?運行時的快速加載代碼
?省略只在開發時的代碼
?不暴露源代碼或者路徑
?快捷使用輸出assets
development選項提供了一下默認配置,它能夠:
?瀏覽器內調試更好的工具
?在一個快速的開發週期,更快的增量編譯
?更好的運行時錯誤提示
6.零配置模塊打包 #OCJS
到目前爲止,在webpack.config.js中須要定義一個entry point來爲app打包。然而,在Webpack 4.0,不須要定義這個erntry point,默認爲./src/index.js
並且,也不要定義輸出文件,缺省爲./dist/main.js
這種特性的重要意義在於處理小型項目的時候,不須要配置文件,只須要webpack。
Webpack 4不須要配置文件和入口文件。
Webpack 4 不須要任何配置文件,只要src/index.js文件。
7.更快的構建時間
Webpack的構建時間,和以前的主要版本相比,速度提高了98%。若是不信,能夠本身嘗試一下。你能夠這樣用:
npm i webpack --save-dev
或者使用yarn:
yarn add webpack --dev
在package.json中,你能夠看到devDependencies這一塊:
"webpack": "^4.0.0"
Webpack 3: 2405ms前端

 


webpack 4 :1388msjava

Webpack 4.x 是3.x版本的2倍多。
8.全新的插件系統
Webpack 4配備了全新整改的插件系統。這是一個全新的API,這些插件和hooks的API有如下的配置:
?hooks對象將全部鉤子做爲可擴展類的屬性
?多種Hook類如今會根據hook類型存在:sync, async, normal, bailing, waterfall, looping.
?在添加插件的時候,你須要提供一個名字
?在添加插件的時候,你能夠選擇插件的類型(sync/callback/promise)
?this.hooks = { myHook: new SyncHook(…) } 是註冊鉤子的新方法。建立一個新的Hook對象,做爲hooks對象的屬性
9.到webpack-cli的改變
webpack的cli(command line interface)已經移動到webpack-cli了,若是要使用CLI,你須要安裝webpack-cli。
廢棄和其餘的更新
?這些插件已經廢棄了,NoEmitOnErrorsPlugin, ModuleConcatenationPlugin, NamedModulesPlugin。如今你能夠分別使用optimization.noEmitOnErrors,optimization.concatenateModules和optimization.namedModules了。
?import()一直返回一個命名空間對象
?Wepack默認刪除不存在的分支
?如今使用System.import()會彈出警告的提示
?webpackInclud和webpackExclude在import()魔法註釋的支持下,提供了支持,當使用動態表達式的時候,他們容許過濾文件。
通往Webpack 5
Wepack 5正在進行幾項規劃。其中一些計劃包括:
?穩定的WebAssembly支持
?建立一個自定義的模塊類型,而且使Webpack提供支持的能力
?移除ExtractTextWebpackPlugin插件,並支持CSS模塊類型
?支持HTML模塊類型
?持久化緩存
結論:
如今你已經瞭解到Weboack的新功能了。Webpack擁有不少的新特性和改進,Wepack 的團隊對Webpack 4.0的遷移和合並有詳細指導,在接下來的幾周和一月內將會推出。對Webpack很陌生?我寫了一篇模塊打包器的簡單介紹。Sean Larkin在Webpack Academy也有一些很是棒的Webpack課程。node

精讀《webpack4.0 升級指南》
轉自https://juejin.im/post/5aafc6846fb9a028d936f97c
本週精讀的是 webpack4.0 一些變化,以及 typescript 該怎麼作才能最大化利用 webpack4.0 的全部特性。
1 引言
前段時間嘗試了 parcel 做爲構建工具,就像農村人享受了都市的生活,就再也回不去了同樣,發現無配置真是前端構建工具的大趨勢,用起來很是方便快捷,不再想碰 webpack 的配置了。
但是實踐一段實踐後,發現 parcel 仍是不夠成熟,主要體如今暫時不支持一些 rollup 優秀特性:Tree shaking、Scope Hoist,大型項目打包速度反而比 webpack3.0 慢。因爲筆者徹底零配置,當發現構建速度急速降低時,天然把矛頭指向了 parcel :p.
就在前幾周,webpack4.0 發佈了,也擁抱了零配置,我想,是時候再回到 webpack 了。但是,文檔好少,怎麼遷移呢?
就在這幾天,webpack 文檔發佈了 4.0 版本,雖然遺留了大量舊文檔,不過也足夠參考了。
2 精讀
筆者嘗試了?webpack node api,嘗試了好久,發現被坑了。文檔裏隻字未提?mode?模式,4.0 環境下?compiler?老是提示沒有?mode?的 warning。
讀了一些文檔,發現 webpack4.0 大力度宣傳的是 cli 方式啓動,裏面提到了最重要的?webpack --mode?模式,可見 webpack4.0 更推崇的是讓開發者使用高度封裝的 cli,而不是使用 node 方式開發(那 node 文檔也應該更新呀)。筆者又看了一圈,發現?webpack-dev-server?的 webpack 版本升到了 4.0,ts-loader?也升級到了 4.0,可能生態已經所有準備好了。
使用 webpack cli、webpack-dev-server cli
安裝?webpack^4.1.1?webpack-cli^2.0.10?webpack-dev-server^3.1.0,以及建立一個公共配置文件?webpack.config.ts:
export default {
entry,react

output,webpack

module: {
rules
},es6

resolve,web

resolveLoader,typescript

devServer: { https: true, open: true, overlay: { warnings: true, errors: true }, port }}記得用?tsc?轉換爲?webpack.config.js?做爲 cli 入口。開發模式下使用?webpack-dev-server:webpack-dev-server --mode development --progress --hot --hotOnly --config ./webpack.config.js生產環境 build 使用?webpack:webpack --mode production --progress --config ./webpack.config.js開發/生產模式,都以?webpack.config.ts?做爲配置,其中?devServer?項僅在開發模式下,對?webpack-dev-server?生效。一旦開啓了?--mode production,會自動開啓代碼壓縮、scope hoist 等插件,以及自動傳遞環境變量給 lib 包,因此已經不須要?plugins?這個配置項了。同理,開啓了?--mode development?會自動開啓 sourceMap 等開發插件,咱們只要關心更簡單的配置,這就是 4.0 零配置的重要改變。mode=production,?mode=development?具體內置了哪些配置,能夠參考這篇文章:webpack 4 終於知道「約定優於配置」了。偏偏有意思的是,webpack4 這麼作,就是不想咱們浪費時間瞭解這些機制,社區應該會慢慢習慣零配置的開發方式。固然,雖說零配置,但配置文件基本三板斧仍是很是有必要配置:entry?output?module。咱們可能還要給配置文件傳一些參數,好比定製多種開發模式的入口,經過?--env?傳遞:webpack-dev-server --mode development --env.entry ./src/main.tsxwebpack.config.ts?接收:const entry = yargs.argv.env.entry使用 typescript + webpack簡單來講,只須要?ts-loader?就夠了。在?webpack.config.ts?中增長新的?rules:{ module: { rules: [{ test: /\.(tsx|ts)?$/, use: ["ts-loader"] }] }}注意?tsconfig.json?中模塊解析策略使用:?"module": "esnext"。緣由是 webpack 須要 es6 import 語句,才能進行 tree shaking 或者動態 import 優化,咱們再也不讓?ts-loader?包辦模塊設置,換句話說,咱們採用白名單方式看待?typescript?以及?babel,只讓他作咱們須要的工做,剩下的丟給 webpack 處理,能夠得到最大程度性能優化。若是僅使用 webpack + typescript,建議將 ts 編譯輸出模式調整爲?es3,由於 webpack 自帶的壓縮工具對 es6 語法還存在報錯,並且也不會作兼容處理。使用 typescript + babel + webpcak注意處理順序,ts -> babel -> webpack。由於多出了 babel,咱們將 ts 編譯兼容模式關閉:"target": "esnext",模塊也不要解析:"module": "esnext",ts-loader?僅僅將 typescript 代碼轉換成 js,其餘一切優化都不要作,將 esnext 原生代碼直接傳給 babel 處理。babel 這一層的職責是對代碼進行兼容處理,不要壓縮,也不要把 import 轉成 require。筆者發現 babel 直接解析 import 代碼會沒法處理,所以須要?stage-2?preset:{ presets: [ ["env", { modules: false, }], ["stage-2"] ], plugins: [ ["transform-runtime"] ], comments: true}從上面配置能夠看到,babel 這層對 esnext 的代碼進行了瀏覽器兼容處理(env 插件),直接透傳?import(stage-2 插件讓 babel 識別 esModule),以及支持 async await(transform-runtime) 插件。原本想用 env 替代 transform-runtime 的功能,筆者暫時沒有查詢到可行方式,歡迎讀者補充。另外要容許 babel 保留註釋(comments: true),由於 webpack import 支持自定義 chunkName 是經過註釋的方式:import(/* webpackChunkName: "src" */ "./src")配合?react-loadable?使用更佳:Loadable({ loader: () => import(/* webpackChunkName: "src" */ "./src"), loading: (): any => null})由於?react-loadable?讓頁面按 chunk 方式打包,而 webpack 又會自動 picke shared chunks,配合給每一個 page chunks 經過?webpackChunkName?定義名稱,webpack 能夠給每一個共享 chunks 更加可讀的名字,好比:vendor~src,about,login,你就知道這個是?src?about?login?三個頁面間公共模塊。可能已經有人看出瑕疵了,給每一個文件增長?webpackChunkName?註釋既麻煩又不優雅,並且只要有一個開發者沒有加這個註釋,上面說的可讀 chunks 可能就缺乏了某個模塊名。這就要筆者以前一篇精讀來看了:精讀《Rekit Studio》,項目能夠經過約定的方式定義頁面,入口文件經過 cli 自動生成,不就既減小業務代量,又統一加上了?webpackChunkName?嘛?這裏小小安利下集成了這個思路的項目腳手架?pri,使用了 ts + babel + webpack4.0,上述的小優化也是內置的功能之一。webpack4 帶來的是適配成本的大幅優化社區彷佛有部分聲音在抱怨,webpack 又發新版本,咱們又要適配一輪。其實 webpack 這麼作偏偏沒有帶來適配成本,出問題的在於咱們對 webpack 的使用方式與理念。若是咱們開始就將 webpack 看成一體化打包方案,開發調試使用?webpack-dev-server cli,開發環境編譯使用?webpack cli,那麼 webpack4 其實只是補充了開發環境這個最重要的配置變量而已。類比?parcel?的兩個命令:parcel index.htmlparcel build index.html對應:webpack-dev-server --mode developmentwebpack --mode production因此 webpack4 幾乎是有史以來最方便使用與遷移的版本,前提是使用思惟得正確,捨得將編譯環節全權交給兩個官方的 Cli。3 總結只要合理的使用 typescript、babel,讓各自只發揮最小功能,將原生的模塊化代碼拋給 webpack,再配合?--mode production?配置,webpack 會自動開啓一切可能的插件優化你的項目,而咱們再不須要閱讀形形色色的 webpack 插件了,更使人激動的是,隨着 webpack 版本升級,優化會不斷升級,而咱們只要留着?--mode?參數,不須要改一行配置。總結起來,就是不用關心優化相關的配置,咱們只須要配置業務相關的?entry?output?module,這就是 webpack4.0.我之前爲了實現第一次編譯完後當即打開瀏覽器的功能,寫了一共 200 行的?customCompiler?以及?format-webpack-message,並且利用 koa 開了一個 server,利用 await 和 flags 等待第一次編譯完的時機,並利用?opn?庫打開網頁。其實用 cli 只須要?webpack-dev-server --open。隨着新的一波零配置浪潮,真的不該該在編譯配置上花那麼多時間了。4 番外 - prefetch讀者自習閱讀就會發現,這不是一篇單純 webpack4 升級指南,仔細閱讀能夠發現文中蘊藏的一些工程優化思路。文章末尾再給一波福利,分析一下 prefetch 優化是什麼,以及怎麼作。現代瀏覽器支持瞭如下兩種語法:<link rel="preload" /><link rel="prefetch" />兼容性本身查?Caniuse,筆者重點在功能上。preload?收集當前用到的資源,prefetch?收集將來用到的資源。頁面本質上也是將來一種資源,若是認爲用戶會點擊另外一個頁面(若是對產品沒自信,或者 pv 太低能夠忽略這個功能),就能夠用?prefetch?讓瀏覽器在空閒時間下載下一個頁面的 chunk 文件。前端包體積優化效率通常和用戶體驗是違背的,既然下一個頁面在另外一個 chunk 中,用戶點擊後必然會產生 loading。但是若是結合了?prefetch,魚和熊掌就兼得了(正經常使用戶不可能頁面還沒加載完就馬上點按鈕跳頁,因此惟一的缺點幾乎不會對正經常使用戶產生影響)。api 有了,那麼最大的問題就是,當前頁面怎麼知道要加載哪些 chunks?通常兩種作法:全量模式?使用好比?preload-webpack-plugin?插件,將全部生成的 chunk 都做爲?prefetch?資源,在全部頁面中。幾乎全部規模的項目都不會產生過多的 chunks,因此這個方案理論上不夠優雅,但能解決實際問題。按需模式,是理論和實踐雙重優雅的方案,是否要這麼作取決於您是否有代碼潔癖。方法是提供一個定製的?Link?標籤,根據 URL 地址按需生成?prefetch?標籤。這種方案最大缺陷是,若是用戶不按照約定使用內置的?Link,prefetch?規則將會無效。

相關文章
相關標籤/搜索