你不知道的webpack和webpack-dev-server高級玩法

相信很多同學都知道webpack,畢竟是現階段最火的前端打包工具,現在要是不知道webpack,你可能都不好意思出去面試說你是前端工程師,面試官估計也會斜著眼心裡嘀咕:又是個頁面仔。webpack的基本用法我想大家應該都知道,你寫一個配置文件,然後通過webpack --config /path/to/your/config.js啟動webpack就可以進行打包,或者通過webpack-dev-server --config /path/to/your/config.js啟動dev-server,你就可以花式使用熱更替功能提高你的開發效率了。而我今天就為大家來講一講,webpack和webpack-dev-server的一些高級玩法。

把webpack作為一個node module使用

大部分情況下,我們都直接命令行啟動webpack進行打包,就可以滿足我們的需求。但畢竟計劃趕不上變化,有時候你會發現用命令行啟動webpack變得不是那麼方便。比如我們在調試react的服務端渲染的時候,我們不可能每次有文件更新,等著webpack打包完輸出到硬碟上某個文件,然後你重啟服務度去載入這個新的文件,因為這太浪費時間了,畢竟開發時你隨時都可能改代碼,而且改動可能還很小。

那麼要解決這個問題怎麼辦呢?我們可以在啟動nodejs服務的時候,順帶啟動webpack打包服務,這樣我們可以在nodejs的執行環境中拿到webpack打包的上下文,就可以不重啟服務但每次文件更新都可以拿到最新的bundle。那麼具體怎麼做呢?很簡單,看下面的代碼:

const webpack = require(webpack) const webpackConfig = require(/path/to/your/config.js) const compiler = webpack(webpackConfig) compiler.run((err, stats) => {/* ...處理結果 */}) // or compiler.watch({ // watch options }, (err, stats) => {/* ...處理結果 */})

通過給webpack傳入配置,可以得到一個webpack的compiler,你可以調用compiler.run來一次性調用webpack的打包服務,他接受一個callback方法,你可以在裡面處理他的打包結果。

同時你也可以調用compiler.watch來讓webpack監聽文件變化,每次更新打包結束都會調用你傳入的callback。而第一個參數是watchOptions,跟配置文件裡面的watchOptions是一樣的。

但是這樣做了之後呢,webpack依舊是把文件打包到本地磁碟,顯然在開發的時候我們並沒有這個需求,我希望的是提高打包速度,而寫入磁碟明顯是個低效率的操作,我們要避免這個問題。怎麼做呢?還在webpack為我們提供了一個配置項,我們可以指定webpack輸出的文件系統。

const MemoryFS = require(memory-fs)const mfs = new MemoryFS()compiler.outputFileSystem = mfs

memory-fs是一個在內存中存儲讀取文件的文件系統類庫,他的api和nodejs默認的fs一模一樣,所以直接給compiler.outputFileSystem之後,所有webpack輸出的文件都將存儲在內存裡面。而隨後,我們都可以通過mfs對象,讀取到這些文件。速度瞬間上了一個檔次有木有。其實webpack-dev-server內部也用了這個方法,他才能快速得幫我們更新代碼。

通過nodejs啟動webpack-dev-server

同樣的道理,我們有時候也需要在nodejs在啟動webpack-dev-server,而webpack-dev-server和webpack不同的是,他本身自己也會啟動一個服務,並監聽獨立的埠。但是我們也有辦法讓他不這麼做,我們可以讓只啟動我們自己的服務,但同時可以具備webpack-dev-server那些牛逼的功能,怎麼做呢?

我們要用兩個工具:webpack-dev-middlewarewebpack-hot-middleware,這兩個是express的中間件,如果你的服務使用express開發的,那麼你可以很方便的把這兩個工具集成到你的服務上,我們來看看怎麼做:

const express = require(express)const devMiddleware = require(webpack-dev-middleware)const hotMiddleware = require(webpack-hot-middleware)const app = express()app.use(devMiddleware(compiler, {/* dev config */}))app.use(hotMiddleware(compiler))// ...your server code here

這裡的compiler就是我們上面webpack生成的compiler,devMiddleware的config跟webpack配置裡面的devServer的配置基本類似,但是也有幾個不一樣的配置,具體可以移步這裡查看詳細api

但是這樣還不能實現熱更替功能,在使用hotMiddleware的時候,我們需要在我們webpack配置的entry中加入一個文件webpack-hot-middleware/client,這是一共在客戶端跟hotMiddleware進行通信的js,有了它之後,我們客戶端才能接收到新的代碼並覆蓋老的代碼。

你以為這樣就結束了嗎?還有呢

雖然通過上面的方式我們可以只起一個服務,但是這也有弊端,就是webpack的打包服務要隨著我們重啟node服務而重啟,而總所周知,如果你的前端應用很複雜,那麼webpack打包的速度會很慢,重啟webpack的成本還是很高的,如果你經常要改服務端的代碼,那這就不划算了。那有沒有辦法能把這兩個服務分開,但又是在node中啟動呢?

答案當然是有的,只要你有需求,沒有你解決不了的問題,前提是你敢想敢做

const WebpackDevServer = require(webpack-dev-server)const devServer = new WebpackDevServer(compiler, {/* devServer config */})devServer.listen(/* port */)

這樣子你就可以通過nodejs啟動webpack-dev-server了

這是在webpack-dev-server的文檔中沒有提到的,其實他也是可以直接作為一個node module使用的。

當然如果你的express server和dev server都寫在一個js入口文件中啟動,那麼你每次修改服務端代碼,還是順便會重啟dev server。這時候如果你要區分,可以把這兩個入口文件分開,然後在一個腳本中通過child_process分別啟動兩個服務,然後在這個腳本中控制這兩個服務什麼時候該重啟,這一塊我就不深入講了,大家可以自己去研究一下,只要知道了上面這些方法,你就可以隨意控制你的服務在何時啟動,又在何時結束。

以上就是webpack和webpack-dev-server的一些高級玩法,當然我這裡只是拋磚引玉,webpack太過複雜,如果要把每個細節寫清楚估計能寫很厚一本書。寫這篇文章的用意更多是希望大家能拋開很多流水線化的編程習慣,去擁抱變化,每一個強大的工具或者框架總有各種等著你去挖掘的用法,你只有往深入去研究,才能解鎖更多姿勢。

作者: Jokcy

鏈接:imooc.com/article/21713

來源:慕課網

本文原創發佈於慕課網 ,轉載請註明出處,謝謝合作!


推薦閱讀:

阿里雲前端工程化方案dawn
React學習資源匯總
bb學習 Vue 你需要知道的 webpack 知識(三)
Webpack 的核心開發者 Sean Larkin 入駐 SegmentFault 了

TAG:webpack | 前端开发工具 | 编程 |