6

I'm building an isomorphic application. It is completely built with react -- namely, the html base is also in react.

I have my root html as an app component.

It looks something like this:

...
var AppTemplate = React.createClass({
    displayName: 'AppTemplate',
    render: function() {
        return (
            <html>
                    <head lang="en">
                        <title>hello</title>
                        <link rel="stylesheet" href='/css/style.css' />
                    </head>
                    <body>
                        <RouteHandler {...this.props}/>
                        <script type='text/javascript' src='/js/bundle.js' />
                    </body>
                </html>
        );
    }
});
...
module.exports = AppTemplate;

When I build the project with webpack, I need to replace js/bundle.js to include the hash.

Webpack delivers the stats.json after it is finished. But I need to have the hash available during build time.

I was thinking of using the feature flags to do something like:

...
var AppTemplate = React.createClass({
    displayName: 'AppTemplate',
    render: function() {
        return (
            <html>
                    <head lang="en">
                        <title>hello</title>
                        <link rel="stylesheet" href='/css/style.css' />
                    </head>
                    <body>
                        <RouteHandler {...this.props}/>
                        <script type='text/javascript' src='/js/bundle.{__HASH__}.js' />
                    </body>
                </html>
        );
    }
});
...
module.exports = AppTemplate;

Which would ideally inject the right hash reference into the built js.

It's a bit tricky since it is self referencing. Is there a better way to do it? Modifying the built code after webpack has finished seems counterproductive. I've also thought about having the client simply request bundle.js, but have my node server serve the hashed file.

What would be a proper solution to this caching?

3 Answers 3

7

The ExtendedAPIPlugin adds a __webpack_hash__ variable to your bundle, which might be what you're looking for.

Sign up to request clarification or add additional context in comments.

Comments

4

Instead of trying to render it in the app, I found the best solution is to pass the webpack assets into the app. This can be either directly through props or through your flux.

That way your code is rendered with a variable. The value of your variable is irrelevant for the build process.

...
var AppTemplate = React.createClass({
    displayName: 'AppTemplate',
    render: function() {
        return (
            <html>
                    <head lang="en">
                        <title>hello</title>
                        <link rel="stylesheet" href='/css/style.css' />
                    </head>
                    <body>
                        <RouteHandler {...this.props}/>
                        <script type='text/javascript' src={this.props.jsFile} />
                    </body>
                </html>
        );
    }
});
...
module.exports = AppTemplate;

Something like that.

Comments

0

You shouldn't be rendering your full HTML on the client, ever. Your head and everything outside your app div in body should just be sent from the server. That way your problem is solved right away, as your client-side Javascript doesn't need to know what file it lives in, and on the server you can just wait for the stats to be ready.

2 Comments

It is an isomorphic app. The this react app is render on the server, with React.renderToString(). This renders a string (or just the view part of the component). It includes the head and everything outside the app and is sent down from the server. On the client, you have to 'rehydrate' the document with the exact same react app. On the client you do React.render() which will render the view + the functionality/event handlers.
Sure, but you should not try to rehydrate the full HTML on the client (including all the script tags), that's just unneeded. Nothing outside your body will generally change at runtime. Have a look here for a good example: github.com/yahoo/flux-examples/tree/master/fluxible-router Basically: Create an app div inside your body, render your actual React app to a string and print it inside the app div. Then render the outer HTML and put the rendered app div inside it. Then rehydrate your app into the app div. I've built a pretty big Fluxible app that way, including [hash], works great!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.