Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions common/js/pages/Todos/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Loadable from 'react-loadable';
import { Loading } from 'components/common';
import { fetchTodos } from 'actions/todos';

// NOTE: To turn off dynamic imports, import this container normally using:
// import TodosContainer from 'containers/Todos';
const TodosContainer = Loadable({
loader: () => import('../../containers/Todos'),
loading: Loading
Expand Down
3 changes: 3 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const { mapValues, keyBy } = require('lodash');

module.exports = {
// Enable or disable server-side rendering
enableSSR: true,

// Enable or disable dynamic imports (code splitting)
enableDynamicImports: false,

Expand Down
4 changes: 2 additions & 2 deletions nodemon.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"watch": [
"config/**/*.js",
"server/**/*.js",
"server/**/*.json",
"server/templates/**/*.html",
"common/js/**/*.js"
"server/templates/**/*.html"
]
}
26 changes: 21 additions & 5 deletions server/renderer/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export default function handleRender(req, res) {
// Grab the initial state from our Redux store
const finalState = store.getState();

// If SSR is disabled, just render the skeleton HTML.
if (!config.enableSSR) {
const markup = render(null, finalState, []);
return res.send(markup);
}

// See react-router's Server Rendering section:
// https://reacttraining.com/react-router/web/guides/server-rendering
const matchRoutes = routes => {
Expand Down Expand Up @@ -88,20 +94,30 @@ export default function handleRender(req, res) {

let context = {}, modules = [];

const component = (
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
const getComponent = () => {
let component = (
<Provider store={store}>
<StaticRouter context={context} location={req.baseUrl}>
<App />
</StaticRouter>
</Provider>
</Loadable.Capture>
);
);

if (config.enableDynamicImports) {
return (
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
{component}
</Loadable.Capture>
);
}

return component;
};

// Execute the render only after all promises have been resolved.
Promise.all(fetchData).then(() => {
const state = store.getState();
const html = renderToString(component);
const html = renderToString(getComponent());
const bundles = stats && getBundles(stats, modules) || [];
const markup = render(html, state, bundles);

Expand Down
17 changes: 2 additions & 15 deletions webpack/development.hot.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const entry = [

// Additional plugins
let plugins = [
...baseConfig.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.NamedModulesPlugin()
Expand All @@ -31,9 +32,6 @@ if (!config.enableDynamicImports) {
}));
}

// Additional loaders
const loaders = [];

const webpackConfig = {
...baseConfig,
devtool: 'eval',
Expand All @@ -44,18 +42,7 @@ const webpackConfig = {
...baseConfig.entry.app
]
},
plugins: [
// don't use the first plugin (isomorphic plugin)
...baseConfig.plugins,
...plugins
],
module: {
...baseConfig.module,
rules: [
...baseConfig.module.rules,
...loaders
]
}
plugins
};

console.info('Firing up Webpack dev server...\n');
Expand Down