摘要:在前后端分離的前端項目開發(fā)中經(jīng)常用到。是的一個中間件。即是一個重要的功能。配置先來在配置文件中引入添加一個和通信的客戶端添加應用入口文件在插件中引入在我們的開發(fā)環(huán)境中是這樣配置的。
原文鏈接
此文是我同事寫的,搭建Express結(jié)合Webpack。以下是正文,后面我會附上我的解讀
本篇文件主要講結(jié)合 Webpack 和 Express 實現(xiàn)前后端熱更新開發(fā),如果你還不太了解webpack推薦閱讀
webpack 官網(wǎng)文檔
Webpack dev server 是一個輕量的node.js express服務器,實現(xiàn)了 webpack 編譯代碼實時輸出更新。在前后端分離的前端項目開發(fā)中經(jīng)常用到。不過這篇文章應該不會講到它。
webpack dev middlewareWebpack dev middleware 是 WebPack 的一個中間件。它用于在 Express 中分發(fā)需要通過 WebPack 編譯的文件。多帶帶使用它就可以完成代碼的熱重載(hot reloading)功能。
特性:
不會在硬盤中寫入文件,完全基于內(nèi)存實現(xiàn)。
如果使用 watch 模式監(jiān)聽代碼修改,Webpack 會自動編譯,如果在 Webpack 編譯過程中請求文件,Webpack dev middleware 會延遲請求,直到編譯完成之后再開始發(fā)送編譯完成的文件。
webpack hot middlewareWebpack hot middleware 它通過訂閱 Webpack 的編譯更新,之后通過執(zhí)行 webpack 的 HMR api 將這些代碼模塊的更新推送給瀏覽器端。
HMRHMR 即 Hot Module Replacement 是 Webpack 一個重要的功能。它可以使我們不用通過手動地刷新瀏覽器頁面實現(xiàn)將我們的更新代碼實時應用到當前頁面中。
HMR 的實現(xiàn)原理是在我們的開發(fā)中的應用代碼中加入了 HMR Runtime,它是 HMR 的客戶端(瀏覽器端 client)用于和開發(fā)服務器通信,接收更新的模塊。服務端工作就是前面提到的 Webpack hot middleware 的,它會在代碼更新編譯完成之后通過以 json 格式輸出給HMR Runtime 就會更具 json 中描述來動態(tài)更新相應的代碼。
先來在webpack配置文件中引入
var webpack = require("webpack"); var HotMiddleWareConfig = "webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000" module.exports = { context: __dirname, entry: [ // 添加一個和HotMiddleWare通信的客戶端 HotMiddleWareConfig, // 添加web應用入口文件 "./client.js" ], output: { path: __dirname, publicPath: "/", filename: "bundle.js" }, devtool: "#source-map", plugins: [ new webpack.optimize.OccurenceOrderPlugin(), // 在 webpack 插件中引入 webpack.HotModuleReplacementPlugin new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ], };
webpack-hot-middleware example webpack.config.js
在我們的開發(fā)環(huán)境中是這樣配置的。getEntries 是自動根據(jù)我們規(guī)則獲取到入口文件并加上 webpack hot middle 配置。
var webpack = require("webpack"); var path = require("path") var merge = require("webpack-merge") var baseConfig = require("./webpack.base") var getEntries = require("./getEntries") var publicPath = "http://0.0.0.0:7799/dist/"; var hotMiddlewareScript = "webpack-hot-middleware/client?reload=true"; var assetsInsert = require("./assetsInsert") module.exports = merge(baseConfig, { entry: getEntries(hotMiddlewareScript), devtool: "#eval-source-map", output: { filename: "./[name].[hash].js", path: path.resolve("./public/dist"), publicPath: publicPath }, plugins: [ new webpack.DefinePlugin({ "process.env": { NODE_ENV: ""development"" } }), new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin(), new assetsInsert() ] })Express 中的配置
在 Express 的配置主要就4個步驟:
引入 webpack 的配置文件和 生成 webpack 的編譯器
將編譯器連接至 webpack dev middleware
將編譯器連接至 webpack hot middleware
定義 express 配置
var http = require("http"); var express = require("express"); var app = express(); app.use(require("morgan")("short")); // ************************************ // This is the real meat of the example // ************************************ (function() { // Step 1: 引入 webpack 的配置文件和 生成 webpack 的編譯器 var webpack = require("webpack"); var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : "./webpack.config"); var compiler = webpack(webpackConfig); // Step 2: 將編譯器掛載給 webpack dev middleware app.use(require("webpack-dev-middleware")(compiler, { noInfo: true, publicPath: webpackConfig.output.publicPath })); // Step 3: 將編譯器掛載給 webpack hot middleware app.use(require("webpack-hot-middleware")(compiler, { log: console.log, path: "/__webpack_hmr", heartbeat: 10 * 1000 })); })(); // 定義 express 配置 app.get("/", function(req, res) { res.sendFile(__dirname + "/index.html"); }); app.get("/multientry", function(req, res) { res.sendFile(__dirname + "/index-multientry.html"); }); if (require.main === module) { var server = http.createServer(app); server.listen(process.env.PORT || 1616, function() { console.log("Listening on %j", server.address()); }); }
webpack-hot-middleware example server.js
區(qū)分開發(fā)和生產(chǎn)環(huán)境要注意的是一定要在定義 express router 前定義 webpack 相關(guān)的中間件。還有一點是這里server.js 只是開發(fā)環(huán)境中使用,在生成環(huán)境中我們就不需要再用到它們了。所以在我們實際的使用中需要通過定義環(huán)境變量來區(qū)分開發(fā)和生產(chǎn)環(huán)境
var NODE_ENV = process.env.NODE_ENV || "production"; var isDev = NODE_ENV === "development"; if (isDev) { var webpack = require("webpack"), webpackDevMiddleware = require("webpack-dev-middleware"), webpackHotMiddleware = require("webpack-hot-middleware"), webpackDevConfig = require("./build/webpack.config.js"); var compiler = webpack(webpackDevConfig); app.use(webpackDevMiddleware(compiler, { publicPath: webpackDevConfig.output.publicPath, noInfo: true, stats: { colors: true } })); app.use(webpackHotMiddleware(compiler)); routerConfig(app, { dirPath: __dirname + "/server/routes/", map: { "index": "/", "api": "/api/*", "proxy": "/proxy/*" } }); var reload = require("reload"); var http = require("http"); var server = http.createServer(app); reload(server, app); app.use(express.static(path.join(__dirname, "public"))); server.listen(port, function() { console.log("App (dev) is now running on port " + port + "!"); }); } else { routerConfig(app, { dirPath: __dirname + "/server/routes/", map: { "index": "/", "api": "/api/*", "proxy": "/proxy/*" } }); app.use(express.static(path.join(__dirname, "public"))); app.listen(port, function() { console.log("App (dev) is now running on port " + port + "!"); }); }supervisor
以上在前端我們實現(xiàn)了前端文件的熱更新,但是我們在修改服務端文件的時候,并不會使Node自動重啟,所以我們使用 supervisor 來作為監(jiān)聽文件修改事件來自動重啟 Node服務。
supervisor 需要 全局安裝
npm install supervisor -g
安裝完成之后我們就可以在命令行中使用
我們在 package.json 的 scripts 中寫好常用的命令,之后只用 npm run xxx 即可使用
"scripts": { "dev": "export NODE_ENV=development && supervisor -w server,app.js app", "build": "node build/build.js", "start": "node app" },
node-supervisor
supervisor [options]supervisor -w server,app.js app
-w 就是一個 options 配置項,它用于監(jiān)聽指定目錄或者文件的變更,可以使用,
分隔,監(jiān)聽多個目錄或者文件,這就是監(jiān)聽了 server 目錄和根目錄的 app.js 到變更之后就會重啟我們的 Express 入口文件 app。
getEntries 這個是我們自己的載入入口文件的統(tǒng)一方法,具體內(nèi)容其實我前面的文章提到過,就是規(guī)定好了的,文件夾目錄下的main.js就是我們的入口文件,其他全部忽略,原因也說過,這里再說一次,規(guī)定死了,簡單,方便,利于合作。
var publicPath = "http://0.0.0.0:7799/dist/"; 這里publicPath和大家平時配置Webpack的publicPath 不太一樣的原因,是需要Express能夠認出絕對地址來,因為你項目是Express大于Webpack的。
routerConfig 這個方法是我們自己的一個方法,內(nèi)容前面文章提到過,就是我寫的一個用來加載所有路由的方法,免得重復寫各種引用。npm地址
export NODE_ENV=development 注意這里,windows的環(huán)境可能會失敗,可以替換成 cross-env NODE_ENV=development
其次說下這么做的原因前面文章也提到了,我司目前前端的整體架構(gòu)是使用Node做中間層,那么問題就是Node渲染層會高于Webpack層,而且很多時候,不一定使用SPA的方式,要兼容這個架構(gòu),所以才需要這些配置。
這個配置也很好解決了我們開發(fā)中的幾個痛點,一個Node自動重新,一個文件熱更新,結(jié)合起來,基本不需要自己不停的手動刷新瀏覽器,而且能保存當前狀態(tài),這點很關(guān)鍵,能節(jié)省不少時間,提升開發(fā)效率。
當然也有痛點,例如要多一個模板文件,而且文件目錄要根據(jù)規(guī)范來,要不是不會渲染的。
最后記得這是一個連續(xù)的文章系列,只看這里你不一定能配置成功!!!!文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/50200.html
摘要:在前后端分離的前端項目開發(fā)中經(jīng)常用到。是的一個中間件。即是一個重要的功能。配置先來在配置文件中引入添加一個和通信的客戶端添加應用入口文件在插件中引入在我們的開發(fā)環(huán)境中是這樣配置的。 原文鏈接此文是我同事寫的,搭建Express結(jié)合Webpack。以下是正文,后面我會附上我的解讀 Express 結(jié)合 Webpack 實現(xiàn)HMR 本篇文件主要講結(jié)合 Webpack 和 Express 實...
摘要:解析不同文件使用哪些,這個比較簡單,很多文章都有,就不多說了,注意的是,這里的可以換成你自己的預編譯器,例如等,或者直接用都行,當然還可以用一種通用方法,后面補上。 前情提要 上一篇文章介紹了目前前端比較流行的各種編輯器,以及各種流行的打包方式,最后給了一個Gulp的例子,這個例子還是14年的時候?qū)懙模€有一些可以優(yōu)化的空間,就不討論了,這篇文章主要講目前火熱的打包構(gòu)建方式--Webp...
摘要:解析不同文件使用哪些,這個比較簡單,很多文章都有,就不多說了,注意的是,這里的可以換成你自己的預編譯器,例如等,或者直接用都行,當然還可以用一種通用方法,后面補上。 前情提要 上一篇文章介紹了目前前端比較流行的各種編輯器,以及各種流行的打包方式,最后給了一個Gulp的例子,這個例子還是14年的時候?qū)懙模€有一些可以優(yōu)化的空間,就不討論了,這篇文章主要講目前火熱的打包構(gòu)建方式--Webp...
摘要:的最后一個大招就是替換一些傳統(tǒng)的服務端語言,例如,,等,在業(yè)務層上面使用來開發(fā)服務端完全不成問題。更多的的使用細節(jié)和技巧建議關(guān)注美團博客大搜車論壇下一篇我們開啟如何結(jié)合和搭建一個開發(fā)環(huán)境和項目目錄 往期回顧 前面2期都講得是瀏覽器端的東西比較多,包括Webpack,雖然是Node處理的,但是還是瀏覽器端用的多,對于現(xiàn)在的前端開發(fā)來說,不懂一點服務端的東西,簡直沒辦法活,一般的招聘要求都...
摘要:我覺得這方面的原因是當時對和的依賴,導致大家對的興趣不弄,錯過了最佳時機,這個其實跟百度自己的的技術(shù)棧有很大關(guān)系。這個阮一峰對于前端構(gòu)建的變化吐槽過,說新的構(gòu)建工具就是的構(gòu)建工具。 文章來源 最近幾年,前端發(fā)展越來越迅速,各種萌新加入了前端這個大家庭,大有趕IOS、超Android的趨勢呀!同時,萌新們提出了各種前端工作問題,除了最基礎的html、css、js三板斧之外,最讓人頭疼的應...
閱讀 2784·2023-04-25 18:06
閱讀 2576·2021-11-22 09:34
閱讀 1684·2021-11-08 13:16
閱讀 1302·2021-09-24 09:47
閱讀 3049·2019-08-30 15:44
閱讀 2773·2019-08-29 17:24
閱讀 2584·2019-08-23 18:37
閱讀 2433·2019-08-23 16:55