Giter VIP home page Giter VIP logo

isomorphic-react-example's Introduction

What is Isomorphic/Universal JavaScript ?

There is a push to change the word Isomorphic to Universal. Whatever floats your boat!

See full post on ReactJS News

Shared JavaScript that runs on both the client & server.

What's the point?

JavaScript driven MVCs (angular, ember, backbone, etc.) render on DOM load, this can be really slowwwww & can make for a bad user experience.

Another major problem is that they aren't indexable by search engines (without paying $$ for a third party service like https://prerender.io/). If your app is serving any kind of data that people might be searching for, this is a bad thing.

When you render JavaScript on the server side you can solve these problems and be super cool while doing so!

Isomorphic Javascript Benefits:

  • Better overall user experience
  • Search engine indexable
  • Easier code maintenance
  • Free progressive enhancements

I've built a live example of isomorphic JS for you to check out here: https://github.com/DavidWells/isomorphic-react-example

The demo uses the griddle react component to show how you can have apps with large data sets indexed by search engines and thus easier to find by potential users in search engines.

Tutorial & Video!

https://www.youtube.com/watch?v=8wfY4TGtMUo

In /server.js install the jsx transpiler:

// Make sure to include the JSX transpiler
require("node-jsx").install();

Then change components to Node friendly syntax where you module.exports the component if it's in a seperate file

Also make sure to React.createFactory your component for it to be rendered server side

/** @jsx React.DOM */

var React = require('react/addons');

/* create factory with griddle component */
var Griddle = React.createFactory(require('griddle-react'));

var fakeData = require('../data/fakeData.js').fakeData;
var columnMeta = require('../data/columnMeta.js').columnMeta;
var resultsPerPage = 100;

var ReactApp = React.createClass({

      componentDidMount: function () {
        console.log(fakeData);

      },

      render: function () {

        return (
          <div id="table-area">

             <Griddle results={fakeData} columnMetadata={columnMeta} resultsPerPage={resultsPerPage} tableClassName="table"/>

          </div>
        )
      }

  });

/* Module.exports instead of normal dom mounting */
module.exports.ReactApp = ReactApp;
/* Normal mounting happens inside of /main.js and is bundled with browserify */

Now the magic happens with routes using React.renderToString inside /app/routes/coreRoutes.js:

var React = require('react/addons');
var ReactApp = React.createFactory(require('../components/ReactApp').ReactApp);

module.exports = function(app) {

	app.get('/', function(req, res){
    	// React.renderToString takes your component
        // and generates the markup
		var reactHtml = React.renderToString(ReactApp({}));
        // Output html rendered by react
		// console.log(myAppHtml);
	    res.render('index.ejs', {reactOutput: reactHtml});
	});

};

The reactOutput variable is then passed into the template:

<!doctype html>
<html>
  <head>
    <title>React Isomorphic Server Side Rendering Example</title>
    <link href='/styles.css' rel="stylesheet">
  </head>
  <body>
	<h1 id="main-title">React Isomorphic Server Side Rendering Example</h1>
    <!-- reactOutput is the server compiled React Dom Nodes -->
    <!-- comment out reactOutput to see empty non indexable source in browser -->
    <div id="react-main-mount">
      <%- reactOutput %>
    </div>

	<!-- comment out main.js to ONLY see server side rendering -->
	<script src="/main.js"></script>


  </body>
</html>

Notes:

Because the files are .js and not .jsx, the React.createFactory has to be used when including components. See why here: https://gist.github.com/sebmarkbage/ae327f2eda03bf165261

Demo Install Instructions

If you would like to download the code and try it for yourself:

  1. Clone the repo: [email protected]:DavidWells/isomorphic-react-example.git
  2. Install packages: npm install
  3. Launch: node server.js
  4. Visit in your browser at: http://localhost:4444
  5. To see serverside rendering, comment out main.js from the /views/index.ejs file. This will show what is rendered purely from the server side.

Build changes with gulp

Other Isomorphic Tutorials & Resources

Server-Client with React
Server Side rendering

New to React? Check out these tutorials

isomorphic-react-example's People

Contributors

andismith avatar callumlocke avatar davidwells avatar g-lex avatar kenfehling avatar typpo avatar zanesterling 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

