├── .nvmrc ├── .npmrc ├── .gitignore ├── hmr.gif ├── .babelrc ├── src ├── middleware │ ├── api.js │ └── view.js ├── app.js └── server.js ├── README.md ├── .vscode └── launch.json ├── package.json ├── LICENSE └── webpack.config.js /.nvmrc: -------------------------------------------------------------------------------- 1 | v4.2 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save=true 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /hmr.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericclemmons/webpack-hot-server-example/HEAD/hmr.gif -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "es2015", 5 | { "modules": false } 6 | ] 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/middleware/api.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | 3 | export default express.Router() 4 | .get("/", (req, res) => { 5 | res.send(`✅ Date: ${new Date()}`); 6 | }) 7 | ; 8 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | 3 | const app = express(); 4 | 5 | app 6 | .use("/api", require("./middleware/api").default) 7 | .use(require("./middleware/view").default) 8 | ; 9 | 10 | export default app; 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Webpack Hot Module Replacement (HMR) Example 2 | 3 | > The simplest example demonstrating server-side [Hot Module Replacement][hmr] 4 | > with [Webpack][webpack] & [Express][express]. 5 | > 6 | > ![Latest Demo](hmr.gif) 7 | 8 | [express]: http://expressjs.com/ 9 | [hmr]: https://webpack.github.io/docs/hot-module-replacement.html 10 | [webpack]: http://webpack.github.io/ 11 | -------------------------------------------------------------------------------- /src/server.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import app from "./app"; 3 | 4 | if (module.hot) { 5 | module.hot.accept("./app", function() { 6 | console.log("🔁 HMR Reloading `./app`..."); 7 | }); 8 | 9 | console.info("✅ Server-side HMR Enabled!"); 10 | } else { 11 | console.info("❌ Server-side HMR Not Supported."); 12 | } 13 | 14 | export default express() 15 | .use((req, res) => app.handle(req, res)) 16 | .listen(3000, function(err) { 17 | if (err) { 18 | console.error(err); 19 | return; 20 | } 21 | 22 | console.log("Listening at http://localhost:3000"); 23 | }) 24 | ; 25 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceRoot}/node_modules/webpack/bin/webpack.js", 12 | "args": ["--watch"], 13 | "cwd": "${workspaceRoot}" 14 | 15 | }, 16 | { 17 | "type": "node", 18 | "request": "attach", 19 | "name": "Attach to Process", 20 | "address": "localhost", 21 | "port": 5858 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "webpack-hot-server-example", 4 | "version": "1.0.0", 5 | "description": "Webpack Hot Module Replacement (HMR) Example", 6 | "main": "index.js", 7 | "engines": { 8 | "node": ">=4.2.0" 9 | }, 10 | "dependencies": { 11 | "babel-core": "^6.14.0", 12 | "babel-loader": "^6.2.5", 13 | "babel-preset-es2015": "6.24.0", 14 | "express": "^4.14.0", 15 | "rimraf": "^2.5.4", 16 | "start-server-webpack-plugin": "^2.0.1", 17 | "webpack": "^2.2.1" 18 | }, 19 | "devDependencies": { 20 | "npm-install-webpack-plugin": "^4.0.4" 21 | }, 22 | "scripts": { 23 | "prestart": "rimraf build", 24 | "start": "webpack --watch" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/ericclemmons/webpack-hot-server-example.git" 29 | }, 30 | "author": "Eric Clemmons ", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/ericclemmons/webpack-hot-server-example/issues" 34 | }, 35 | "homepage": "https://github.com/ericclemmons/webpack-hot-server-example#readme" 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Eric Clemmons 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var NpmInstallPlugin = require("npm-install-webpack-plugin"); 2 | var StartServerPlugin = require("start-server-webpack-plugin"); 3 | var webpack = require("webpack"); 4 | 5 | module.exports = { 6 | devtool: "inline-sourcemap", 7 | 8 | entry: { 9 | server: [ 10 | "webpack/hot/poll?1000", 11 | "./src/server.js", 12 | ], 13 | }, 14 | 15 | externals: [ 16 | // Every non-relative module is external 17 | /^[a-z\-0-9]+$/, 18 | ], 19 | 20 | module: { 21 | loaders: [ 22 | { 23 | loader: "babel-loader", 24 | query: { cacheDirectory: true }, 25 | test: /\.js$/, 26 | }, 27 | ], 28 | }, 29 | 30 | node: { 31 | __filename: true, 32 | __dirname: true, 33 | }, 34 | 35 | output: { 36 | chunkFilename: "[id].[hash:5]-[chunkhash:7].js", 37 | devtoolModuleFilenameTemplate: "[absolute-resource-path]", 38 | filename: "[name].js", 39 | libraryTarget: "commonjs2", 40 | path: "./build/server", 41 | }, 42 | 43 | plugins: [ 44 | new StartServerPlugin(), 45 | new webpack.HotModuleReplacementPlugin(), 46 | new webpack.NamedModulesPlugin(), 47 | new webpack.NoEmitOnErrorsPlugin(), 48 | ], 49 | 50 | target: "async-node", 51 | }; 52 | -------------------------------------------------------------------------------- /src/middleware/view.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | 3 | export default express.Router() 4 | .get("/", (req, res) => { 5 | res.send(` 6 | 7 | 8 | 9 | 10 | 11 | 15 | Webpack Hot Server Example 16 | 17 | 18 |
19 | Waiting for /api… 20 |
21 | 22 | 45 | 46 | 47 | `); 48 | }) 49 | ; 50 | --------------------------------------------------------------------------------