From 3134944a7faaf734e61f7526b7809969f673dfa2 Mon Sep 17 00:00:00 2001 From: Matthew Smith Date: Thu, 7 May 2015 20:48:20 -0600 Subject: [PATCH] Use webpack-dev-server instead of webpack-dev-middleware Will update changes files both server and client side without needing to restart. Resolves #623 --- docs/dev-run | 78 ++++++++++++++++++++++++++++++++++++++ docs/server.js | 54 ++++++++++++-------------- package.json | 7 +++- webpack/strategies/docs.js | 1 + 4 files changed, 108 insertions(+), 32 deletions(-) create mode 100755 docs/dev-run diff --git a/docs/dev-run b/docs/dev-run new file mode 100755 index 0000000000..24fe49d995 --- /dev/null +++ b/docs/dev-run @@ -0,0 +1,78 @@ +#!/usr/bin/env babel-node +/* eslint no-process-exit: 0 */ +import 'colors'; +import portfinder from 'portfinder'; +import { exec } from 'child-process-promise'; + +portfinder.basePort = 4000; + +const SIGINT = 'SIGINT'; +let webpackDevServer; +let docsServer; + +function output(prefix, message) { + let formattedMessage = message.trim().split('\n') + .reduce((acc, line) => `${acc}${ acc !== '' ? '\n' : '' }${prefix} ${line}`, ''); + + console.log(formattedMessage); +} + +function listen({stdout, stderr}, name) { + stdout.on('data', data => output(`[${name}] `.grey, data)); + stderr.on('data', data => output(`[${name}] `.grey, data)); +} + +function shutdown() { + if (webpackDevServer) { + webpackDevServer.kill(SIGINT); + } + if (docsServer) { + docsServer.kill(SIGINT); + } +} + +function catchExec(name, err) { + if (err.killed) { + console.log('Shutdown: '.cyan + name.green); + } else { + console.log(`${name} -- Failed`.red); + console.log(err.toString().red); + } + shutdown(); +} + +console.log('Starting docs in Development mode'.cyan); + +process.on(SIGINT, shutdown); + +portfinder.getPorts(2, {}, (portFinderErr, [docsPort, webpackPort]) => { + if (portFinderErr) { + console.log('Failed to acquire ports'.red); + process.exit(1); + } + + exec(`webpack-dev-server --quiet --config webpack.docs.js --color --port ${webpackPort}`) + .progress(childProcess => { + listen(childProcess, 'webpack-dev-server'); + webpackDevServer = childProcess; + return; + }) + .then(() => console.log('Shutdown: '.cyan + 'webpack-dev-server'.green)) + .catch(err => catchExec('webpack-dev-server', err)); + + exec('nodemon --exec babel-node docs/server.js', { + env: { + PORT: docsPort, + WEBPACK_DEV_PORT: webpackPort, + ...process.env + } + }) + .progress(childProcess => { + listen(childProcess, 'docs-server'); + docsServer = childProcess; + return; + }) + .then(() => console.log('Shutdown: '.cyan + 'docs-server'.green)) + .catch(err => catchExec('docs-server', err)); +}); + diff --git a/docs/server.js b/docs/server.js index 1c19d26628..2554a5482a 100644 --- a/docs/server.js +++ b/docs/server.js @@ -1,46 +1,40 @@ +import 'colors'; import React from 'react'; import express from 'express'; import path from 'path'; -import webpack from 'webpack'; -import webpackMiddleware from 'webpack-dev-middleware'; -import webpackConfigBuilder from '../webpack/webpack.config'; import Router from 'react-router'; import routes from './src/Routes'; +import httpProxy from 'http-proxy'; const development = process.env.NODE_ENV !== 'production'; +const port = process.env.PORT || 4000; + let app = express(); if (development) { - let webpackConfig = webpackConfigBuilder({ - development: development, - docs: true - }); - let publicPath = webpackConfig.output.publicPath; + let proxy = httpProxy.createProxyServer(); + let webpackPort = process.env.WEBPACK_DEV_PORT; + let target = `http://localhost:${webpackPort}`; - webpackConfig.output.path = '/'; - webpackConfig.output.publicPath = undefined; - webpackConfig.module.noParse = /babel-core\/browser/; + app.get('/assets/*', function (req, res) { + proxy.web(req, res, { target }); + }); - app = app - .use(webpackMiddleware(webpack(webpackConfig), { - noInfo: false, - publicPath: publicPath, - stats: { - colors: true - } - })) - .use(function renderApp(req, res) { - Router.run(routes, req.url, Handler => { - let html = React.renderToString(); - res.send(html); - }); + app.use(function renderApp(req, res) { + Router.run(routes, req.url, Handler => { + let html = React.renderToString(); + res.send(html); }); + }); + + proxy.on('error', function(e) { + console.log('Could not connect to webpack proxy'.red); + console.log(e.toString().red); + }); } else { - app = app - .use(express.static(path.join(__dirname, '../docs-built'))); + app.use(express.static(path.join(__dirname, '../docs-built'))); } -app - .listen(4000, function () { - console.log('Server started at http://localhost:4000'); - }); +app.listen(port, function () { + console.log(`Server started at http://localhost:${port}`); +}); diff --git a/package.json b/package.json index 2638018c59..e0c545a22f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "npm run lint && npm run build && karma start --single-run", "lint": "eslint src test docs ie8 tools webpack karma.conf.js webpack.config.js webpack.docs.js", "docs-build": "babel-node tools/build-cli.js --docs-only", - "docs": "babel-node docs/server.js", + "docs": "docs/dev-run", "docs-prod": "webpack --config webpack.docs.js -p --progress && NODE_ENV=production babel-node docs/server.js", "ie8": "babel-node ie8/server.js" }, @@ -53,6 +53,7 @@ "file-loader": "^0.8.1", "fs-extra": "^0.18.0", "fs-promise": "^0.3.1", + "http-proxy": "^1.11.1", "json-loader": "^0.5.1", "karma": "~0.12.32", "karma-chai": "^0.1.0", @@ -69,6 +70,8 @@ "less-loader": "^2.1.0", "lodash": "^3.5.0", "mocha": "^2.2.1", + "nodemon": "^1.3.7", + "portfinder": "^0.4.0", "react": "^0.13.1", "react-router": "^0.13.1", "rf-changelog": "^0.4.0", @@ -78,7 +81,7 @@ "style-loader": "^0.12.0", "transform-loader": "^0.2.1", "webpack": "^1.7.2", - "webpack-dev-middleware": "^1.0.11", + "webpack-dev-server": "^1.8.2", "yargs": "^3.5.4" }, "dependencies": { diff --git a/webpack/strategies/docs.js b/webpack/strategies/docs.js index 9801053a8c..4933b9aaf7 100644 --- a/webpack/strategies/docs.js +++ b/webpack/strategies/docs.js @@ -20,6 +20,7 @@ export default (config, options) => { extensions: ['', '.js', '.json'] }, module: { + noParse: /babel-core\/browser/, loaders: config.module.loaders .map(value => { if (/\.js\/$/.test(value.test.toString())) {