Skip to content

Commit

Permalink
Step 3b: save the day by making webpack to render server-side code
Browse files Browse the repository at this point in the history
To save our issue with CSS modules, we make Webpack to render both
our client and our server side code. The best way to do it is to
use Webpack's abillity to handle array of configs.

With first config we transform our client-side code (`client.js`),
just as we were doing before. But with the second config we transform
`handleRender` function that we have extracted into `serverEntry.js`,
so now our server-side rendering code gets processed by Webpack too.
There we use css-loader/locals as a CSS loader, to just get class names from
CSS modules, as that's all we need to render html on the server.
Also notice how we use `target:node` and `nodeExternals`.

Great! Now our build is fixed, so we can use CSS modules both during client
and server rendering.
  • Loading branch information
dimaip committed May 12, 2016
1 parent e2c0244 commit 6e36b96
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 21 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
</head>
<body>
<div id="app"></div>
<script src="built/index.js"></script>
<script src="/built/client.js"></script>
</body>
</html>
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"style-loader": "^0.13.1",
"webpack": "^1.12.14"
"webpack": "^1.12.14",
"webpack-node-externals": "^1.0.0"
}
}
18 changes: 1 addition & 17 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
import express from 'express';
import fs from 'fs';
import path from 'path';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Hello from './Hello.js';

function handleRender(req, res) {
const html = ReactDOMServer.renderToString(
<Hello name="World" />
);
fs.readFile('./index.html', 'utf8', function (err, file) {
if (err) {
return console.log(err);
}
const document = file.replace(/<div id="app"><\/div>/, `<div id="app">${html}</div>`);
res.send(document);
});
}
import handleRender from './built/server.js';

const app = express();
// Serve built files with express static files middleware
Expand Down
19 changes: 19 additions & 0 deletions serverEntry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import fs from 'fs';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Hello from './Hello.js';

function handleRender(req, res) {
const html = ReactDOMServer.renderToString(
<Hello name="World" />
);
fs.readFile('./index.html', 'utf8', function (err, file) {
if (err) {
return console.log(err);
}
const document = file.replace(/<div id="app"><\/div>/, `<div id="app">${html}</div>`);
res.send(document);
});
}

export default handleRender;
45 changes: 43 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const nodeExternals = require('webpack-node-externals');

const config = {
name: 'client',
entry: ['client.js'],
output: {
path: path.join(__dirname, 'built/'),
filename: 'index.js',
filename: 'client.js',
publicPath: '/built/'
},
module: {
Expand All @@ -20,6 +22,10 @@ const config = {
test: /\.css$/,
loader: ExtractTextPlugin.extract('style', 'css')
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
}
]
},
plugins: [new ExtractTextPlugin('styles.css')],
Expand All @@ -28,4 +34,39 @@ const config = {
}
};

module.exports = config;
const serverConfig = {
name: 'server',
target: 'node',
externals: [nodeExternals()],
entry: [
'./serverEntry.js'
],
output: {
path: path.join(__dirname, 'built/'),
filename: 'server.js',
publicPath: 'built/',
libraryTarget: 'commonjs2'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel'
},
{
test: /\.css$/,
loader: 'null'
},
{
test: /\.scss$/,
loader: 'css-loader/locals?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
}
]
},
resolve: {
root: __dirname
}
};

module.exports = [config, serverConfig];

0 comments on commit 6e36b96

Please sign in to comment.