diff --git a/.dockerignore b/.nowignore similarity index 86% rename from .dockerignore rename to .nowignore index f1cfc631..446590ad 100644 --- a/.dockerignore +++ b/.nowignore @@ -2,4 +2,4 @@ README.md LICENSE tests -dist \ No newline at end of file +dist diff --git a/README.md b/README.md index 5884e622..e1fac041 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ I avoided this by performing *1 extra http request* to fetch the props as json b See [browser.tsx](https://github.com/styfle/react-server-example-tsx/blob/master/src/browser.tsx) for the client-side code. -See [server.tsx](https://github.com/styfle/react-server-example-tsx/blob/master/src/server.tsx) for the server-side code. +See [server.ts](https://github.com/styfle/react-server-example-tsx/blob/master/src/server.ts) for the server-side code. ## Prior art diff --git a/now.json b/now.json index 34d14fca..e80a3f4b 100644 --- a/now.json +++ b/now.json @@ -1,10 +1,18 @@ { "name": "react-server-example-tsx", "alias": "react-tsx.now.sh", - "type": "docker", - "features": { - "cloud": "v2" - }, + "version": 2, + "regions": ["all"], + "builds": [ + { "src": "src/style.min.css", "use": "@now/static" }, + { "src": "package.json", "use": "@now/static-build" }, + { "src": "src/server.ts", "use": "@now/node@canary" } + ], + "routes": [ + { "src": "/style.min.css", "dest": "/src/style.min.css" }, + { "src": "/browser.js", "dest": "/browser.js" }, + { "src": "/(.*)", "dest": "/src/server.ts" } + ], "env": { "NODE_ENV": "production" } diff --git a/package.json b/package.json index d933e006..08ca28c8 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "repository": "styfle/react-server-example-tsx", "scripts": { "start": "node dist/server.js", - "build": "webpack --mode production", + "build": "webpack --mode development", + "now-build": "webpack --mode production", "watch": "webpack --mode development --watch", "prettier": "prettier \"./src/**/*.ts\" \"./src/**/*.tsx\" --write", "test": "tsc --outDir . --sourceMap false && tape tests/**/*.js", diff --git a/src/constants.ts b/src/constants.ts index f801fd5a..4f5aba70 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,3 @@ -export const reactUrl = '/react.js'; -export const reactDomUrl = '/react-dom.js'; export const faviconUrl = 'data:image/x-icon;base64,AAABAAEAIB0AAAEAIAAcDwAAFgAAACgAAAAgAAAAOgAAAAEAIAAAAAAAgA4AAMMOAADDDgAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////79/f/y6O3/7d7l//Pp7v/+/v7//////////////////////////////////v39//Po7f/t3uX/8+nu//79/v/////////////////////////////////////////////////////////////////////////////////7+Pr/1rTF/7Nzkv+sZoj/tHWU/8ugtf/u3+b///////////////////7//+zc4//KnbP/tHST/6xmiP+0dZT/2bjI//z6+////////////////////////////////////////////////////////////////////////////+DG0v+oXoL/xZSs/9u9y//KnbP/rmqM/69rjP/ZuMj/+/j6//r2+P/WtMT/rmmK/69sjf/LoLX/273L/8OQqf+oX4P/48zX///////////////////////////////////////////////////////////////////////9/Pz/voei/7uBnf/48fT///////7+/v/w5Or/xpau/6hfg//ImbD/xpat/6hfg//ImrH/8ubs///+/v//////9u7y/7h8mf/Cjaf//v3+//////////////////////////////////////////////////////////////////r2+P+vbI3/z6a6///////////////////////7+Pn/z6a6/6FSeP+iU3r/0q2///z5+///////////////////////y5+0/7Nykf/8+fr/////////////////////////////////////////////////////////////////9e3x/65pi//VscP///////////////////////r3+f/HmK//pFh9/6VZfv/Ln7T//Pn6///////////////////////Rqb3/sG2O//jx9P/////////////////////////////////////////////////////////////////48vX/rWmK/9Ksv////////////////////v7/06/B/6lhhP/Vs8T/1LDB/6phhf/Ws8T//////////////////////86kuf+wbY7/+vb4//////////////////////////////////////////////////////////////////z5+/+ycZH/yp6z//79/f/17fH/7uDn/9i2x/+oX4P/tHaU/9u9zP/bvMv/s3KR/6pihf/ausr/7uHn//bu8v/9/P3/xpeu/7V3lf/9/Pz/////////////////////////////////////////////////////////////////+fP2/7uBnv+ua4z/v4mj/7d6l/+wbY3/o1V7/6JTef+mW4D/pFh9/6RYff+mW3//oVJ5/6NWfP+wbo7/t3qY/7+Jo/+uaIr/voij//r19///////////////////////////////////////////////////////9Ozw/9i3x/+2eZf/o1Z8/55Ndf+0dZT/xpau/7Fujv+qYoX/38LQ/+/h6P/y5+z/8ubs/+/h6P/cv83/qWCE/7FxkP/Gla3/s3KS/55MdP+kV33/uHuZ/9q7yv/27vH//////////////////////////////////v7+/+TN2P+3e5j/qF+D/8KOqP/No7j/plyA/+DF0v/n0tz/q2SH/9Gpvf///f7///////r+///6/v////////79/f/OpLj/rGaI/+nW3//cvs3/p12B/8+muv/AjKX/qF6C/7l+m//m0dv///////////////////////7+/v/ew9D/rGWI/7uAnf/o1N3/+/n6//fx9P+5fZr/vYah/76Hov+1d5X/9+/z//f9//+v4P//acX//2vF//+04v//+v7///Xs8P+zc5L/wIul/7uBnv+7gp7/+fT3//v3+f/m0Nv/uHya/61oiv/hyNT/////////////////7+Lo/7Jykf/AiqT/9u7y/////////////////9Krvv+iU3r/pVp//9y/zf//////teL//0K2//82sf//NrH//0W3//+/5v///////9m5yf+lWX7/o1V7/9Wyw//////////////////17PD/vYWg/7V2lP/z6O3////////////ew9D/pluA/+rZ4f//////////////////////7Nvk/6lgg/+2eJb/9e3x//////96zP//NbH//ziy//84sv//NbH//4PP////////8+nu/7Nykv+rZIf/7uDn///////////////////////n09z/pVp+/+XP2v///////////+HH1P+nXYH/5M3Y///////////////////////n093/p1yA/7Fvj//y5+z//////4PP//82sf//OLL//ziy//82sf//itL////////w4+n/rmuL/6lgg//q2OH//////////////////////+DG0/+nXIH/59Pc////////////9Ovv/7l/nP+1dpX/7N3k/////////////v3+/8ygtf+kWH3/p12B/9OuwP//////y+v//1G8//82sf//NrH//1S9///Q7f////7+/9CovP+nXYH/pFh9/8+nu////v7////////////r2eL/s3KS/7yEn//38PP/////////////////6tjh/7V2lf+uaov/17XF//Tq7v/z6e7/tHOT/8iZsP/ImbD/r2uM//Dj6f/+////z+z//4/U//+Q1P//z+z///7////u3+b/rWiJ/8uetP/Ek6v/tniW//Xt8f/y6O3/1bHD/61oiv+3epj/7Nzk////////////////////////////7+Lo/8aWrf+pYYT/tHST/72Fof+kV33/38LQ/+rX4P+uaov/x5eu//z5+v//////////////////////+/f5/8SSq/+vbI3/69ri/9u8y/+kV33/vYei/7Nykv+qYoX/yJqw//Hl6////////////////////////////////////////Pr7/+nV3//HmK//qF+C/59Odf+oXoL/t3qY/61piv+lWH3/zqS4/93Bz//gxtP/4MbS/93Az//MoLX/pFd8/65qjP+2eZf/qF2B/59Ndf+pYYT/yZux/+rY4f/8+vv///////////////////////////////////////////////////////37/P+7gp7/t3qX/9Ktv//Gla3/uoCd/6lgg/+eTHT/o1Z8/6RXfP+kV33/o1V7/55MdP+qYoX/u4Ke/8aWrv/Trb//tHWU/7+Jo//+/f3/////////////////////////////////////////////////////////////////+/j5/7Btjf/No7j///////z5+//59Pb/59Pd/7Btjv+2eZf/6dfg/+jV3v+0dJP/snGQ/+nW4P/59Pb//Pr7///////Jm7H/s3KR//z6+//////////////////////////////////////////////////////////////////38PT/rmmK/9OuwP//////////////////////38TR/6phhf/Hl6//xZSs/6tkhv/hyNX//////////////////////8+muv+wbY7/+fT3//////////////////////////////////////////////////////////////////bu8v+uaYr/1LDC///////////////////////+/v7/0au9/6JTef+iVHr/1LHC////////////////////////////0Ki8/7Btjv/48vX/////////////////////////////////////////////////////////////////+/j5/7FvkP/Mobb///////////////////////Tr7//Ekqr/pFd8/6RXfP/Hl67/9u7y///////////////////////ImbD/tXWU//36+//////////////////////////////////////////////////////////////////+/f3/xJKr/7R1lP/x5ev//vz9//n09v/jzNf/t3uY/6xmiP/Yt8f/1bPE/6tkh/+6fpv/5c/a//n09//+/f3/7uDn/7Jxkf/ImbD//v7+///////////////////////////////////////////////////////////////////////p1t//rGeJ/7d6mP/JnLL/uoCd/6hegv+7gp7/59Pd///////+/v7/5dDa/7l/m/+oX4P/u4Of/8mcs/+1d5b/rmqL/+zb4/////////////////////////////////////////////////////////////////////////////38/f/iytb/uoCc/65pi/+7gp7/2rvK//Xt8f//////////////////////9Ovw/9m5yP+6gJz/rmmK/7yDnv/kzdj//v39////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='; export const stylesUrl = '/style.min.css'; diff --git a/src/server.tsx b/src/server.ts similarity index 83% rename from src/server.tsx rename to src/server.ts index ce9a0c74..c9f2418e 100644 --- a/src/server.tsx +++ b/src/server.ts @@ -1,4 +1,4 @@ -import { createServer } from 'http'; +import { createServer, IncomingMessage, ServerResponse } from 'http'; import { createFactory } from 'react'; import { renderToNodeStream } from 'react-dom/server'; import { createReadStream } from 'fs'; @@ -9,8 +9,6 @@ import { control } from './cache-control'; import { faviconUrl, stylesUrl, - reactUrl, - reactDomUrl, browserUrl, browserMapUrl, propsUrl, @@ -23,8 +21,9 @@ console.log('Production optimization enabled? ', isProd); const AppFactory = createFactory(App); const PORT = process.env.PORT || 3007; const suffix = isProd ? '.production.min.js' : '.development.js'; +const reactVersion = require('../package.json').dependencies.react; -createServer(async (req, res) => { +export default async function handler(req: IncomingMessage, res: ServerResponse) { let { httpVersion, method, url } = req; console.log(`${httpVersion} ${method} ${url}`); if (!url || url === '/') { @@ -52,8 +51,8 @@ createServer(async (req, res) => { ); stream.on('end', () => { res.end(` - - + + `); @@ -62,12 +61,6 @@ createServer(async (req, res) => { res.setHeader('Content-Type', lookup(url)); res.setHeader('Cache-Control', control(isProd, 0)); res.end(JSON.stringify(fetchProps())); - } else if (url === reactUrl || url === reactDomUrl) { - res.setHeader('Content-Type', lookup(url)); - res.setHeader('Cache-Control', control(isProd, 7)); - const name = url.replace('.js', ''); - const file = `./node_modules${name}/umd${name}${suffix}`; - createReadStream(file).pipe(res); } else if (url === stylesUrl) { res.setHeader('Content-Type', lookup(url)); res.setHeader('Cache-Control', control(isProd, 7)); @@ -93,6 +86,10 @@ createServer(async (req, res) => { res.statusCode = 500; res.end('500 Internal Error'); } -}).listen(PORT, () => { - console.log(`Listening on ${PORT}...`); -}); +} + +if (!isProd) { + createServer(handler).listen(PORT, () => { + console.log(`Listening on ${PORT}...`); + }); +} diff --git a/webpack.config.js b/webpack.config.js index b15677a5..7563df74 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -37,7 +37,7 @@ const configs = [ }, { entry: { - server: './src/server.tsx', + server: './src/server.ts', }, output: { path: __dirname + '/dist',