You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _posts/2015-12-12-isomorphic-react-in-real-life.md
+64-16Lines changed: 64 additions & 16 deletions
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ published: true
8
8
categories: react, redux, isomorphic
9
9
---
10
10
11
-
This post is not a tutorial. There are enough of them on the Internet. It is always more interesting to look at a real production app. A lot of tutorials and boilerplates show how to write isomorphic ReactJS applications, but they do not cover a lot of real-life problems we've faced in production (styling, data-fetching, vendor-prefixes, configutation etc). So we decided to share our experience at github and develop the app in a [public repo](https://github.com/webbylab/itsquiz-wall). The post describes all the issues and howto to deal with them.
11
+
This post is not a tutorial. There are enough of them on the Internet. It is always more interesting to look at a real production app. A lot of tutorials and boilerplates show how to write isomorphic ReactJS applications, but they do not cover a lot of real-life problems we've faced in production (styling, data-fetching, vendor-prefixes, configutation etc). So we decided to share our experience at github and develop the app in a [public repo](https://github.com/webbylab/itsquiz-wall). The post describes all the issues and howto to deal with them.
12
12
13
13
<!--more-->
14
14
@@ -231,6 +231,27 @@ You can find whole [production config on github](https://github.com/WebbyLab/its
231
231
232
232
Alternative solution is to create a plugin for babel that will just return "{}" on the server. I am not sure that it possible to do. If you can create babel-stub-plugin - it will be awesome.
233
233
234
+
**UPDATE: We've switched to the alternative solution after migrating to Babel 6**
235
+
236
+
We use [babel-plugin-transform-require-ignore](https://www.npmjs.com/package/babel-plugin-transform-require-ignore) plugin for Babel 6. Special thanks to @morlay (Morlay Null) for the plugin.
237
+
238
+
All you need is to configure file extentions that should be ignored by babel in [.babelrc](https://github.com/WebbyLab/itsquiz-wall/blob/master/.babelrc)
and set environment variable BABEL_ENV='node' before starting your app. So, you can start your app like that [`cross-env BABEL_ENV='node' nodemon server/runner.js`](https://github.com/WebbyLab/itsquiz-wall/blob/7fb861ca09a4759b1b3622ab69d0cd610303da8e/package.json#L14).
254
+
234
255
#### Pain #3: Material UI uses vendor prefixing based on browser DOM
235
256
236
257
Ok. Let's go further. We managed our styles. And it seems that the problems with styles are solved. We use [Material UI](http://material-ui.com/) components library for our UI and we like it. But the problem with it is that it uses the same approach to vendor autoprefixing as Radium.
@@ -414,30 +435,54 @@ In browser the wrapper component will call action creators in **componentDidMoun
414
435
415
436
*IMPORTANT: componentWillMount is not suitable for this because it will be invoked on the client and server. componentDidMount will be invoked only on the client.*
416
437
417
-
On the server we do this in a different way. We have a function ["fetchComponentsData"](https://github.com/WebbyLab/itsquiz-wall/blob/master/server/utils.js#L4) which takes an array of components you are going to render and calls static method "fetchData" on each. One important thing is a usage of promises. We use promises to postpone rendering until the required data is fetched and saved to the redux store.
438
+
On the server we do this in a different way. We have a function ["fetchComponentsData"](https://github.com/WebbyLab/itsquiz-wall/blob/master/server/utils.js#L12) which takes an array of components you are going to render and calls static method "fetchData" on each. One important thing is a usage of promises. We use promises to postpone rendering until the required data is fetched and saved to the redux store.
@@ -450,6 +495,8 @@ export default function connectDataFetchers(Component, actionCreators) {
450
495
451
496
```
452
497
498
+
[Production version](https://github.com/WebbyLab/itsquiz-wall/blob/master/shared/lib/connectDataFetchers.jsx) a little bit longer. It passes locale information and has propTypes described.
499
+
453
500
So, on server our code looks like:
454
501
455
502
```javascript
@@ -494,13 +541,15 @@ We load out config on the server and return it in index.html
*IMPORTANT: Serialization of initialState with JSON.stringify will make your application vulnerable to XSS attacks!!! You should use [serialize-javascript](https://github.com/yahoo/serialize-javascript) instead!*
552
+
504
553
505
554
But depending on a global variable in your code is not a good idea. So, we create "config.js" module that just exports global variable. And our code depends on "config.js" module. Our "config.js" should be isomorphic, so on the server we just require json file.
506
555
@@ -538,4 +587,3 @@ Very few tutorials explain how to deal with localization in a regular SPA. No tu
538
587
* Server specific code - 139 SLOC (5.4%)
539
588
540
589
While all codebase growths, isomorphic part of the code growths the most. So, code reuse rate will become higher with time.
0 commit comments