Coder Social home page Coder Social logo

iso's Introduction

Unmaintained/Deprecated

Hi everyone! Airbnb was using this module for their server-rendering and client bootstrapping but have since moved to and open sourced Hypernova which is a service that server renders your JS views but also includes some browser JS which does the server to client bootstrapping.

So this package/repo is now unmaintained and deprecated. I encourage you to check out Hypernova since it has very similar features.

--

Iso

Gitter

A helper class that allows you to hand off data from server to client.

Iso is a class. You instantiate it, add your markup, add some data to go with it, and render it. On the clientside Iso picks up what you sent down and gives it back to you so you can bring your content to life.

API

constructor(name = '', renderer = defaultRenderer)

The constructor takes in a name which is then used to build up a unique key for every added html, and a renderer which is used to determine how the data is prestented to the client. By default the renderer renders the markup into a div and the data into a script tag.

Iso#add(html: string, data: ?object): this

You provide the markup to add and some data you wish to pass down, and iso will save it internally.

Iso#render(): string

Once you're ready to collect your html you call render and a string will be returned to you.

Iso.bootstrap(onNode: function, selector: function)

onNode is a function that is called with the data, and a reference to the container node on the DOM. The selector is a function that you can configure to find the state and nodes on the DOM and return them.

The returned payload from selector should be an Object which contains the state and node pair for each unique key.

{
  "foobar": {
    state: { name: "foo" },
    node: DOMNode,
  },
}

Usage

Sample:

// server.js
const iso = new Iso()

request.get('/', function (req, res) {
  iso.add('<div>Hello, World!</div>', { someSampleData: 'Hello, World!' })
  res.render(iso.render())
})

// client.js
Iso.bootstrap(function (state, node) {
  // Now I do something with this data, perhaps run it through some library and then append
  // the result to node?
})

License

MIT

iso's People

Contributors

andrew-d avatar chadpaulson avatar fredericgrati avatar gitter-badger avatar goatslacker avatar iancmyers avatar michaelbenin avatar olslash 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

iso's Issues

Browserify not specified as a dependency

Following the iso-react-router-flux instructions (npm install; npm run build; npm start) fails:

> [email protected] build ~/Desktop/iso/examples/react-router-flux
> browserify -t [reactify --harmony] js/client.js > js/bundle.js

sh: browserify: command not found

Performance improvement

Hi Guys!
In this place I see no reason to encode all string:

core.encode(JSON.stringify(_state));

You can do something like this:

JSON.stringify(_state, (k, v) => typeof v  === "string" ? core.encode(v) : v);

In this case you will significantly reduce size of encoded JSON.

The same matches for decode.

Question

Where does Iso.bootstrap get the container that is passes via cb? I get error's telling me that this is not a valid DOM node.

Website breaking after updating to 5.0.0

After updating to 5.0.0, I get a bug every time there's some </script> text in my data.
Previously that data was inside a div and there were no problems, but now that the data goes inside a <script> element as JSON, if there's some text that contains </script> the browser considers it's the end of the tag, and it breaks the whole website.

Has anyone experienced the same?

React 0.14.0-beta1 warning when Alt.flush() contains nested objects

Running the react code below on the server side, which bootstraps Alt stores, displays a warning message Any use of a keyed object should be wrapped in React.addons.createFragment(object) before being passed as a child. when the the snapshot variable has nested JSON objects.

export default (req, res, next) => {
  Cookie.setRawCookie(req.headers.cookie || '');

  let location = new Location(req.path, req.query);
  Router.run(routes, location, (error, state, transition) => {
    if (error) return next(error);
    if (transition.isCancelled) return res.redirect(transition.redirectInfo.pathname);

    bootstrap(state, req).then(snapshot => {
      Alt.bootstrap(snapshot); // HERE!!!!!!!!!

      let markup = ReactDomServer.renderToString(<Router {...state}/>);
      let html = Iso.render(markup, Alt.flush());
      res.render('index', {html});
    }).catch(next);
  });
};

Server will output this:

