From ba7704b6d8b9d891bcabf06510fa219aea1198b4 Mon Sep 17 00:00:00 2001 From: Konstantin Tarkus Date: Mon, 19 Feb 2018 01:20:37 +0300 Subject: [PATCH] Save compiled server-side code to disk in dev mode --- README.md | 2 +- packages/react-app-tools/config/paths.js | 1 + .../config/webpack.config.server.js | 23 +++++++++++-------- .../config/webpackDevServer.config.js | 20 ++++++++++++---- packages/react-app-tools/package.json | 5 ++-- packages/react-app-tools/scripts/patch.js | 22 +++++++++++++----- yarn.lock | 19 +++++++++++++-- 7 files changed, 67 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 0abb9b4f..dded2cd4 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ entry point for the server-side application bundle as demonstrated below: }, { - "react-scripts": "^1.1.1" -+ "react-app-tools": "^2.0.0-beta.4" ++ "react-app-tools": "^2.0.0-beta.5" }, "scripts": { - "test": "react-scripts test --env=jsdom", diff --git a/packages/react-app-tools/config/paths.js b/packages/react-app-tools/config/paths.js index 447b653d..31cfa5e2 100644 --- a/packages/react-app-tools/config/paths.js +++ b/packages/react-app-tools/config/paths.js @@ -17,4 +17,5 @@ module.exports = Object.assign(paths, { appIndexJs: `${paths.appIndexJs.slice(0, -8)}app.browser.js`, appEntry: `${paths.appIndexJs.slice(0, -8)}app.node.js`, serverEntry: `${paths.appIndexJs.slice(0, -8)}server.js`, + assets: path.join(paths.appBuild, 'assets.json'), }); diff --git a/packages/react-app-tools/config/webpack.config.server.js b/packages/react-app-tools/config/webpack.config.server.js index 9c9f9d99..6b4cef59 100644 --- a/packages/react-app-tools/config/webpack.config.server.js +++ b/packages/react-app-tools/config/webpack.config.server.js @@ -12,6 +12,7 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin'); +const WriteFilePlugin = require('write-file-webpack-plugin'); const paths = require('./paths'); module.exports = config => @@ -71,15 +72,17 @@ module.exports = config => }), // Remove plugins that are not needed in the server-side bundle - plugins: config.plugins.filter( - x => - !( - x instanceof InterpolateHtmlPlugin || - x instanceof HtmlWebpackPlugin || - x instanceof UglifyJsPlugin || - x instanceof SWPrecacheWebpackPlugin - ) - ), + plugins: config.plugins + .filter( + x => + !( + x instanceof InterpolateHtmlPlugin || + x instanceof HtmlWebpackPlugin || + x instanceof UglifyJsPlugin || + x instanceof SWPrecacheWebpackPlugin + ) + ) + .concat([new WriteFilePlugin({ output: paths.serverBuild })]), - externals: [nodeExternals()], + externals: ['./assets.json', nodeExternals()], }); diff --git a/packages/react-app-tools/config/webpackDevServer.config.js b/packages/react-app-tools/config/webpackDevServer.config.js index 7e62b7fb..41ca6976 100644 --- a/packages/react-app-tools/config/webpackDevServer.config.js +++ b/packages/react-app-tools/config/webpackDevServer.config.js @@ -8,18 +8,30 @@ 'use strict'; const createConfig = require('react-scripts/config/webpackDevServer.config'); +const paths = require('./paths'); module.exports = function(proxy, allowedHost) { const config = createConfig(proxy, allowedHost); return Object.assign(config, { historyApiFallback: false, + setup(app) { + app.get('/', (req, res, next) => { + global.appPromise + .then(() => { + const app = require(paths.serverBuildAppJs).default; + app.handle(req, res); + }) + .catch(next); + }); + }, after(app) { - app.get('*', (req, res) => { + app.get('*', (req, res, next) => { global.appPromise - .then(x => { - x.handle(req, res); + .then(() => { + const app = require(paths.serverBuildAppJs).default; + app.handle(req, res); }) - .catch(console.error); + .catch(next); }); }, }); diff --git a/packages/react-app-tools/package.json b/packages/react-app-tools/package.json index 927e0b3e..a4c59bb1 100644 --- a/packages/react-app-tools/package.json +++ b/packages/react-app-tools/package.json @@ -1,6 +1,6 @@ { "name": "react-app-tools", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "description": "Build and test tooling for front-end application development with Node.js and React.", "repository": "kriasoft/react-app", "bugs": { @@ -38,7 +38,8 @@ }, "dependencies": { "react-scripts": "2.0.0-next.47d2d941", - "webpack-node-externals": "^1.6.0" + "webpack-node-externals": "^1.6.0", + "write-file-webpack-plugin": "^4.2.0" }, "scripts": { "prepublishOnly": "cp ../../README.md . && yarn install && node ./scripts/patch" diff --git a/packages/react-app-tools/scripts/patch.js b/packages/react-app-tools/scripts/patch.js index c2dd59d6..14646927 100644 --- a/packages/react-app-tools/scripts/patch.js +++ b/packages/react-app-tools/scripts/patch.js @@ -51,6 +51,10 @@ copy('react-scripts/scripts/build.js', 'scripts/build.js', [ '[paths.appHtml, paths.appIndexJs]', '[paths.appIndexJs, paths.appEntry, paths.serverEntry]', ], + [ + 'printBrowsers(paths.appPath);', + 'printBrowsers(paths.appPath);\n fs.outputJsonSync(paths.assets, stats.toJson({}, true).assetsByChunkName, { spaces: 2 });', + ], ]); copy('react-scripts/scripts/start.js', 'scripts/start.js', [ @@ -75,16 +79,22 @@ copy('react-dev-utils/WebpackDevServerUtils.js', 'WebpackDevServerUtils.js', [ "require('react-dev-utils/getProcessForPort');", "require('react-dev-utils/getProcessForPort');\nconst paths = require('./config/paths');", ], + [ + "console.log('Compiling...');", + `console.log('Compiling...'); + + global.appPromise = new Promise(resolve => { + global.appPromiseResolve = resolve; + });`, + ], [ ' });\n return compiler;', ` + const assets = JSON.stringify(stats.stats[0].toJson({}, true).assetsByChunkName, null, ' '); + fs.writeFileSync(paths.assets, assets, 'utf8'); + delete require.cache[paths.assets]; delete require.cache[paths.serverBuildAppJs]; - const code = stats.stats[1].compilation.assets['app.js'].children[0]._value; - const m = new Module(paths.serverBuildAppJs, module.parent); - m.filename = paths.serverBuildAppJs; - m.paths = Module._nodeModulePaths(path.dirname(m.filename)); - m._compile(code, m.filename); - global.appPromiseResolve(m.exports.default); + global.appPromiseResolve(); });\n return compiler;`, ], [ diff --git a/yarn.lock b/yarn.lock index c27a3b1b..70c823f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3833,6 +3833,10 @@ filesize@3.5.11: version "3.5.11" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" +filesize@^3.2.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa" + fill-range@^2.1.0: version "2.2.3" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" @@ -5872,7 +5876,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: +"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" @@ -6163,7 +6167,7 @@ modify-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2" -moment@^2.6.0: +moment@^2.11.2, moment@^2.6.0: version "2.20.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" @@ -9253,6 +9257,17 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.1.0, write-file-atomic@^2.3.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write-file-webpack-plugin@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/write-file-webpack-plugin/-/write-file-webpack-plugin-4.2.0.tgz#7bd18547eaa0ea0b23992fb1e0322e5431d339ef" + dependencies: + chalk "^1.1.1" + debug "^2.6.8" + filesize "^3.2.1" + lodash "^4.5.1" + mkdirp "^0.5.1" + moment "^2.11.2" + write-json-file@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f"