isomorphic-react-example's Issues

Cannot read property "toString" from undefined

Hi David,

I have an issue with the renderOnServer, i the CommentList function
var commentNodes = this.props.data.map(function (comment) {
return (
React.createElement(Comment, {author: 'comment.author'}, comment.text)
);
});
comment.text raise the exception : Cannot read property "toString" from undefined

Any idea ?

Thx
Bruno

won't install

Seems like since esprima-six was unpublished from NPM, this example no longer installs.

npm ERR! Darwin 14.0.0
npm ERR! argv "/Users/matt/.nvm/versions/node/v5.0.0/bin/node" "/Users/matt/.nvm/versions/node/v5.0.0/bin/npm" "i"
npm ERR! node v5.0.0
npm ERR! npm  v2.14.12
npm ERR! code E404

npm ERR! 404 Registry returned 404 for GET on https://registry.npmjs.org/esprima-six
npm ERR! 404 
npm ERR! 404 'esprima-six' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404 It was specified as a dependency of 'astw'
npm ERR! 404 
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! Please include the following file with any support request:
npm ERR!     /projects/oss/isomorphic-react-example/npm-debug.log

react render error:ReactDOM.render(): Invalid component element

I render React Component on server side:

1.components.js:

var React = require('react/addons');
var MonitorApp =  React.createClass({...});
module.exports = MonitorApp;

2.appFile/app.js

 var React = require('react/addons');
var ReactApp = require('../components');
var ReactDOM = require('react-dom');
var mountNode = document.getElementById("react-main-mount");

ReactDOM.render(new ReactApp({}), mountNode);

3.gruntFile.js

browserify: {
        dist: {
            files: {
                '<%= srcBase %>/assets/app.js': ['app/appFile/*.js']
            },
            options: {
                transform: ['reactify']
            }
        }
    }

4.html

<div id="react-main-mount">
    {{{reactOutput}}}
</div>
<script src="/assets/app.js"></script>

there is a error on browser console like this:

Uncaught Error: Invariant Violation: ReactDOM.render(): Invalid component element. This may be caused by unintentionally loading two independent copies of React.

Broken package.json

Hi.

The current package.json will fail to produce a working app after running 'npm install', failing with the following error:

var ReactButton =  React.createFactory(require('./ReactButton').ReactButton);

TypeError: Object function ReactJSShim() {
  error();
} has no method 'createFactory'

I was able to get the app to run by removing the duplicate (but different version) references to react in dependencies and devDependencies and reinstalling with npm install --save, which brought them up to v.0.12.2.

I'm still only getting server side rendering though, as the table just sits there, without any sorting/filtering. There is an 'Invariant Violation' error in the console that says it's possibly due to loading react twice. Thanks!

About re-render

Hi,I'm new to this.My question is that the server already render the react component why it should still write code in client side html to ReactDOM.render again?

'esprima-six' is not in the npm registry

When I clone to the local and npm install, it report the error information below:
npm ERR! 404 Registry returned 404 for GET on https://registry.npmjs.org/esprima-six npm ERR! 404 npm ERR! 404 'esprima-six' is not in the npm registry.

Time for a rewrite?

@DavidWells this repo, though it is getting a little outdated, has been a great starting place for me to understand how isomorphic React can work. I would like to contribute to rewriting this library using Webpack instead of browserify, and handlebars instead of ejs templating.

There have been a lot of isomorphic react libraries popping up since you've written this though they all seem to attempt to reduce boilerplate and give users a minimalist, opinionated starting point rather than provide an example for how this should be implemented. Anyone seen a more up to date example of this?

I just responded to a stack overflow question about this: https://stackoverflow.com/questions/45668191/injecting-react-component-into-handlebars-in-client-side/45740354#45740354
If anyone has anything to add to it, that may be a better place to suss out how this should be done best.

Install fail