<!DOCTYPE html><html lang="en"><head><title>React App</title><link href="http://localhost:4445/bundle.731b7891885111ef8124.css" media="all" rel="stylesheet" type="text/css"></head><body>
<div class="___iso-html___" data-key="0"><div data-reactid=".kdi2muzp4w" data-react-checksum="1597768506"><div data-reactid=".kdi2muzp4w.0"><span data-reactid=".kdi2muzp4w.0.0">Authenticated: </span><span data-reactid=".kdi2muzp4w.0.1">true</span></div><ul data-reactid=".kdi2muzp4w.1"><li data-reactid=".kdi2muzp4w.1.0"><a class="active" href="/" data-reactid=".kdi2muzp4w.1.0.0">Home</a></li><li data-reactid=".kdi2muzp4w.1.1"><a class="active" href="/stats" data-reactid=".kdi2muzp4w.1.1.0">Stats</a></li><li data-reactid=".kdi2muzp4w.1.2"><a class="" href="/login" data-reactid=".kdi2muzp4w.1.2.0">Login</a><span data-reactid=".kdi2muzp4w.1.2.1"> | </span><a class="" href="/logout" data-reactid=".kdi2muzp4w.1.2.2">Logout</a></li><li data-reactid=".kdi2muzp4w.1.3"><a class="" href="/projects" data-reactid=".kdi2muzp4w.1.3.0">Projects</a></li></ul><div data-reactid=".kdi2muzp4w.2"><div data-reactid=".kdi2muzp4w.2.0"><span data-reactid=".kdi2muzp4w.2.0.0">Environment: </span><span data-reactid=".kdi2muzp4w.2.0.1">development</span></div><div data-reactid=".kdi2muzp4w.2.1"><span data-reactid=".kdi2muzp4w.2.1.0">Platform: </span><span data-reactid=".kdi2muzp4w.2.1.1">darwin</span></div><div data-reactid=".kdi2muzp4w.2.2"><span data-reactid=".kdi2muzp4w.2.2.0">MemoryUsage: </span><span data-reactid=".kdi2muzp4w.2.2.1:$rss:0">98435072</span><span data-reactid=".kdi2muzp4w.2.2.1:$heapTotal:0">76464640</span><span data-reactid=".kdi2muzp4w.2.2.1:$heapUsed:0">50990096</span></div><div data-reactid=".kdi2muzp4w.2.3"><span data-reactid=".kdi2muzp4w.2.3.0">Uptime: </span><span data-reactid=".kdi2muzp4w.2.3.1">1086.548</span></div></div></div></div>
<div class="___iso-state___" data-key="0" data-meta="{}" data-state="&quot;{\&quot;SessionStore\&quot;:{},\&quot;ProjectStore\&quot;:{},\&quot;ProjectsStore\&quot;:{},\&quot;StatsStore\&quot;:{\&quot;env\&quot;:\&quot;development\&quot;,\&quot;platform\&quot;:\&quot;darwin\&quot;,\&quot;memoryUsage\&quot;:{\&quot;rss\&quot;:98435072,\&quot;heapTotal\&quot;:76464640,\&quot;heapUsed\&quot;:50990096},\&quot;uptime\&quot;:1086.548}}&quot;"></div>
<script src="http://localhost:4445/bundle.731b7891885111ef8124.js" type="text/javascript" async></script></body></html>

Snapshot variable example:

// warning IS visible
{"StatsStore":{"env":"development","platform":"darwin","memoryUsage":{"rss":98435072,"heapTotal":76464640,"heapUsed":50990096},"uptime":1086.548}}
// warning IS NOT visible
{"StatsStore":{"env":"development","platform":"darwin","memoryUsage": null,"uptime":1086.548}}

I'm using react 0.14.0-beta1 and react-dom 0.14.0-beta1. The source code is available here. Any suggestions?

Issue also posted here facebook/react#4524 but the owner says it's not react related.

move iso examples into its own repo

Hey, I was wondering if we should consider moving the iso examples into its own repository. Probably best for it to be in your name, similar to with the alt-tutorial.

This is mainly because I wanted to add a few iso examples and thought it would be a good place to discuss issues and conventions, rather than with iso itself.

