From ddb8b41b14a787fedfc6529cb8a3d8e31ee51878 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Wed, 29 Jul 2015 16:42:58 +0200 Subject: [PATCH 01/32] stopped doing require('webpack-stats.json') on client side, as suggested by @goldensunliu on #60 --- src/components/InfoBar.js | 2 +- src/views/App.js | 2 +- src/views/Home.js | 2 +- src/views/Login.js | 2 +- src/views/Widgets.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/InfoBar.js b/src/components/InfoBar.js index 7a40a928a..e329f3cf4 100755 --- a/src/components/InfoBar.js +++ b/src/components/InfoBar.js @@ -6,10 +6,10 @@ import * as infoActions from '../actions/infoActions'; import {relativeToSrc} from '../util'; const styles = (function getStyle() { - const stats = require('../../webpack-stats.json'); if (__CLIENT__) { return require('./InfoBar.scss'); } + const stats = require('../../webpack-stats.json'); return stats.css.modules[relativeToSrc(path.join(__dirname, './InfoBar.scss'))]; })(); diff --git a/src/views/App.js b/src/views/App.js index e03ef67d8..e53c711db 100755 --- a/src/views/App.js +++ b/src/views/App.js @@ -13,10 +13,10 @@ import {createTransitionHook} from '../universalRouter'; import {relativeToSrc} from '../util'; const styles = (function getStyle() { - const stats = require('../../webpack-stats.json'); if (__CLIENT__) { return require('./App.scss'); } + const stats = require('../../webpack-stats.json'); return stats.css.modules[relativeToSrc(path.resolve(__dirname, './App.scss'))]; })(); diff --git a/src/views/Home.js b/src/views/Home.js index 261c7e135..b7384c4f3 100755 --- a/src/views/Home.js +++ b/src/views/Home.js @@ -5,10 +5,10 @@ import GithubButton from '../components/GithubButton'; import {relativeToSrc} from '../util'; const styles = (function getStyle() { - const stats = require('../../webpack-stats.json'); if (__CLIENT__) { return require('./Home.scss'); } + const stats = require('../../webpack-stats.json'); return stats.css.modules[relativeToSrc(path.resolve(__dirname, './Home.scss'))]; })(); diff --git a/src/views/Login.js b/src/views/Login.js index 94d5cd238..026e7511b 100755 --- a/src/views/Login.js +++ b/src/views/Login.js @@ -8,10 +8,10 @@ import {load as loadAuth} from '../actions/authActions'; import {relativeToSrc} from '../util'; const styles = (function getStyle() { - const stats = require('../../webpack-stats.json'); if (__CLIENT__) { return require('./Login.scss'); } + const stats = require('../../webpack-stats.json'); return stats.css.modules[relativeToSrc(path.join(__dirname, './Login.scss'))]; })(); diff --git a/src/views/Widgets.js b/src/views/Widgets.js index dc371511e..2dfd1ce64 100755 --- a/src/views/Widgets.js +++ b/src/views/Widgets.js @@ -8,10 +8,10 @@ import {load as loadWidgets} from '../actions/widgetActions'; import {relativeToSrc} from '../util'; const styles = (function getStyle() { - const stats = require('../../webpack-stats.json'); if (__CLIENT__) { return require('./Widgets.scss'); } + const stats = require('../../webpack-stats.json'); return stats.css.modules[relativeToSrc(path.join(__dirname, './Widgets.scss'))]; })(); From b1c6b7479f910efad499d469d1c49225584fdfde Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Wed, 29 Jul 2015 17:07:18 +0200 Subject: [PATCH 02/32] added printout to clarify what port to hit with a web browser to fix #61 --- src/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server.js b/src/server.js index 133d4f9a7..ea481e675 100755 --- a/src/server.js +++ b/src/server.js @@ -74,6 +74,7 @@ if (config.port) { api().then(() => { console.info('==> ✅ Server is listening'); console.info('==> 🌎 %s running on port %s, API on port %s', config.app.name, config.port, config.apiPort); + console.info('----------\n==> 💻 Open http://localhost:%s in a browser to view the app.', config.port); }); } }); From 6697d51032829d4de7fe3e48afbcfe96ba97f5ad Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 18:32:44 +0800 Subject: [PATCH 03/32] Resolve the e.g.:"C:\" issue on windows --- webpack/utils/writeStats.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/webpack/utils/writeStats.js b/webpack/utils/writeStats.js index 10da6f9d9..d79610a09 100755 --- a/webpack/utils/writeStats.js +++ b/webpack/utils/writeStats.js @@ -46,6 +46,12 @@ module.exports = function writeStats(stats, env) { var name = path.resolve(__dirname, '../../', env === 'prod' ? m.name.slice('./src'.length) : m.name.slice(namePrefix.length + './src'.length)); + //Resolve the e.g.:"C:\" issue on windows + if(name) { + const i = name.indexOf(":"); + name = name.substring(i > -1 ? i + 1 : 0, name.length + 1); + } + //end var regex = env === 'prod' ? /module\.exports = ((.|\n)+);/ : /exports\.locals = ((.|\n)+);/; var match = m.source.match(regex); cssModules[name] = match ? JSON.parse(match[1]) : {}; From 26b9b45492dfc25860b5f55a4aacf32e65ef4c1c Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 18:39:49 +0800 Subject: [PATCH 04/32] need to check if the component is not undefined when using nested router without passing a component in props. --- src/universalRouter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/universalRouter.js b/src/universalRouter.js index 06683a174..03e3f7cdb 100755 --- a/src/universalRouter.js +++ b/src/universalRouter.js @@ -4,7 +4,8 @@ import routes from './views/routes'; import { Provider } from 'react-redux'; const getFetchData = (component) => { - return component.fetchData || (component.DecoratedComponent && component.DecoratedComponent.fetchData); + //need to check if the component is not undefined when using nested router without passing a component in props. + return (component && component.fetchData) || (component && component.DecoratedComponent && component.DecoratedComponent.fetchData); }; export function createTransitionHook(store) { From 0c4d345e3dd5a139aae7315e14ba8fd44d05c0a0 Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 19:09:58 +0800 Subject: [PATCH 05/32] Find compiled images in modules of web pack stats memory --- webpack/utils/writeStats.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/webpack/utils/writeStats.js b/webpack/utils/writeStats.js index d79610a09..967a4bfeb 100755 --- a/webpack/utils/writeStats.js +++ b/webpack/utils/writeStats.js @@ -57,12 +57,28 @@ module.exports = function writeStats(stats, env) { cssModules[name] = match ? JSON.parse(match[1]) : {}; }); + // Find compiled images in modules + // it will be used to map original filename to the compiled one + // for server side rendering + const imagesRegex = /\.(jpe?g|png|gif|svg)$/; + const images = json.modules + .filter(function(module) { + return imagesRegex.test(module.name); + }) + .map(function(image) { + return { + original: image.name, + compiled: `${publicPath}${image.assets[0]}` + }; + }); + var content = { script: script, css: { files: cssFiles, modules: cssModules - } + }, + images: images }; fs.writeFileSync(filepath, JSON.stringify(content)); From d6f9fd141d357a85a0b32692e58189028422b06b Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 20:08:31 +0800 Subject: [PATCH 06/32] add the image server render example to the logo.png. Sorry for the bad CSS knowledge. --- src/views/Home.js | 16 +++++++++++++++- src/views/Home.scss | 11 +++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/views/Home.js b/src/views/Home.js index b7384c4f3..4483d3352 100755 --- a/src/views/Home.js +++ b/src/views/Home.js @@ -3,6 +3,7 @@ import path from 'path'; import CounterButton from '../components/CounterButton'; import GithubButton from '../components/GithubButton'; import {relativeToSrc} from '../util'; +import {requireServerImage} from '../util'; const styles = (function getStyle() { if (__CLIENT__) { @@ -12,13 +13,26 @@ const styles = (function getStyle() { return stats.css.modules[relativeToSrc(path.resolve(__dirname, './Home.scss'))]; })(); +// require the logo image both from client and server +let logoImage = "" +if(__CLIENT__) { + logoImage = require('./logo.png'); +} else { + logoImage = requireServerImage('./logo.png'); +} + + export default class Home extends Component { render() { return (
-
+
+

