使用webpack實現react的熱更新
- 2019 年 10 月 10 日
- 筆記
單獨把熱更新拿出來,是因為它的配置稍微比較繁瑣。網上也各說風雲,這裡就上個demo,說下個人的實現吧
前言
項目結構大致如下:
app 中自然就是源代碼,app/index.js是最外層的js文件。因為涉及到是熱更新,所以當然是在我們的 webpack.dev.js 文件下操作。
webpack的常規配置這裡不再贅述。項目的打包主要通過 server.js 文件
webpack-dev-middleware
webpack dev server 是一個開發服務器,內建 webpack 使用的 live reloading 功能。
這裡的使用其實就是當做一個Express中間件來使用的,用於服務webpack的包。
安裝webpack-dev-middleware
npm i webpack-dev-middleware --save-dev
配置webpack-dev-middleware
這裡我直接粘貼了 server.js 的代碼
const Webpack = require('webpack'); const WebpackDevMiddleware = require('webpack-dev-middleware'); const config = require('./webpack.dev');const app = new (require('express'))(); const port = 3000;const compiler = Webpack(config); app.use(WebpackDevMiddleware(compiler, { publicPath: config.output.publicPath, stats: {colors: true}, lazy: false, watchOptions: { aggregateTimeout: 300, poll: true }, }));app.get('/', function (req, res) { res.sendFile(__dirname + '/build/index.html'); });app.listen(port);
通過運行server.js即可進行打包,因為webpack提供了express的middleware,讓我們可以處理靜態資源文件而不需要使用express.static。而打成這像功能,就是我們配置的webpack-dev-middleware。
簡單說下上面devMiddle的配置:
- publicPath:這裡我導入的是webpack中的輸出publicPath,注意:這是一個必填項。其實就是告訴index.html頁面相對於瀏覽器地址怎麼拿到他要拿到的js。
- stats:非必填項,這裡的color,就是指console統計日誌帶顏色輸出。
- lazy:指示是否懶人加載模式。true表示不監控源碼修改狀態,收到請求才執行webpack的build。false表示監控源碼狀態,配套使用的watchOptions可以設置與之相關的參數。
小結
到這一步,我們不需要再運行webpack命令去打包文件了,我們可以直接
node server.js
然後修改我們的源碼文件你可以在控制台中發現,他會自動打包。
打開瀏覽器,127.0.0.1:3000 可以看到我們的的項目,修改後刷新就可以看到修改後的效果。
當然,我們任務還沒結束。目前只是實現了不需要手動打包了,但是還是要手動刷新哇!
熱更新
熱更新,就是讓我們更改完源碼後,不需要再瀏覽器上手動刷新即可看到效果。解放我們的雙手有木有
安裝插件
npm i --save-dev webpack-hot-middleware
修改配置文件
這裡我們需要修改三個地方的配置文件:webpack.dev.js server.js index.js
server.js 添加一個中間件
const WebpackHotMiddleware = require('webpack-hot-middleware'); ... app.use(WebpackHotMiddleware(compiler));
webpack.dev.js
入口文件部分修改如下:
entry: { index: [ 'react-hot-loader/patch', 'webpack-hot-middleware/client', 'babel-polyfill', pathLib.resolve(ENTRY_PATH, 'index.js') ], vendor: ['react', 'react-dom', 'react-router-dom'] },
插件部分添加上 HotModuleReplacementPlugin
new webpack.HotModuleReplacementPlugin()
一切都給你打包好了,得告訴前端來接收下: index.js 部分:
if(module.hot){ module.hot.accept(); }
小結
這個時候當我們再次運行
node server.js
的時候,啟動瀏覽器,可以看到當我們修改源碼文件後,瀏覽器會自動的刷新的。
問題
代碼如上。當我點擊button,state也會隨之增加。但是這個時候如果我修改了某一個文件內容,可以看到我瀏覽器的確刷新了。但是!state卻重置到了1,這並不是我們想要的。
熱更新保留組件狀態
之前的我們只需要安裝 babel-preset-react-hmre ,然後配置 .babelrc 文件就可以完美解決了。但是目前這個插件已經放棄維護了。推出了 react-hot-loader 插件。目前還都是在測試版。但是可以使用。
這裡我們使用的版本時 3.0.0-beta.6
安裝插件
npm i --save-dev react-hot-reload
修改配置文件
.bebelrc
{ "presets": ["es2015","react","stage-0","env"], "plugins": ["react-hot-loader/babel"], "env": { "production":{ "preset":["react-optimize"] } } }
在plugins中添加 react-hot-loader/babel
webpack.dev.js entry 部分修改:
entry: { index: [ 'react-hot-loader/patch', 'webpack-hot-middleware/client', 'babel-polyfill', pathLib.resolve(ENTRY_PATH, 'index.js') ], vendor: ['react', 'react-dom', 'react-router-dom'] },
修改index.js文件
import {AppContainer} from 'react-hot-loader' ... render( <AppContainer > <IndexApp/> </AppContainer> , mountNode );
注意 3.0.0-beta.6 通過component屬性傳組件也是可以的。
完結
至此,我們就已經實現了,修改源碼後 ,瀏覽器自動刷新的效果了,並且還保留了刷新前的state狀態。
說明
這是我寫一個博客系統的demo(項目還在進行中)配置中的一部分。
項目地址: https://github.com/Nealyang/React-Express-Blog-Demo
喜歡的朋友可以關注公眾號,交流更多前端知識總結demo實戰,讓你我共贏!