After npm install, the error i got:
[[email protected] › querystring@https://github.com/substack/querystring/archive/0.2.0-ie8.tar.gz] install querystring from remote https://github.com/substack/querystring/archive/0.2.0-ie8.tar.gz, may be very slow, please keep patience [[email protected][email protected][email protected] › querystring@https://github.com/substack/querystring/archive/0.2.0-ie8.tar.gz] install querystring from remote https://github.com/substack/querystring/archive/0.2.0-ie8.tar.gz, may be very slow, please keep patience × Install fail! Error: [[email protected][email protected][email protected][email protected][email protected]] Can't find package esprima-six's version: 0.0.3 Error: [[email protected][email protected][email protected][email protected][email protected]] Can't find package esprima-six's version: 0.0.3 at resolve (C:\Users\WenWest\AppData\Roaming\npm\node_modules\cnpm\node_modules\npminstall\lib\download\npm.js:97:11) at resolve.next (<anonymous>) at onFulfilled (C:\Users\WenWest\AppData\Roaming\npm\node_modules\cnpm\node_modules\co\index.js:65:19) at <anonymous> at process._tickCallback (internal/process/next_tick.js:188:7) npminstall version: 3.0.1 npminstall args: F:\NodeJS\node.exe C:\Users\WenWest\AppData\Roaming\npm\node_modules\cnpm\node_modules\npminstall\bin\install.js --china --userconfig=C:\Users\WenWest\.cnpmrc --disturl=https://npm.taobao.org/mirrors/node --registry=http://registry.npm.taobao.org
I get confused about that, what's the reason?

fake data is included with browserify bundle

Over the last couple days I have been working on isomorphic react, and then I stumbled on your example. One issue I see is that the fake data file is bundled with the browserify build and shipped with the js the browser loads. Most apps will retrieve the data at runtime from a store or api and wont be able to do this.

It would be nice if isomorphic-react-example could show loading data from some public api and rendering that serverside and then having the client mount that component.

So far the only way I have found to deal with this is to JSON.stringify the data on the server included in the html, and then on the client JSON.parse the data and pass it to the ReactApp component.

npm install fails

Hi , after clonung and running npm install I get :

daslicht:isomorphic-react-example daslicht$ npm install
npm WARN package.json node-authentication@ No repository field.
npm WARN deprecated [email protected]: react-tools is deprecated. For more information, visit https://fb.me/react-tools-deprecated
npm WARN deprecated [email protected]: react-tools is deprecated. For more information, visit https://fb.me/react-tools-deprecated
npm WARN deprecated [email protected]: Use the "buffer" module (https://www.npmjs.com/package/buffer) instead
npm ERR! TypeError: Cannot read property '0.0.3' of undefined
npm ERR!     at /Users/daslicht/.nvm/v0.10.40/lib/node_modules/npm/lib/cache/add-named.js:123:27
npm ERR!     at RegClient.get_ (/Users/daslicht/.nvm/v0.10.40/lib/node_modules/npm/node_modules/npm-registry-client/lib/get.js:130:14)
npm ERR!     at RegClient.<anonymous> (/Users/daslicht/.nvm/v0.10.40/lib/node_modules/npm/node_modules/npm-registry-client/lib/get.js:49:12)
npm ERR!     at evalmachine.<anonymous>:272:14
npm ERR!     at /Users/daslicht/.nvm/v0.10.40/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:102:5
npm ERR!     at Object.oncomplete (evalmachine.<anonymous>:108:15)
npm ERR! If you need help, you may report this *entire* log,
npm ERR! including the npm and node versions, at:
npm ERR!     <http://github.com/npm/npm/issues>

npm ERR! System Darwin 15.0.0
npm ERR! command "/Users/daslicht/.nvm/v0.10.40/bin/node" "/Users/daslicht/.nvm/v0.10.40/bin/npm" "install"
npm ERR! cwd /Users/daslicht/DEV/node/react/isomorphic-react-example
npm ERR! node -v v0.10.40
npm ERR! npm -v 1.4.28
npm ERR! type non_object_property_load


Why not do away with .ejs templates altogether

I used to think that having templates (like .ejs) was needed or useful with React.
But now I believe you can just do away with it entirely, and use React's compose-ability.

So why no create a parent component that looks something like so:

const React = require('react');

module.exports = React.createClass({

   render: function(){

      return (

          <html lang="en">
          <head>
              <meta charset="UTF-8">
                  <title>Title</title>
          </head>
          <body>

              {this.props.body}

          </body>
          </html>

      )
   } 
});

perhaps React does not allow <html> <body> <head> tags?

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.