+ +

+

React Redux Example

All the modern best practices in one example.

diff --git a/src/views/Home.scss b/src/views/Home.scss index cf9a1e19f..6d31a4d57 100755 --- a/src/views/Home.scss +++ b/src/views/Home.scss @@ -9,13 +9,20 @@ $humility: #777; .logo { $size: 200px; margin: auto; - background: url('./logo.png') no-repeat center center; - background-size: 75%; height: $size; width: $size; border-radius: $size / 2; border: 1px solid $cyan; box-shadow: inset 0 0 10px $cyan; + vertical-align: middle; + p { + line-height: $size; + margin: 0px; + } + img { + width: 75%; + margin: auto; + } } h1 { color: $cyan; From fc9ab7b70fd401be8845931e144315bc704e4f1d Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 20:08:44 +0800 Subject: [PATCH 07/32] correct the util error :P --- src/util.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/util.js b/src/util.js index 88532d7d8..8b1aa4207 100755 --- a/src/util.js +++ b/src/util.js @@ -5,3 +5,32 @@ const pathToSrc = path.resolve(__dirname, '.'); export function relativeToSrc(value) { return value.slice(pathToSrc.length); } + +export function requireServerImage(imagePath) { + if(!imagePath) { + return ''; + } + if (__CLIENT__) { + throw new Error('image-resolver called on browser'); + } + else { + // Load images compiled from `webpack-stats` + // don't cache the `webpack-stats.json` on dev + // so we gonna read the file on each request + // on production, use simple `require` to cache the file + let images = require('../webpack-stats.json').images;; + if (__DEVELOPMENT__) { + delete require.cache[require.resolve('../webpack-stats.json')]; + } + + // Find the correct image + const regex = new RegExp(`${imagePath}$`); + const image = images.find(img => regex.test(img.original)); + + // Serve image. + if (image) return image.compiled; + + // Serve a not-found asset maybe? + return ''; + } +} From f6fcca3dff5e87358b2cacc851a9c76b287a13ed Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 20:16:12 +0800 Subject: [PATCH 08/32] update README. --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fda88837b..bce2135d1 100755 --- a/README.md +++ b/README.md @@ -81,16 +81,29 @@ This is where the meat of your server-side application goes. It doesn't have to To understand how the data and action bindings get into the components – there's only one, `InfoBar`, in this example – I'm going to refer to you to the [Redux](https://github.com/gaearon/redux) library. The only innovation I've made is to package the component and its wrapper in the same js file. This is to encapsulate the fact that the component is bound to the `redux` actions and state. The component using `InfoBar` needn't know or care if `InfoBar` uses the `redux` data or not. +#### Images + +Now it's able to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion, the usage would be like below (super easy): + +```javascript +let logoImage = "" +if(__CLIENT__) { + logoImage = require('./logo.png'); +} else { + logoImage = requireServerImage('./logo.png'); +} +``` + #### Styles This project uses [local styles](https://medium.com/seek-ui-engineering/the-end-of-global-css-90d2a4a06284) using [css-loader](https://github.com/webpack/css-loader). The way it works is that you import your stylesheet at the top of the class with your React Component, and then you use the classnames returned from that import. Like so: ```javascript const styles = (function getStyle() { - const stats = require('../../webpack-stats.json'); if (__CLIENT__) { return require('./App.scss'); } + const stats = require('../../webpack-stats.json'); return stats.css.modules[path.join(__dirname, './App.scss')]; })(); ``` From ecab6d2fd99968fac729a5ebae20c61fd47b5a81 Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 20:17:29 +0800 Subject: [PATCH 09/32] remove a space :P --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bce2135d1..4447feefe 100755 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ To understand how the data and action bindings get into the components – there #### Images -Now it's able to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion, the usage would be like below (super easy): +Now it's able to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion,the usage would be like below (super easy): ```javascript let logoImage = "" From b973036df86a49a734e3ab34bd87290bb27eeb19 Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 20:20:05 +0800 Subject: [PATCH 10/32] =?UTF-8?q?correct=20the=20=EF=BC=8C=20to=20,=20sorr?= =?UTF-8?q?y=20for=20my=20keyboard.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4447feefe..30398dc4a 100755 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ To understand how the data and action bindings get into the components – there #### Images -Now it's able to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion,the usage would be like below (super easy): +Now it's able to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion, the usage would be like below (super easy): ```javascript let logoImage = "" From cb4d43177f8960ab8eb1d62527ba5dc703b5b097 Mon Sep 17 00:00:00 2001 From: L Date: Thu, 30 Jul 2015 20:37:02 +0800 Subject: [PATCH 11/32] util import should be in single line. --- src/views/Home.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/views/Home.js b/src/views/Home.js index 4483d3352..95d25fd89 100755 --- a/src/views/Home.js +++ b/src/views/Home.js @@ -2,8 +2,7 @@ import React, {Component} from 'react'; import path from 'path'; import CounterButton from '../components/CounterButton'; import GithubButton from '../components/GithubButton'; -import {relativeToSrc} from '../util'; -import {requireServerImage} from '../util'; +import {relativeToSrc, requireServerImage} from '../util'; const styles = (function getStyle() { if (__CLIENT__) { From 8386da5432889422a03df114ec03f8dceb2be5f9 Mon Sep 17 00:00:00 2001 From: Darek Rossman Date: Thu, 30 Jul 2015 10:11:47 -0400 Subject: [PATCH 12/32] update universal router getFetchState Loop through all DecoratedComponent instances when looking for static fetchData method. This was needed when I had more than one decorator on a component (assuming my additional decorators used the same 'DecoratedComponent' static name. Also set default object for component param to avoid repetitive undefined checks. --- src/universalRouter.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/universalRouter.js b/src/universalRouter.js index 03e3f7cdb..65f64720e 100755 --- a/src/universalRouter.js +++ b/src/universalRouter.js @@ -3,22 +3,19 @@ import Router from 'react-router'; import routes from './views/routes'; import { Provider } from 'react-redux'; -const getFetchData = (component) => { - //need to check if the component is not undefined when using nested router without passing a component in props. - return (component && component.fetchData) || (component && component.DecoratedComponent && component.DecoratedComponent.fetchData); +const getFetchData = (component={}) => { + return component.DecoratedComponent ? + getFetchData(component.DecoratedComponent) : + component.fetchData; }; export function createTransitionHook(store) { return (nextState, transition, callback) => { Promise.all(nextState.branch .map(route => route.component) - .filter(component => { - return getFetchData(component); - }) + .filter(getFetchData(component)) .map(getFetchData) - .map(fetchData => { - return fetchData(store, nextState.params); - })) + .map(fetchData => fetchData(store, nextState.params)) .then(() => { callback(); // can't just pass callback to then() because callback assumes first param is error }, (error) => { From de8cd019e053cc8e582cb68fe626bda584e42c0b Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 16:25:05 +0200 Subject: [PATCH 13/32] work on forms --- src/actions/formActions.js | 12 ++++ src/reducers/createFormReducer.js | 24 ++++++++ src/validation/surveyValidation.js | 20 +++++++ src/views/Survey.js | 88 ++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 src/actions/formActions.js create mode 100644 src/reducers/createFormReducer.js create mode 100644 src/validation/surveyValidation.js create mode 100755 src/views/Survey.js diff --git a/src/actions/formActions.js b/src/actions/formActions.js new file mode 100644 index 000000000..f72730be5 --- /dev/null +++ b/src/actions/formActions.js @@ -0,0 +1,12 @@ +import { + FORM_CHANGE +} from './actionTypes'; + +export function formChange(form, field, value) { + return { + type: FORM_CHANGE, + form: form, + field: field, + value: value + }; +} diff --git a/src/reducers/createFormReducer.js b/src/reducers/createFormReducer.js new file mode 100644 index 000000000..2ae8b8510 --- /dev/null +++ b/src/reducers/createFormReducer.js @@ -0,0 +1,24 @@ +import { + FORM_CHANGE +} from '../actions/actionTypes'; + +export default function createFormReducer(name, validate, initialData = {}) { + return (state = {data: initialData, errors: {}}, action = {}) => { + switch (action.type) { + case FORM_CHANGE: + if (action.form === name) { + const data = { + ...state.data, + [action.field]: action.value + }; + console.info('data', data); + return { + ...state, + data: data, + errors: validate(data) + }; + } + } + return state; + }; +} diff --git a/src/validation/surveyValidation.js b/src/validation/surveyValidation.js new file mode 100644 index 000000000..8e6accfd0 --- /dev/null +++ b/src/validation/surveyValidation.js @@ -0,0 +1,20 @@ +const rules = { + name: (value) => { + if (value === undefined || value === null || value === '') { + return 'Required'; + } + }, + email: (value) => { + if (value === undefined || value === null || value === '') { + return 'Required'; + } + } +}; + +export default function surveyValidation(data = {}) { + const errors = {}; + Object.keys(rules).forEach((key) => { + errors[key] = rules[key](data[key]); + }); + return errors; +} \ No newline at end of file diff --git a/src/views/Survey.js b/src/views/Survey.js new file mode 100755 index 000000000..b5e5d39c9 --- /dev/null +++ b/src/views/Survey.js @@ -0,0 +1,88 @@ +import React, {Component, PropTypes} from 'react'; +import {formChange} from '../actions/formActions'; +import reduxForm from 'redux-form'; +import {relativeToSrc} from '../util'; + +@reduxForm('survey', formChange) +export default +class Survey extends Component { + static propTypes = { + data: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, + handleChange: PropTypes.func.isRequired + } + + handleSubmit(event) { + event.preventDefault(); + console.info('submitted', this.props.data); + } + + render() { + const { + data: {name, email, occupation}, + errors: {name: nameError, email: emailError, occupation: occupationError}, + handleChange + } = this.props; + console.info('dog', this.props.errors, nameError, emailError); + return ( +
+