Looking to create:

  • an isomorphic example of the alt-tutorial.
  • an image touch-swipe example
  • maybe a simple isomorphic site with a few routes with express similar to the fluxxor example on their site.

Thanks

layout consequences of wrapping the application in a div

Might be worth documenting the HTML that iso generates because it looks like I'll need to style it.

For example, I have a flexbox-based layout that expects html and body to be 100% high. The app is then grown to fill that space. But since iso wraps the html – div.___iso-html___ – the layout breaks…unless that iso wrapper is styled to be 100% high too.

Or, iso could allow an extra class to be set so that things don't break if that classname is ever altered in this module.

What do you think?

react-router-flux server patch

needed to supply an empty object to get the react-router-flux example to work

diff --git a/examples/react-router-flux/server.js b/examples/react-router-flux/server.js
index b4e37f9..992510d 100644
--- a/examples/react-router-flux/server.js
+++ b/examples/react-router-flux/server.js
@@ -55,7 +55,7 @@ app.get('/time', function (req, res, next) {
 app.use(function (req, res) {
   alt.bootstrap(JSON.stringify(res.locals.data || {}))

-  var iso = new Iso()
+  var iso = new Iso({})

   Router.run(routes, req.url, function (Handler) {
     var content = React.renderToString(React.createElement(Handler))

Maybe a better solution would be to get the Iso constructor to create the empty object if not provided.

Question

I don't get why you load Iso that way :
var Iso = require('../../')

and not :
var Iso = require('iso');
const iso = new Iso();

Have static method on React Components for pre-fetching?

Hello @goatslacker,

Instead of making a request for fetching data before server-side render into the app.use like in your example:

getNameFromServer(function (name) {
  res.locals.data = {
    HelloStore: { name: name }
  }
  next()
})

(That means double-work, one method in component / stores for fetching data when app is running client-side, and one on the server-side. Or am I wrong and I didn't understand something?)

Would it possible to have static method on components that would be resolved before rendering, like https://github.com/ericclemmons/react-resolver/ is doing?

Anyway, thank's for Alt & iso :)

Leave markup without state/meta alone

const iso = new Iso();

iso.add('<!DOCTYPE html>');

this.body = iso.render();

produces:

<div class="___iso-html___" data-key="0"><!DOCTYPE html></div>
<div class="___iso-state___" data-key="0" data-meta="{}" data-state="{}"></div>

This is because of:

iso/src/iso.js

Lines 20 to 30 in feac661

render() {
let markup = this.html.reduce((markup, html, i) => {
return markup + `<div class="___iso-html___" data-key="${i}">${html}</div>`
}, '')
let data = this.data.reduce((nodes, data, i) => {
let { state, meta } = data
return nodes + `<div class="___iso-state___" data-key="${i}" data-meta="${meta}" data-state="${state}"></div>`
}, '')
return (

My recommendation is that <!DOCTYPE html> is produced without wrapping. (Similarly, whitespace can be trimmed from the output).

There shouldn't be a need to worry about changing key indexes or anything...

Thoughts?

Populating stores automatically?

I'm still learning React and Flux (with alt and iso), but I'm wondering if there's a way to approach the initial server-side render without having to populate the stores manually.

Looking at your react-router-flux example, I see you (pretending to) fetch data from a backend API and populate a store with it. Is there an example that you know of that does this automatically by using react-router load the route and any nested routes, call the initial actions, and populate the stores like one would client-side? I guess you'd have to wait for all store data-fetching promises to resolve first, but I'm unsure of how you'd enumerate them, wait, and only then serialize the stores for the initial markup response.

Thanks so much!

datetime-flux example action methods are not called

It seems in the datetime-flux example when you call an action like TimeActions.setAsync(Date.now()) it pretty much jumps straight into the store method ignoring the action. So rather than jumping in to the setAsync(n) function in TimeActions it goes directly to onSetAsync(n) in TimeStore.

Is this expected behaviour? because I was trying to make a similar example based on this one using images in a slider, and it seems like making an async call to get images in the action, similar to the setAsync(n) function basically skips the action part.

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.