Giter Club home page Giter Club logo

react-redux-universal-hot-example's Introduction

React Redux Universal Hot Example

build status Dependency Status devDependency Status react-redux-universal channel on discord Demo on Heroku PayPal donate button


About

This is a starter boilerplate app I've put together using the following technologies:

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 quickly as they have come into it, but I personally believe that this stack is the future of web development and will survive for several years. I'm building my new projects like this, and I recommend that you do, too.

Installation

npm install

Running Dev Server

npm run dev

The first time it may take a little while to generate the first webpack-assets.json and complain with a few dozen [webpack-isomorphic-tools] (waiting for the first Webpack build to finish) printouts, but be patient. Give it 30 seconds.

Using Redux DevTools

Redux Devtools are enabled by default in development.

If you have the Redux DevTools chrome extension installed it will automatically be used on the client-side instead.

If you want to disable the dev tools during development, set __DEVTOOLS__ to false in /webpack/dev.config.js.
DevTools are not enabled during production.

Building and Running Production Server

npm run build
npm run start

Demo

A demonstration of this app can be seen running on heroku, which is a deployment of the heroku branch.

Documentation

Explanation

What initially gets run is bin/server.js, which does little more than enable ES6 and ES7 awesomeness in the server-side node code. It then initiates server.js. In server.js we proxy any requests to /api/* to the API server, running at localhost:3030. All the data fetching calls from the client go to /api/*. Aside from serving the favicon and static content from /static, the only thing server.js does is initiate delegate rendering to react-router. At the bottom of server.js, we listen to port 3000 and initiate the API server.

Routing and HTML return

The primary section of server.js generates an HTML page with the contents returned by react-router. First we instantiate an ApiClient, a facade that both server and client code use to talk to the API server. On the server side, ApiClient is given the request object so that it can pass along the session cookie to the API server to maintain session state. We pass this API client facade to the redux middleware so that the action creators have access to it.

Then we perform server-side data fetching, wait for the data to be loaded, and render the page with the now-fully-loaded redux state.

The last interesting bit of the main routing section of server.js is that we swap in the hashed script and css from the webpack-assets.json that the Webpack Dev Server – or the Webpack build process on production – has spit out on its last run. You won't have to deal with webpack-assets.json manually because webpack-isomorphic-tools take care of that.

We also spit out the redux state into a global window.__data variable in the webpage to be loaded by the client-side redux code.

Server-side Data Fetching

The redux-async-connect package exposes an API to return promises that need to be fulfilled before a route is rendered. It exposes a <ReduxAsyncConnect /> container, which wraps our render tree on both server and client. More documentation is available on the redux-async-connect page.

Client Side

The client side entry point is reasonably named client.js. All it does is load the routes, initiate react-router, rehydrate the redux state from the window.__data passed in from the server, and render the page over top of the server-rendered DOM. This makes React enable all its event listeners without having to re-render the DOM.

Redux Middleware

The middleware, clientMiddleware.js, serves two functions:

  1. To allow the action creators access to the client API facade. Remember this is the same on both the client and the server, and cannot simply be imported because it holds the cookie needed to maintain session on server-to-server requests.
  2. To allow some actions to pass a "promise generator", a function that takes the API client and returns a promise. Such actions require three action types, the REQUEST action that initiates the data loading, and a SUCCESS and FAILURE action that will be fired depending on the result of the promise. There are other ways to accomplish this, some discussed here, which you may prefer, but to the author of this example, the middleware way feels cleanest.

Redux Modules... What the Duck?

The src/redux/modules folder contains "modules" to help isolate concerns within a Redux application (aka Ducks, a Redux Style Proposal that I came up with). I encourage you to read the Ducks Docs and provide feedback.

API Server

This is where the meat of your server-side application goes. It doesn't have to be implemented in Node or Express at all. This is where you connect to your database and provide authentication and session management. In this example, it's just spitting out some json with the current time stamp.

Getting data and actions into components

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 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 possible to render the image both on client and server. Please refer to issue #39 for more detail discussion, the usage would be like below (super easy):

let logoImage = require('./logo.png');

Styles

This project uses local styles using css-loader. The way it works is that you import your stylesheet at the top of the render() function in your React Component, and then you use the classnames returned from that import. Like so:

render() {
const styles = require('./App.scss');
...

Then you set the className of your element to match one of the CSS classes in your SCSS file, and you're good to go!

<div className={styles.mySection}> ... </div>

Alternative to Local Styles

If you'd like to use plain inline styles this is possible with a few modifications to your webpack configuration.

1. Configure Isomorphic Tools to Accept CSS

In webpack-isomorphic-tools.js add css to the list of style module extensions

    style_modules: {
      extensions: ['less','scss','css'],

2. Add a CSS loader to webpack dev config

In dev.config.js modify module loaders to include a test and loader for css

  module: {
    loaders: [
      { test: /\.css$/, loader: 'style-loader!css-loader'},

3. Add a CSS loader to the webpack prod config

You must use the ExtractTextPlugin in this loader. In prod.config.js modify module loaders to include a test and loader for css

  module: {
    loaders: [
      { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader')},

Now you may simply omit assigning the required stylesheet to a variable and keep it at the top of your render() function.

render() {
require('./App.css');
require('aModule/dist/style.css');
...

NOTE In order to use this method with scss or less files one more modification must be made. In both dev.config.js and prod.config.js in the loaders for less and scss files remove

  1. modules
  2. localIdentName...

Before:

{ test: /\.less$/, loader: 'style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!less?outputStyle=expanded&sourceMap' },

After:

{ test: /\.less$/, loader: 'style!css?importLoaders=2&sourceMap!autoprefixer?browsers=last 2 version!less?outputStyle=expanded&sourceMap' },

After this modification to both loaders you will be able to use scss and less files in the same way as css files.

Unit Tests

The project uses Mocha to run your unit tests, it uses Karma as the test runner, it enables the feature that you are able to render your tests to the browser (e.g: Firefox, Chrome etc.), which means you are able to use the Test Utilities from Facebook api like renderIntoDocument().

To run the tests in the project, just simply run npm test if you have Chrome installed, it will be automatically launched as a test service for you.

To keep watching your test suites that you are working on, just set singleRun: false in the karma.conf.js file. Please be sure set it to true if you are running npm test on a continuous integration server (travis-ci, etc).

Deployment on Heroku

To get this project to work on Heroku, you need to:

  1. Remove the "PORT": 8080 line from the betterScripts / start-prod section of package.json.
  2. heroku config:set NODE_ENV=production
  3. heroku config:set NODE_PATH=./src
  4. heroku config:set NPM_CONFIG_PRODUCTION=false
  • This is to enable webpack to run the build on deploy.

The first deploy might take a while, but after that your node_modules dir should be cached.

FAQ

This project moves fast and has an active community, so if you have a question that is not answered below please visit our Discord channel or file an issue.

Roadmap

Although this isn't a library, we recently started versioning to make it easier to track breaking changes and emerging best practices.

Contributing

I am more than happy to accept external contributions to the project in the form of feedback, bug reports and even better - pull requests :)

If you would like to submit a pull request, please make an effort to follow the guide in CONTRIBUTING.md.


Thanks for checking this out.

– Erik Rasmussen, @erikras

react-redux-universal-hot-example's People

Contributors

andrewmclagan avatar arkist avatar bdefore avatar benoitvallon avatar carlyle avatar catamphetamine avatar chadoh avatar erikras avatar gaearon avatar greenkeeperio-bot avatar gusaiani avatar jneto avatar justingreenberg avatar korczis avatar leonli avatar markus-ipse avatar merriam avatar methodgrab avatar mhodgson avatar nicolabortignon avatar nogsmpls avatar psalz avatar quicksnap avatar snowcxt avatar standuprey avatar stevoland avatar strawbrary avatar swordsreversed avatar trueter avatar yuters avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-redux-universal-hot-example's Issues

integrate redux-react-router

i tried so myself but to no avail.

has to be a context problem because i get Warning: Failed Context Types: Required context 'store' was not specified in 'Connector'. Check the render method of 'Connector(AppContainer)'.

Does not work on windows

I've tried to run the server, but no luck. I'm on Win7.

I also pulled the repo now, but same results. My node version is v0.12.5 NPM: v.2.11.2

clipboard01

Only restart rendering server when components change

I wonder if there's a way to restart only the API server when API code changes and only restart the "front end" rendering server when components change.

Just an idea. It would maintain your session across UI updates.

Url params in API

Has no one needed to use url params yet? I might be missing something but they are not working for me

In routes/index.js

export podcasts from './podcasts';

hit /podcasts - action is found and route is matched
hit podcasts/123 - action is undefined and 404

I'm happy to hack away (on the regex i assume) but if anyone has already existing code, would be a good addition for this boilerplate.

Support for Redirect / transitionTo

The universal router errors when attempting to process a Redirect route / transitionTo. Any chance I can get some direction to resolve this? universalRouter is looking for a component it seems, but I'm not quite sure how to get it one when a Redirect route / transitionTo code is executed.

Thanks!

refreshing the page after a hot reload in dev breaks HMR

To repro:

  1. Run npm run dev
  2. Make a change to Home.js to trigger a hot reload.
  3. Refresh the page.

We just get this:

GET http://localhost:3001/dist/main-5a337b033a10cd47da21ad76b756b735.js,http://localhost:3001/dist/0.39b22b5b028e91381a8e.hot-update.js net::ERR_TOO_MANY_REDIRECTS

You must restart the server to get it working again.

importing images

Has anyone got importing images with webpack working? For me it seems to break server render.

Get image requiring working with url-loader

Ideally we want to use url-loader for image files to capture small files as base64 encoded strings to reduce the number of http requests to the server, but the image requiring solution that solved #39 does not work with url-loader.

Someone needs to investigate. The base64 string is probably in webpack-stats.json somewhere. It's just a matter of making requireServerImage() smart enough to use it instead.

What is the right way to have client side code run?

So, I have a component called <HomeHero/>, which is basically a big hero text with a background <video> tag.

I want to place some code that interacts with the <video> tag in the DOM (plays it, sets speed, e.t.c) once we render.

From what I understand there's some sort of gotcha about server vs. client, and not putting client side code upon first render.

Could you clarify the right place to place client side JS in components?

Issues running dev example

Server-side React render was discarded. Make sure that your initial render does not contain any client-side code.

Cloned -> npm install -> npm run dev -> visit localhost:3000

Any ideas? Thanks!

Edit: Works fine with production

Server actions that require GET/POST variables to be passed on?

I'm still getting my head wrapped around this structure, loving it so far.

However, I'm trying to understand how an action, such as getting info from server would look when it requires some sort of GET/POST variable passed along with it. For instance - if we want to get x amount of random numbers, and we want to pass on that x to the server in form of a GET variable.

Question about static files

I'm playing around with this skeleton, and when I put a folder named images in my static, and try to access it like so:
http://localhost:3000/images/logo.jpg

I get the following error:

TypeError: Cannot read property 'components' of null
   at /Users/danny/src/bpii-next/src/server.js:52:31
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/Router.js:53:7
   at done (/Users/danny/src/bpii-next/node_modules/react-router/lib/AsyncUtils.js:14:14)
   at next (/Users/danny/src/bpii-next/node_modules/react-router/lib/AsyncUtils.js:24:12)
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:120:9
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:100:13
   at done (/Users/danny/src/bpii-next/node_modules/react-router/lib/AsyncUtils.js:14:14)
   at next (/Users/danny/src/bpii-next/node_modules/react-router/lib/AsyncUtils.js:24:12)
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:120:9
   at matchRouteDeep (/Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:108:5)
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:116:5
   at next (/Users/danny/src/bpii-next/node_modules/react-router/lib/AsyncUtils.js:22:12)
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:120:9
   at matchRouteDeep (/Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:108:5)
   at /Users/danny/src/bpii-next/node_modules/react-router/lib/RoutingUtils.js:116:5
   at next (/Users/danny/src/bpii-next/node_modules/react-router/lib/AsyncUtils.js:22:12)

It looks as if it's trying to access a route with this URL. On lines 29-31 of server.js I see this:

if (app.get('env') === 'production') {
  app.use(require('serve-static')(path.join(__dirname, '..', 'static')));
}

Why do we serve static files only in a production environment (I guess it has to do with hot loading stuff via webpack?)?

In any case - uncommenting that didn't help much.

ReferenceError: ApiClient is not defined

Hi,

I did a fresh install of react-rudex-universal-hot-example on Node 0.12

# node -v
v0.12.5
# git clone [email protected]:erikras/react-redux-universal-hot-example.git
# cd react-redux-universal-hot-example
# npm install 
# npm run dev

When I open localhost:3000 in my browser I get the following exception:

ReferenceError: ApiClient is not defined
[1]     at new ApiClient (/home/rudolf/dev/react-redux-universal-hot-example/src/ApiClient.js:15:22)
[1]     at /home/rudolf/dev/react-redux-universal-hot-example/src/server.js:39:16
[1]     at Layer.handle [as handle_request] (/home/rudolf/dev/react-redux-universal-hot-example/node_modules/express/lib/router/layer.js:95:5)
[1]     at trim_prefix (/home/rudolf/dev/react-redux-universal-hot-example/node_modules/express/lib/router/index.js:312:13)
...

I don't know enough about babel and ES6 to completely debug it. But I did manage to make it work by changing src/server.js:

diff --git a/src/server.js b/src/server.js
index 94c4b3a..507a812 100755
--- a/src/server.js
+++ b/src/server.js
@@ -36,7 +36,8 @@ app.use('/api', (req, res) => {
 });

 app.use((req, res) => {
-  const client = new ApiClient(req);
+  let client = new ApiClient(req);
   const redux = createRedux(client);
   const location = new Location(req.path, req.query);
   if (process.env.NODE_ENV === 'development') {

It doesn't make sense how the scope of client should change anything and as far as I can tell this produces the same compiled code.

Let me know if I can provide any more information?

Running the example in heroku

First of all, this is a great repo, good example of what you can do with redux!

My question is related to running it in heroku. Has anyone been able to do so? From what I see in the logs, it always times out when superagent queries the API server:

https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/ApiClient.js#L40

I have tried many different things: using the hostname from os.hostname(), adding request.headers.host = 'heroku_hostname'; to the superagent call... but no luck so far.

Thanks,

Webpack not writing css modules to stats

I just can't seem to get webpack to write my css info to webpack-stats.json - my dev config appears to be in order:

var path = require('path');
var Webpack = require('webpack');
var writeStats = require('./utils/writeStats');
var host = 'localhost';
var port = parseInt(process.env.PORT) + 1 || 3001;

module.exports = {
  devtool: 'eval-source-map',
  context: path.resolve(__dirname, '..'),

  entry: [
    'webpack-dev-server/client?http://' + host + ':' + port,
    'webpack/hot/only-dev-server', 
    './js/main.js'
  ],

  resolve: {
    modulesDirectories: [
      'js',
      'node_modules'
    ],
    extensions: ['', '.json', '.js']
  },

  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: 'http://' + host + ':' + port + '/dist/'
  },

  module: {
    loaders: [
      { 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' },
      {test: /\.js$/, exclude: /(node_modules)/, loaders: ['react-hot', 'babel?stage=0&optional[]=runtime']},
      {test: /\.svg$/, loader: 'raw'},
      { test: /\.json$/, loader: 'json-loader' }
    ]
  },

  plugins: [
    new Webpack.HotModuleReplacementPlugin(),
    new Webpack.WatchIgnorePlugin([/\.json$/]),
    new Webpack.NoErrorsPlugin(),
    new Webpack.DefinePlugin({
      __CLIENT__: true, 
      __SERVER__: false,
      __DEVELOPMENT__: true
    }),

    function () {
      this.plugin('done', function(stats) {
        writeStats.call(this, stats, 'dev');
      });
    }
  ]

}

I can require scss files in my components with no problem - but I can't get the server-side bit working as the css block in webpack-stats isn't being populated. Any idea what stupid thing I'm forgetting?

{"script":["http://localhost:5001/dist/bundle.js","http://localhost:5001/dist/0.d881f22741bd91a83a47.hot-update.js"],"css":[]}

Consider updating to Redux 1.0 RC

Redux 1.0 RC is out with breaking changes. No further API changes are expected in 1.0 so it may be a good time to port the example to 1.0 RC (in a branch). We will release 1.0 when the docs are ready.

You can find the comprehensive list of the changes in 1.0 RC against 1.0 alpha in the Redux 1.0 RC release notes. If you haven't ported to alpha yet, you'll need to apply changes from 0.12 to alpha first.

Thank you!
Please make sure to report any issues so we can release a stable 1.0.

hot-reloading is very slow

hi, I found that I had to wait for serval second to see the result after modifying a component.Can I turn webpack-dev-server lazy mode to true?It seems not working as I expected.

move PORT from package.json to config.js

Heroku deploys dynamically set $PORT on their dyno, so in order to fully support it we'd have to move what's currently being defined (as 8080) in package.json betterScripts start to a port property of process.env.PORT || 8080 on the config object.

I then had to modify my server.js at the bottom to:

if (config.port) {
  app.listen(config.port, (err) => {
    if (err) {
      console.error(err);
    } else {
      console.info('==> ✅  Client is listening on port', config.port);
      console.info('----------\n==> 💻  Open http://localhost:%s in a browser to view the app.', config.port);
    }
  });
} else {
  console.error('==>     ERROR: No PORT environment variable has been specified');
}

Let me know if you'd like me to formally make a PR, I won't be able to get around to it until next week though.

Does not showcase as Universal / Isomorphic

Just a few issues noticed in the example when JS is disabled:

  • "Clicked Me # Times" button stuck at zero.
  • Login form never actually logs you in.
  • Github Fork links on homepage rely on JS and thus break

I know some of these are picky, however, when looking to pitch a boilerplate/methodology's use, being able to point to something without immediate flaw is rather imperative.

Question about reverse proxy with Apache/Nginx/etc

It's often said that a best practice for Node/Express is to reverse proxy it through Apache or some other server. This might potentially also speed up the serving of static files, allowing them to come directly from Apache rather than going through Express.

I'm not very knowledgeable about server setups, but I was thinking maybe you have some suggestions for this that might be relevant for the purpose of this example repo, in case you've done this before? When implementing a reverse proxy setup through Apache, is there anything in particular that the dev needs to do or keep in mind?

Using redux inside nested components?

Are you able to use @connect descriptor inside react-router children components? For example, try moving your InfoBar into the the Home view. I cannot get that scenario to work server-side. The dispatch doesn't make it through the router and if I go around the router the actions yield a 'document is not defined' error.

webpack-dev-server crashes quietly on sass @import in component

I have one line that makes the difference between webpack-dev-server crashing without any error message and running smoothly. The only thing that happens is that it does not report stats, however it does print: "Webpack development server listening on localhost:3001".

The line in question is

// file: /components/recentlyReported.scss

@import "../variablesAndMixins.scss";

which is imported like other scss files in the example, like so:

// file: /components/recentlyReported.js

if (__CLIENT__) {
  require('./RecentlyReported.scss');
}

It seems to work fine for files in /views, however the component in question is in /compoents, and is used as a sub component of my Dashboard view. When I uncomment the @import line, start webpack-dev-server, then uncomment the @import line, it works fine. It is only initially that it does not work.

Why does this matter? and how can I enable error messages for things like this?

React ref on header links

Theres a ref attribute on links in header, which seems unused.
Does this serve any purpose or was it forgotten?

webpackStats.css.map((css, i) => <link href={css} ref={i} media="screen, projection" rel="stylesheet" type="text/css"/>)

Dev server not building bundle correctly

When starting the dev server through npm run dev I am getting the following error, which is fixed by replacing chunkhash to hash in the webpack/dev.config.js file. For some reason this does not apply to the webpack/prod.config.js file (npm build + npm start works as expected), maybe because the dev server is using hot reloading?

[0] chunk main [entry]
[0] [name]-[chunkhash].js
[0] Cannot use [chunkhash] for chunk in '[name]-[chunkhash].js' (use [hash] instead)
[0] Error: Cannot use [chunkhash] for chunk in '[name]-[chunkhash].js' (use [hash] instead)
[0]     at Tapable.replacePathVariables (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/TemplatedPathPlugin.js:66:9)
[0]     at Tapable.applyPlugins [as applyPluginsWaterfall] (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/node_modules/tapable/lib/Tapable.js:37:47)
[0]     at Tapable.Compilation.getPath (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/Compilation.js:866:27)
[0]     at Tapable.createChunkAssets (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/Compilation.js:839:17)
[0]     at Tapable.<anonymous> (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/Compilation.js:549:8)
[0]     at Tapable.applyPluginsAsync (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/node_modules/tapable/lib/Tapable.js:60:69)
[0]     at Tapable.seal (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/Compilation.js:517:7)
[0]     at Tapable.<anonymous> (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/Compiler.js:395:15)
[0]     at /Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/node_modules/tapable/lib/Tapable.js:103:11
[0]     at Tapable.<anonymous> (/Users/orhan/desktop/react-redux-universal-hot-example/node_modules/webpack/lib/Compilation.js:438:10)

Cannot resolve 'file' or 'directory' ../../webpack-stats.json on first build

since webpack-stats.json is only created after a webpack build, how would the first build ever succeed:
on npm run build for the first time

ERROR in ./src/views/Widgets.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../../webpack-stats.json in /Users/sliu/workplace/react-redux-universal-hot-example/src/views
resolve file
  /Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json doesn't exist
  /Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json.json doesn't exist
  /Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json.js doesn't exist
resolve directory
  /Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json doesn't exist (directory default file)
  /Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json/package.json doesn't exist (directory description file)
[/Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json]
[/Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json.json]
[/Users/sliu/workplace/react-redux-universal-hot-example/webpack-stats.json.js]
 @ ./src/views/Widgets.js 38:14-49

Cannot read property 'components' of null in server.js

Thanks for this awesome example, @erikras
when I run npm run dev, my console keep reports the error
TypeError: Cannot read property 'components' of null
then I trace the error, found that it's that after
Router.run(routes, location, (error, initialState) => {
initialState is null
I add these console.log to help with debug

    console.log('req.url', req.url);
    console.log('routes', routes);
    console.log('location', location);
    console.log('initialState', initialState);

here is the report:

req.url /socket.io/?EIO=3&transport=polling&t=1435241343441-2522
[1] routes { type: 
[1]    { [Function]
[1]      displayName: 'Route',
[1]      createRouteFromReactElement: [Function: createRouteFromReactElement],
[1]      propTypes: 
[1]       { path: [Object],
[1]         ignoreScrollBehavior: [Object],
[1]         handler: [Object],
[1]         component: [Object],
[1]         components: [Object],
[1]         getComponents: [Object] } },
[1]   key: null,
[1]   ref: null,
[1]   _owner: null,
[1]   _context: {},
[1]   _store: 
[1]    { props: { component: [Function: App], children: [Object] },
[1]      originalProps: { component: [Function: App], children: [Object] } } }
[1] location { pathname: '/socket.io/',
[1]   query: { EIO: '3', transport: 'polling', t: '1435241343441-2522' },
[1]   state: null,
[1]   navigationType: 'POP' }
[1] initialState null

seems like a problem with webpack-dev-server?
although the functionality is not affected(reload from server still works)
but it's weird and annoying to see these on console?
anyone encountered that as well?

Req.body missing from api.js

Hi,

I just wanted to file an issue while I work out the solution (and submit a PR).
req.body doesn't get forwarded to the api server.

// src/api/api.js
export default function api() {
  return new Promise((resolve) => {
    app.use((req, res) => {

      // req.body === {}
      // the body doesn't get forwarded
      console.log("api.js: body", req.body);

     .....
  });
}
// src/server.js
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Proxy to API server
app.use('/api', (req, res) => {
  // req.body === {"foo":"bar"}
  // this works.
  console.log("server.js:", req.body);
  proxy.web(req, res);
});

I'm using postman to post to the dev server.

Turn SSR off?

First of all: Great job on this! I was looking into quite a bunch of starter examples, but this is the one I liked most.

As for my question: Is there an easy way to turn the server side rendering off? This would help debugging JavaScript errors with the Chrome Dev Tools instead of hunting the errors provided by the error sent down from the server.

Adding RouteHandler to App.js

I tried to replace {this.props.children] width in App.js , but i always get error "Cannot read property 'toUpperCase' of undefined at autoGenerateWrapperClass".

What could be wrong?

Syntax error on first run.

Trying to run out the example fails, with Babel complaining about a syntax error:

→ node --version
v0.12.0

→ npm --version
2.11.2

→ npm start

> [email protected] start dir/react-redux-universal-hot-example
> NODE_PATH="./src" NODE_ENV="production" PORT="8080" node ./babel.server

dir/react-redux-universal-hot-example/node_modules/babel-core/lib/babel/transformation/file/index.js:604
      throw err;
            ^
SyntaxError: dir/react-redux-universal-hot-example/src/redux/clientMiddleware.js: Unexpected token (4:30)
  2 |   return ({/* dispatch, getState */}) => {
  3 |     return (next) => (action) => {
> 4 |       const { promise, types, ...rest } = action;
    |                               ^
  5 |       if (!promise) {
  6 |         return next(action);
  7 |       }
    at Parser.pp.raise (dir/react-redux-universal-hot-example/node_modules/babel-core/lib/acorn/src/location.js:73:13)
    at Parser.pp.unexpected ...

I've ran npm install, and looking at node_modules/babel/package.json tells me that it really did install babel v5.4.7.

I feel like I'm missing something painfully obvious.

Making the API a little more RESTful

I guess this is a bit question and a bit suggestion?

It kind of makes sense to me to start off with an architecture that can lend itself to future de-coupling of the API & client/frontend - for example - to power a mobile client app.

In that case it would make much sense for the API to be more RESTful, meaning a structure with resources, id's and actions, rather than just glorified function names. Is there an easy way to implement that in the grand scheme of this example?

es6

No, issue but just a question.
I'm really interested in looking into this example but I'm not willing to go into ES7 yet. I want to stick to ES6. Any chance of getting this example in ES6 to?

Thanks

Server side errors are hard to debug

If there is a server side issue (like a bad property name) you'll often get an extremely simple error line like, "foo was not found in undefined".

I am wondering if there is either a way to insert better traces on the errors, or instead to run the project without Universal rendering so that the errors can be debugged in the browser.

Reducer not hotloading

case COUNTER_INCREMENT:
let {count} = state;
return {
count: count +1
};

changed it to

case COUNTER_INCREMENT:
let {count} = state;
return {
count: count +10
};

I'm getting the console log as:

[1] [piping] File src/reducers/counter.js has changed, reloading.
[0] Hash: 9bc9239a8a2f86a42fe5
[0] Version: webpack 1.10.3
[0] Time: 215ms
[0] Asset Size Chunks Chunk Names
[0] main-9bc9239a8a2f86a42fe5.js 3.02 MB 0 [emitted] main
[0] 0.4416de2fe6fb28b0fffb.hot-update.js 3.02 kB 0 [emitted] main
[0] 4416de2fe6fb28b0fffb.hot-update.json 36 bytes [emitted]

but it doesn't get reflected when I try to increment it using the button .What am I missing ?

Load when entering new route on client side?

Hi,

Thanks for great example code. I'm playing around with it and on my side I have moved the info loaded to only be displayed on the home route. So I've moved fetchData from App to Home.

When entering on another route (lets say sign-up) the server does not load the info which is what I want. Now the client has initialised and when going to the home route I want to check if info is loaded. If not, then start loading. How would you do that? Do a check in componentWillMount of Home?

Analytics integration

I just got this boilerplate running—it's awesome and well structured. 💯

However, I'm having trouble setting up analytics. I'd like a function to be called every time the route is changed—is there a best practice around where to do this?

Consolidate babel settings

  • .babelrc: stage: 0, loose: 'all'
  • dev.config.js and prod.config.js: stage: 0, optional: 'runtime', plugins: 'typecheck'
  • babel.server.js: stage: 0, plugins: [ 'typecheck' ]

At this moment, i'm unsure what the .babelrcsettings are used for.
Wouldn't it be useful to have all the settings in the same place and could we use them all for both client and server?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.