Survey

+ +

+ This is an example of a form in redux in which all the state is kept within the redux store. + All the components are pure "dumb" components. +

+ +
+
+
+ + +
+ + {nameError &&
{nameError}
} +
+
+
+ + +
+ + {emailError &&
{emailError}
} +
+
+
+ + +
+ + {occupationError &&
{occupationError}
} +
+
+
+
+ +
+
+ +
+
Name: {name}
+
+ ); + } +} + From 43125f03107fcbcf2512e9dbca8844ac4da387e3 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 16:25:49 +0200 Subject: [PATCH 14/32] work on forms --- package.json | 1 + src/actions/actionTypes.js | 1 + src/reducers/index.js | 3 +++ src/views/App.js | 1 + src/views/routes.js | 2 ++ 5 files changed, 8 insertions(+) diff --git a/package.json b/package.json index ea9d77676..ddfdad7bb 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "react-router": "v1.0.0-beta2", "redux": "1.0.0-rc", "redux-devtools": "0.1.2", + "redux-form": "0.0.1", "serialize-javascript": "^1.0.0", "serve-favicon": "^2.3.0", "serve-static": "^1.10.0", diff --git a/src/actions/actionTypes.js b/src/actions/actionTypes.js index 3fa16587c..67b86981e 100644 --- a/src/actions/actionTypes.js +++ b/src/actions/actionTypes.js @@ -14,3 +14,4 @@ export const AUTH_LOGOUT = 'AUTH_LOGOUT'; export const AUTH_LOGOUT_SUCCESS = 'AUTH_LOGOUT_SUCCESS'; export const AUTH_LOGOUT_FAIL = 'AUTH_LOGOUT_FAIL'; export const COUNTER_INCREMENT = 'COUNTER_INCREMENT'; +export const FORM_CHANGE = 'FORM_CHANGE'; diff --git a/src/reducers/index.js b/src/reducers/index.js index fcf5d5dd1..7bd37ba10 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,4 +1,7 @@ +import createFormReducer from './createFormReducer'; +import surveyValidation from '../validation/surveyValidation'; export info from './info'; export widgets from './widgets'; export auth from './auth'; export counter from './counter'; +export const survey = createFormReducer('survey', surveyValidation); diff --git a/src/views/App.js b/src/views/App.js index e53c711db..7df750ce6 100755 --- a/src/views/App.js +++ b/src/views/App.js @@ -54,6 +54,7 @@ class App extends Component {
  • Widgets
  • +
  • Survey
  • About Us
  • Redirect to Home
  • {!user &&
  • Login
  • } diff --git a/src/views/routes.js b/src/views/routes.js index bac53dcce..0c891f68d 100755 --- a/src/views/routes.js +++ b/src/views/routes.js @@ -5,6 +5,7 @@ import Home from 'views/Home'; import Widgets from 'views/Widgets'; import About from 'views/About'; import Login from 'views/Login'; +import Survey from 'views/Survey'; import NotFound from 'views/NotFound'; import Redirect from 'views/Redirect'; @@ -14,6 +15,7 @@ export default ( + From 03c1d2c7b92b12894aded1ff203947cf49c8deb3 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 17:15:33 +0200 Subject: [PATCH 15/32] incorporated PR #67 and added some comments to promise chaining in createTransitionHook() --- src/universalRouter.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/universalRouter.js b/src/universalRouter.js index 65f64720e..0d5b98bac 100755 --- a/src/universalRouter.js +++ b/src/universalRouter.js @@ -11,11 +11,12 @@ const getFetchData = (component={}) => { export function createTransitionHook(store) { return (nextState, transition, callback) => { - Promise.all(nextState.branch - .map(route => route.component) - .filter(getFetchData(component)) - .map(getFetchData) - .map(fetchData => fetchData(store, nextState.params)) + const promises = nextState.branch + .map(route => route.component) // pull out individual route components + .filter((component) => getFetchData(component)) // only look at ones with a static fetchData() + .map(getFetchData) // pull out fetch data methods + .map(fetchData => fetchData(store, nextState.params)); // call fetch data methods and save promises + Promise.all(promises) .then(() => { callback(); // can't just pass callback to then() because callback assumes first param is error }, (error) => { From 82fcf67bfc3e594e94f30b48e8cd575cdb1f3462 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 17:16:33 +0200 Subject: [PATCH 16/32] made pass lint --- src/server.js | 13 ++++++------- src/universalRouter.js | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/server.js b/src/server.js index ea481e675..bbc382e9d 100755 --- a/src/server.js +++ b/src/server.js @@ -51,13 +51,12 @@ app.use((req, res) => { } else { universalRouter(location, undefined, store) .then(({component, transition, isRedirect}) => { - - if (isRedirect) { - res.redirect(transition.redirectInfo.pathname); - return; - } - res.send('\n' + - React.renderToString()); + if (isRedirect) { + res.redirect(transition.redirectInfo.pathname); + return; + } + res.send('\n' + + React.renderToString()); }) .catch((error) => { console.error('ROUTER ERROR:', pretty.render(error)); diff --git a/src/universalRouter.js b/src/universalRouter.js index 0d5b98bac..475a11116 100755 --- a/src/universalRouter.js +++ b/src/universalRouter.js @@ -4,7 +4,7 @@ import routes from './views/routes'; import { Provider } from 'react-redux'; const getFetchData = (component={}) => { - return component.DecoratedComponent ? + return component.DecoratedComponent ? getFetchData(component.DecoratedComponent) : component.fetchData; }; From bcff60732b7ff2ac77c185381c402ac43bc45683 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 17:44:29 +0200 Subject: [PATCH 17/32] merged PR #67. lint-corrected merge. added obligatory cat pic. changed to use url-loader to encode small images. --- .gitignore | 1 + src/util.js | 12 +++++++----- src/views/About.js | 24 +++++++++++++++++++++++- src/views/Home.js | 3 +-- src/views/kitten.jpg | Bin 0 -> 92171 bytes webpack/dev.config.js | 2 +- webpack/utils/writeStats.js | 8 ++++---- 7 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 src/views/kitten.jpg diff --git a/.gitignore b/.gitignore index 0f2eab59d..9d79b6e70 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules/ dist/ *.iml webpack-stats.json +npm-debug.log diff --git a/src/util.js b/src/util.js index 8b1aa4207..a238d1f69 100755 --- a/src/util.js +++ b/src/util.js @@ -7,21 +7,23 @@ export function relativeToSrc(value) { } export function requireServerImage(imagePath) { - if(!imagePath) { + if (!imagePath) { return ''; } if (__CLIENT__) { - throw new Error('image-resolver called on browser'); - } - else { + throw new Error('image-resolver called on browser'); + } else { // Load images compiled from `webpack-stats` // don't cache the `webpack-stats.json` on dev // so we gonna read the file on each request // on production, use simple `require` to cache the file - let images = require('../webpack-stats.json').images;; + let images = require('../webpack-stats.json').images; if (__DEVELOPMENT__) { delete require.cache[require.resolve('../webpack-stats.json')]; } + if (!images) { + return ''; + } // Find the correct image const regex = new RegExp(`${imagePath}$`); diff --git a/src/views/About.js b/src/views/About.js index 8a3c97457..d4caba180 100755 --- a/src/views/About.js +++ b/src/views/About.js @@ -2,7 +2,16 @@ import React, {Component} from 'react'; import MiniInfoBar from '../components/MiniInfoBar'; export default class About extends Component { + state = { + kitten: false + } + + handleToggleKitten() { + this.setState({kitten: !this.state.kitten}); + } + render() { + const {kitten} = this.state; return (
    @@ -18,9 +27,22 @@ export default class About extends Component {

    Mini Bar (not that kind)

    Hey! You found the mini info bar! The following component is display-only. Note that it shows the same - time as the info bar.

    + time as the info bar.

    + +

    Images

    + +

    + Psst! Would you like to see a kitten? + + +

    + + {kitten &&
    }
    ); diff --git a/src/views/Home.js b/src/views/Home.js index 95d25fd89..e3112f43f 100755 --- a/src/views/Home.js +++ b/src/views/Home.js @@ -13,14 +13,13 @@ const styles = (function getStyle() { })(); // require the logo image both from client and server -let logoImage = "" +let logoImage = '' if(__CLIENT__) { logoImage = require('./logo.png'); } else { logoImage = requireServerImage('./logo.png'); } - export default class Home extends Component { render() { return ( diff --git a/src/views/kitten.jpg b/src/views/kitten.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1fc4c6cefb21a0a7f2de261b524c245284f484a GIT binary patch literal 92171 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

    D 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 z -1 ? i + 1 : 0, name.length + 1); } @@ -68,7 +68,7 @@ module.exports = function writeStats(stats, env) { .map(function(image) { return { original: image.name, - compiled: `${publicPath}${image.assets[0]}` + compiled: publicPath + image.assets[0] }; }); From 6712c5147a74061e8e4923f2c0171d4bad35934e Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 17:45:55 +0200 Subject: [PATCH 18/32] added url-loader to production webpack, too --- webpack/prod.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack/prod.config.js b/webpack/prod.config.js index be0d40f9a..f708f627f 100755 --- a/webpack/prod.config.js +++ b/webpack/prod.config.js @@ -24,7 +24,7 @@ module.exports = { }, module: { loaders: [ - { test: /\.(jpe?g|png|gif|svg)$/, loader: 'file' }, + { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, { test: /\.js$/, exclude: /node_modules/, loaders: [strip.loader('debug'), 'babel?stage=0&optional=runtime&plugins=typecheck']}, { test: /\.json$/, loader: 'json-loader' }, { test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=2!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true') } From 2eed11302c910d1e0136912d470af7e0594b8df4 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 17:49:45 +0200 Subject: [PATCH 19/32] minor grammar and js style tweak to README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 30398dc4a..77dda2436 100755 --- a/README.md +++ b/README.md @@ -83,10 +83,10 @@ To understand how the data and action bindings get into the components – there #### Images -Now it's able to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion, the usage would be like below (super easy): +Now it's possible to render the image both on client and server. Please refer to issue [#39](https://github.com/erikras/react-redux-universal-hot-example/issues/39) for more detail discussion, the usage would be like below (super easy): ```javascript -let logoImage = "" +let logoImage = ''; if(__CLIENT__) { logoImage = require('./logo.png'); } else { From a8321a95d48893ae30a2bc2c5d959e41656355cf Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 17:53:16 +0200 Subject: [PATCH 20/32] fixed cat pic on server render --- src/views/About.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/views/About.js b/src/views/About.js index d4caba180..5ee087b56 100755 --- a/src/views/About.js +++ b/src/views/About.js @@ -1,17 +1,20 @@ import React, {Component} from 'react'; import MiniInfoBar from '../components/MiniInfoBar'; +import {requireServerImage} from '../util'; + +const kitten = __CLIENT__ ? require('./kitten.jpg') : requireServerImage('./kitten.jpg'); export default class About extends Component { state = { - kitten: false + showKitten: false } handleToggleKitten() { - this.setState({kitten: !this.state.kitten}); + this.setState({showKitten: !this.state.showKitten}); } render() { - const {kitten} = this.state; + const {showKitten} = this.state; return (

    @@ -36,13 +39,13 @@ export default class About extends Component {

    Psst! Would you like to see a kitten? - + {showKitten ? 'No! Take it away!' : 'Yes! Please!'}

    - {kitten &&
    } + {showKitten &&
    }
    ); From cf65483d2be49756a74d728fa8045d92fe256b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20=C3=85n=C3=B6stam?= Date: Thu, 30 Jul 2015 21:07:29 +0200 Subject: [PATCH 21/32] Added better-npm-run to allow setting env-vars on all platforms --- package.json | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ea9d77676..fae19568c 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,37 @@ ], "main": "babel.server.js", "scripts": { - "start": "NODE_PATH=\"./src\" NODE_ENV=\"production\" PORT=\"8080\" node ./babel.server", + "start": "better-npm-run start", "build": "node ./node_modules/webpack/bin/webpack.js --verbose --colors --display-error-details --config webpack/prod.config.js", "lint": "node ./node_modules/eslint/bin/eslint.js -c .eslintrc src", - "start-dev": "NODE_PATH=\"./src\" NODE_ENV=\"development\" node ./babel.server", - "watch-client": "UV_THREADPOOL_SIZE=100 NODE_PATH=\"./src\" node webpack/webpack-dev-server.js", + "start-dev": "better-npm-run start-dev", + "watch-client": "better-npm-run watch-client", "dev": "node ./node_modules/concurrently/src/main.js --kill-others \"npm run watch-client\" \"npm run start-dev\"" }, + "betterScripts": { + "start": { + "command": "node ./babel.server", + "env": { + "NODE_PATH": "./src", + "NODE_ENV": "production", + "PORT": 8080 + } + }, + "start-dev": { + "command": "node ./babel.server", + "env": { + "NODE_PATH": "./src", + "NODE_ENV": "development" + } + }, + "watch-client": { + "command": "node webpack/webpack-dev-server.js", + "env": { + "UV_THREADPOOL_SIZE": 100, + "NODE_PATH": "./src" + } + } + }, "dependencies": { "babel": "5.4.7", "babel-plugin-typecheck": "0.0.3", @@ -60,6 +84,7 @@ "babel-eslint": "^3.1.18", "babel-loader": "5.1.3", "babel-runtime": "5.4.7", + "better-npm-run": "0.0.1", "clean-webpack-plugin": "^0.1.3", "concurrently": "0.1.1", "css-loader": "^0.15.1", From e775cc9fe3cc53a2a5e5ddb0f17e61a22856e2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20=C3=85n=C3=B6stam?= Date: Thu, 30 Jul 2015 21:58:29 +0200 Subject: [PATCH 22/32] Works on mac now --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fae19568c..5b40bf4f5 100644 --- a/package.json +++ b/package.json @@ -24,16 +24,16 @@ ], "main": "babel.server.js", "scripts": { - "start": "better-npm-run start", + "start": "node ./node_modules/better-npm-run start", "build": "node ./node_modules/webpack/bin/webpack.js --verbose --colors --display-error-details --config webpack/prod.config.js", "lint": "node ./node_modules/eslint/bin/eslint.js -c .eslintrc src", - "start-dev": "better-npm-run start-dev", - "watch-client": "better-npm-run watch-client", + "start-dev": "node ./node_modules/better-npm-run start-dev", + "watch-client": "node ./node_modules/better-npm-run watch-client", "dev": "node ./node_modules/concurrently/src/main.js --kill-others \"npm run watch-client\" \"npm run start-dev\"" }, "betterScripts": { "start": { - "command": "node ./babel.server", + "command": "node ./babel.server.js", "env": { "NODE_PATH": "./src", "NODE_ENV": "production", @@ -41,7 +41,7 @@ } }, "start-dev": { - "command": "node ./babel.server", + "command": "node ./babel.server.js", "env": { "NODE_PATH": "./src", "NODE_ENV": "development" From 238cb386b146c64728bd36ae38b9905dcc113501 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Thu, 30 Jul 2015 23:02:49 +0200 Subject: [PATCH 23/32] switched back to file-loader to avoid error from requireServerImage() fixes #39 --- webpack/dev.config.js | 3 ++- webpack/prod.config.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/webpack/dev.config.js b/webpack/dev.config.js index 7095f8fd3..e5ba13ef6 100755 --- a/webpack/dev.config.js +++ b/webpack/dev.config.js @@ -24,7 +24,8 @@ module.exports = { }, module: { loaders: [ - { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, + { test: /\.(jpe?g|png|gif|svg)$/, loader: 'file' }, + //{ test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, { test: /\.js$/, exclude: /node_modules/, loaders: ['react-hot', 'babel?stage=0&optional=runtime&plugins=typecheck']}, { test: /\.json$/, loader: 'json-loader' }, { test: /\.scss$/, loader: 'style!css?modules&importLoaders=2&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true' } diff --git a/webpack/prod.config.js b/webpack/prod.config.js index f708f627f..d0884ddc7 100755 --- a/webpack/prod.config.js +++ b/webpack/prod.config.js @@ -24,7 +24,8 @@ module.exports = { }, module: { loaders: [ - { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, + //{ test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, + { test: /\.(jpe?g|png|gif|svg)$/, loader: 'file' }, { test: /\.js$/, exclude: /node_modules/, loaders: [strip.loader('debug'), 'babel?stage=0&optional=runtime&plugins=typecheck']}, { test: /\.json$/, loader: 'json-loader' }, { test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=2!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true') } From 3100d143faef86866eb25ff94e9310343582b6b0 Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Thu, 30 Jul 2015 14:14:51 -0500 Subject: [PATCH 24/32] url-loader fix for images --- webpack/dev.config.js | 3 +-- webpack/utils/writeStats.js | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/webpack/dev.config.js b/webpack/dev.config.js index e5ba13ef6..7095f8fd3 100755 --- a/webpack/dev.config.js +++ b/webpack/dev.config.js @@ -24,8 +24,7 @@ module.exports = { }, module: { loaders: [ - { test: /\.(jpe?g|png|gif|svg)$/, loader: 'file' }, - //{ test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, + { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, { test: /\.js$/, exclude: /node_modules/, loaders: ['react-hot', 'babel?stage=0&optional=runtime&plugins=typecheck']}, { test: /\.json$/, loader: 'json-loader' }, { test: /\.scss$/, loader: 'style!css?modules&importLoaders=2&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true' } diff --git a/webpack/utils/writeStats.js b/webpack/utils/writeStats.js index fe98d3a15..452ce0280 100755 --- a/webpack/utils/writeStats.js +++ b/webpack/utils/writeStats.js @@ -66,9 +66,12 @@ module.exports = function writeStats(stats, env) { return imagesRegex.test(module.name); }) .map(function(image) { + const i = image.source.indexOf("\""); + var imageSource = image.source.slice(i + 1, -1); + imageSource = imageSource.lastIndexOf('data:image', 0) === 0 ? imageSource : publicPath + imageSource; return { original: image.name, - compiled: publicPath + image.assets[0] + compiled: imageSource }; }); From 168b2b92bb056261983da61fa1ec03daf7ab8325 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Fri, 31 Jul 2015 00:15:07 +0200 Subject: [PATCH 25/32] linted --- src/views/Home.js | 7 +++++-- webpack/prod.config.js | 3 +-- webpack/utils/writeStats.js | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/views/Home.js b/src/views/Home.js index e3112f43f..d144f10de 100755 --- a/src/views/Home.js +++ b/src/views/Home.js @@ -13,8 +13,8 @@ const styles = (function getStyle() { })(); // require the logo image both from client and server -let logoImage = '' -if(__CLIENT__) { +let logoImage = ''; +if (__CLIENT__) { logoImage = require('./logo.png'); } else { logoImage = requireServerImage('./logo.png'); @@ -96,6 +96,7 @@ export default class Home extends Component {

From the author

+

I cobbled this together from a wide variety of similar "starter" repositories. As I post this in June 2015, all of these libraries are right at the bleeding edge of web development. They may fall out of fashion as @@ -103,7 +104,9 @@ export default class Home extends Component { and will survive for several years. I'm building my new projects like this, and I recommend that you do, too.

+

Thanks for taking the time to check this out.

+

– Erik Rasmussen

diff --git a/webpack/prod.config.js b/webpack/prod.config.js index d0884ddc7..f708f627f 100755 --- a/webpack/prod.config.js +++ b/webpack/prod.config.js @@ -24,8 +24,7 @@ module.exports = { }, module: { loaders: [ - //{ test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, - { test: /\.(jpe?g|png|gif|svg)$/, loader: 'file' }, + { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url', query: {limit: 10240} }, { test: /\.js$/, exclude: /node_modules/, loaders: [strip.loader('debug'), 'babel?stage=0&optional=runtime&plugins=typecheck']}, { test: /\.json$/, loader: 'json-loader' }, { test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=2!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true') } diff --git a/webpack/utils/writeStats.js b/webpack/utils/writeStats.js index 452ce0280..238265502 100755 --- a/webpack/utils/writeStats.js +++ b/webpack/utils/writeStats.js @@ -66,7 +66,7 @@ module.exports = function writeStats(stats, env) { return imagesRegex.test(module.name); }) .map(function(image) { - const i = image.source.indexOf("\""); + var i = image.source.indexOf('"'); var imageSource = image.source.slice(i + 1, -1); imageSource = imageSource.lastIndexOf('data:image', 0) === 0 ? imageSource : publicPath + imageSource; return { From 4cc87c9d4210f020cee6975a1e589b523c153fc6 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Fri, 31 Jul 2015 00:23:23 +0200 Subject: [PATCH 26/32] added apology for #60 in the README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 77dda2436..a9b8b45f7 100755 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ npm install npm run dev ``` +Unfortunately, you'll have to run this twice, because the build depends on a file, `webpack-stats.json` generated by the build itself. [If you can solve this, please do.](https://github.com/erikras/react-redux-universal-hot-example/issues/60) + ## Building and Running Production Server ``` From ea785b262bfa2548096e33972d909784ac248156 Mon Sep 17 00:00:00 2001 From: L Date: Fri, 31 Jul 2015 15:11:22 +0800 Subject: [PATCH 27/32] fixed erikras/react-redux-universal-hot-example#77 --- .eslintignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..ba224b4e2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +webpack/* From 44f0d5d89d262d3f020ece0eb257cde8433340e0 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Fri, 31 Jul 2015 12:31:34 +0200 Subject: [PATCH 28/32] improved syntax for including styles --- README.md | 12 +++------ src/components/InfoBar.js | 11 ++------ src/util.js | 53 +++++++++++++++++++------------------ src/views/App.js | 11 +++----- src/views/Home.js | 11 ++------ src/views/Login.js | 11 ++------ src/views/Widgets.js | 11 ++------ webpack/utils/writeStats.js | 9 ++++--- 8 files changed, 47 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index a9b8b45f7..f4ba1530c 100755 --- a/README.md +++ b/README.md @@ -101,16 +101,12 @@ if(__CLIENT__) { This project uses [local styles](https://medium.com/seek-ui-engineering/the-end-of-global-css-90d2a4a06284) using [css-loader](https://github.com/webpack/css-loader). The way it works is that you import your stylesheet at the top of the class with your React Component, and then you use the classnames returned from that import. Like so: ```javascript -const styles = (function getStyle() { - if (__CLIENT__) { - return require('./App.scss'); - } - const stats = require('../../webpack-stats.json'); - return stats.css.modules[path.join(__dirname, './App.scss')]; -})(); +const styles = __CLIENT__ ? + require('./App.scss') : + requireServerCss(require.resolve('./App.scss')); ``` -That's a little ugly, I know, but what it allows is very powerful. +Then you set the `className` of your element ot match one of the CSS classes in your SCSS file, and you're good to go! ```jsx
...
diff --git a/src/components/InfoBar.js b/src/components/InfoBar.js index e329f3cf4..47fbebd2f 100755 --- a/src/components/InfoBar.js +++ b/src/components/InfoBar.js @@ -1,17 +1,10 @@ -import path from 'path'; import React, {Component, PropTypes} from 'react'; import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; import * as infoActions from '../actions/infoActions'; -import {relativeToSrc} from '../util'; +import {requireServerCss} from '../util'; -const styles = (function getStyle() { - if (__CLIENT__) { - return require('./InfoBar.scss'); - } - const stats = require('../../webpack-stats.json'); - return stats.css.modules[relativeToSrc(path.join(__dirname, './InfoBar.scss'))]; -})(); +const styles = __CLIENT__ ? require('./InfoBar.scss') : requireServerCss(require.resolve('./InfoBar.scss')); class InfoBar extends Component { static propTypes = { diff --git a/src/util.js b/src/util.js index a238d1f69..7c6ef5e58 100755 --- a/src/util.js +++ b/src/util.js @@ -1,9 +1,18 @@ -import path from 'path'; - -const pathToSrc = path.resolve(__dirname, '.'); +const readStats = () => { + // don't cache the `webpack-stats.json` on dev so we read the file on each request. + // on production, use simple `require` to cache the file + const stats = require('../webpack-stats.json'); + if (__DEVELOPMENT__) { + delete require.cache[require.resolve('../webpack-stats.json')]; + } + return stats; +} -export function relativeToSrc(value) { - return value.slice(pathToSrc.length); +export function requireServerCss(cssPath) { + if (__CLIENT__) { + throw new Error('image-resolver called on browser'); + } + return readStats().css.modules[cssPath.slice(__dirname.length)]; } export function requireServerImage(imagePath) { @@ -11,28 +20,20 @@ export function requireServerImage(imagePath) { return ''; } if (__CLIENT__) { - throw new Error('image-resolver called on browser'); - } else { - // Load images compiled from `webpack-stats` - // don't cache the `webpack-stats.json` on dev - // so we gonna read the file on each request - // on production, use simple `require` to cache the file - let images = require('../webpack-stats.json').images; - if (__DEVELOPMENT__) { - delete require.cache[require.resolve('../webpack-stats.json')]; - } - if (!images) { - return ''; - } + throw new Error('server-side only resolver called on client'); + } + const images = readStats().images; + if (!images) { + return ''; + } - // Find the correct image - const regex = new RegExp(`${imagePath}$`); - const image = images.find(img => regex.test(img.original)); + // Find the correct image + const regex = new RegExp(`${imagePath}$`); + const image = images.find(img => regex.test(img.original)); - // Serve image. - if (image) return image.compiled; + // Serve image. + if (image) return image.compiled; - // Serve a not-found asset maybe? - return ''; - } + // Serve a not-found asset maybe? + return ''; } diff --git a/src/views/App.js b/src/views/App.js index e53c711db..2cc14d0cb 100755 --- a/src/views/App.js +++ b/src/views/App.js @@ -10,15 +10,9 @@ import * as authActions from '../actions/authActions'; import {load as loadAuth} from '../actions/authActions'; import InfoBar from '../components/InfoBar'; import {createTransitionHook} from '../universalRouter'; -import {relativeToSrc} from '../util'; +import {requireServerCss} from '../util'; -const styles = (function getStyle() { - if (__CLIENT__) { - return require('./App.scss'); - } - const stats = require('../../webpack-stats.json'); - return stats.css.modules[relativeToSrc(path.resolve(__dirname, './App.scss'))]; -})(); +const styles = __CLIENT__ ? require('./App.scss') : requireServerCss(require.resolve('./App.scss')); class App extends Component { static propTypes = { @@ -43,6 +37,7 @@ class App extends Component { render() { const {user} = this.props; + debugger; return (