Skip to content

Commit 4b9ba51

Browse files
committed
Adds build files and production server side rendering
1 parent 5daf27f commit 4b9ba51

File tree

11 files changed

+190
-7
lines changed

11 files changed

+190
-7
lines changed

.babelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"presets": ["react", "es2015", "stage-0"],
33
"plugins": [
4+
["transform-decorators-legacy"],
45
["add-module-exports"],
5-
["transform-decorators-legacy"]
66
]
77
}

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
"main": "index.js",
66
"scripts": {
77
"dev": "NODE_ENV=development node ./src/server/server.babel.js",
8-
"prod": "NODE_ENV=production node ./src/server/server.babel.js"
8+
"prod": "NODE_ENV=production node ./src/server/server.babel.js",
9+
"build": "npm run build:client && npm run build:server",
10+
"build:server": "NODE_ENV=production webpack --config ./webpack/server.babel.js",
11+
"build:client": "NODE_ENV=production webpack --config ./webpack/prod.babel.js"
912
},
1013
"author": "",
1114
"license": "ISC",
@@ -23,6 +26,7 @@
2326
"redux-immutablejs": "0.0.8"
2427
},
2528
"devDependencies": {
29+
"assets-webpack-plugin": "^3.4.0",
2630
"babel-loader": "^6.2.5",
2731
"babel-plugin-add-module-exports": "^0.2.1",
2832
"babel-plugin-react-transform": "^2.0.2",
@@ -35,6 +39,8 @@
3539
"babel-register": "^6.14.0",
3640
"chokidar": "^1.6.0",
3741
"css-loader": "^0.25.0",
42+
"extract-text-webpack-plugin": "^1.0.1",
43+
"happypack": "^2.2.1",
3844
"querystring": "^0.2.0",
3945
"style-loader": "^0.13.1",
4046
"webpack": "2.1.0-beta.4",

src/server/Html.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ class Html extends Component {
4444
</Provider>
4545
);
4646

47-
// {PROD && <script dangerouslySetInnerHTML={{__html: manifest.text}}/>}
4847

4948

5049
return (
@@ -59,6 +58,7 @@ class Html extends Component {
5958
<body>
6059
<script dangerouslySetInnerHTML={{__html: initialState}} />
6160
{PROD ? <div id="root" dangerouslySetInnerHTML={{__html: root}}></div> : <div id="root"></div>}
61+
{PROD && <script dangerouslySetInnerHTML={{__html: manifest.text}}/>}
6262
<script src={PROD ? app.js : '/static/app.js'} />
6363
</body>
6464
</html>

src/server/server.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ const app = express();
1818

1919
// Production settings
2020
if (PROD) {
21+
22+
app.use('/static', express.static('build'));
23+
2124
app.get('*', renderPage);
2225

2326
// Development settings
@@ -57,7 +60,13 @@ if (PROD) {
5760
compiler.plugin('done', function() {
5861
console.log("Clearing /client/ module cache from server");
5962
Object.keys(require.cache).forEach(function(id) {
60-
if (/[\/\\]client[\/\\]/.test(id) || /[\/\\]universal[\/\\]/.test(id)) delete require.cache[id];
63+
if (/[\/\\]client[\/\\]/.test(id)) {
64+
console.log(`${'Clearing'.yellow} ${'/server/'.red+id.split(/[\/\\]client[\/\\]/)[1].red} ${'module cache from server'.yellow}`);
65+
delete require.cache[id];
66+
} else if (/[\/\\]universal[\/\\]/.test(id)) {
67+
console.log(`${'Clearing'.yellow} ${'/server/'.red+id.split(/[\/\\]universal[\/\\]/)[1].red} ${'module cache from server'.yellow}`);
68+
delete require.cache[id];
69+
}
6170
});
6271
});
6372
}

src/server/ssr.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import React from 'react';
22
import {push} from 'react-router-redux';
3+
import {match} from 'react-router';
34
import {renderToStaticMarkup} from 'react-dom-stream/server';
5+
import fs from 'fs';
6+
import {join, basename} from 'path';
7+
48

59
import Html from './Html';
610
import createStore from '../universal/redux/createStore';
@@ -34,7 +38,32 @@ function renderApp(res, store, assets, renderProps) {
3438

3539
export const renderPage = (req, res) => {
3640
const store = createStore( );
37-
renderApp(res, store);
41+
42+
const makeRoutes = require('../../build/prerender');
43+
const assets = require('../../build/assets.json');
44+
45+
assets.manifest.text = fs.readFileSync(
46+
join(__dirname, '..', '..', 'build', basename(assets.manifest.js)),
47+
'utf-8'
48+
);
49+
50+
const routes = makeRoutes(store);
51+
52+
match({routes, location: req.url}, (error, redirectLocation, renderProps) => {
53+
54+
if (error) {
55+
res.status(500).send(error.message);
56+
} else if (redirectLocation) {
57+
res.redirect(redirectLocation.pathname + redirectLocation.search);
58+
} else if (renderProps) {
59+
renderApp(res, store, assets, renderProps);
60+
} else {
61+
res.status(404).send('Not found');
62+
}
63+
64+
});
65+
66+
// renderApp(res, store);
3867
};
3968

4069
export const renderDevPage = (req, res) => {

src/universal/components/App/App.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ body {
1818

1919
}
2020

21-
2221
h1,h2,h3,h4,h5,h6 {
2322
color: white;
2423
}
2524

26-
2725
h2 {
2826
font-size: 2em;
2927
line-height: 1.5em;

webpack/prod.babel.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require('babel-register');
2+
module.exports = require('./webpack.config.prod');

webpack/server.babel.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require('babel-register');
2+
module.exports = require('./webpack.config.server');

webpack/webpack.config.dev.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const src = path.join(root, 'src');
88
const clientSrc = path.join(src, 'client');
99
const universalSrc = path.join(src, 'universal');
1010

11+
1112
const clientInclude = [clientSrc, universalSrc];
1213

1314
const babelQuery = {

webpack/webpack.config.prod.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import path from 'path';
2+
import webpack from 'webpack';
3+
import qs from 'querystring';
4+
5+
import AssetsPlugin from 'assets-webpack-plugin';
6+
7+
const root = process.cwd();
8+
const src = path.join(root, 'src');
9+
const build = path.join(root, 'build');
10+
11+
const client = path.join(src, 'client');
12+
const universal = path.join(src, 'universal');
13+
14+
const clientInclude = [client, universal];
15+
16+
export default {
17+
context: src,
18+
entry: {
19+
app: ['babel-polyfill', 'client/client.js'],
20+
},
21+
output: {
22+
filename: '[name]_[chunkhash].js',
23+
chunkFilename: '[name]_[chunkhash].js',
24+
path: build,
25+
publicPath: '/static/'
26+
},
27+
resolve: {
28+
extensions: ['.js'],
29+
modules: [src, 'node_modules'],
30+
unsafeCache: true
31+
},
32+
node: {
33+
dns: 'mock',
34+
net: 'mock'
35+
},
36+
plugins: [
37+
new webpack.NamedModulesPlugin(),
38+
new webpack.optimize.CommonsChunkPlugin({
39+
names: ['vendor', 'manifest'],
40+
minChunks: Infinity
41+
}),
42+
new webpack.optimize.AggressiveMergingPlugin(),
43+
new webpack.optimize.MinChunkSizePlugin({minChunkSize: 50000}),
44+
new webpack.optimize.UglifyJsPlugin({compressor: {warnings: false}, comments: /(?:)/}),
45+
new AssetsPlugin({path: build, filename: 'assets.json'}),
46+
new webpack.NoErrorsPlugin(),
47+
new webpack.DefinePlugin({
48+
'__CLIENT__': true,
49+
'__PRODUCTION__': true,
50+
'process.env.NODE_ENV': JSON.stringify('production')
51+
})
52+
],
53+
module: {
54+
loaders: [
55+
{
56+
test: /\.css$/,
57+
loader: 'style-loader!css?'+qs.stringify({
58+
modules: true,
59+
importLoaders: 1,
60+
localIdentName: '[name]_[local]_[hash:base64:5]'
61+
}),
62+
include: clientInclude,
63+
},
64+
65+
{
66+
test: /\.js$/,
67+
loader: 'babel',
68+
include: clientInclude
69+
}
70+
71+
]
72+
}
73+
}

0 commit comments

Comments
 (0)