Skip to content

prerender option with CommonJS-style modules #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alex35mil opened this issue Nov 28, 2014 · 4 comments
Closed

prerender option with CommonJS-style modules #124

alex35mil opened this issue Nov 28, 2014 · 4 comments

Comments

@alex35mil
Copy link

Hi! I have trouble with prerender option.

In short

I'm using CommonJS-style modules with Browserify. In browser everything works fine, but server renderer throws an error: require / module is not defined.

Verbose

I'm using Gulp and Browserify to pack my js assets.
Here is the js-assets part of my Rails project:

| /app
|--- /assets
|------ /javascripts
|--------- application.js           # Only link to //= bundle
|--------- app.js                   # Browserify in-file, contains all `require`s to pack the `bundle`
|--------- bundle.js                # Browserify out-file
|--------- components.js            # Link to components for React gem (only for server renderer)
|--------- /components
|------------ my_component.js       # React component
|------------ /mixins
|--------------- my_shared_mixin.js

When I use prerender on the server, I got an errors: require / module is not defined.
I'm not very familiar with server-side js rendering, but as far as I know require & module should be defined in node env.

Here is my Thor generator to create this setup
JS sources listed below.

/app/assets/javascripts/application.js

Links only bundle.js (generated by Browserify).

//= require bundle
/app/assets/javascripts/components.js

Used only by server renderer.

//= require_tree ./components
/app/assets/javascripts/components/my_component.js
var HelloWorld = React.createClass({
  displayName: 'HelloWorld',
  getInitialState: function() {
    return {val: 'Hello'};
  },
  render: function() {
    return React.createElement('div', {}, this.state.val + ' World');
  }
});

window.HelloWorld = HelloWorld;

// Without this `if` I'll get an error from server renderer
if (typeof module !== 'undefined' && module.exports) {
  module.exports = React.createFactory(HelloWorld);
}

I solved the undefined module problem using if, but if I'll need to require shared mixin or smth else — I'll get an error from the renderer anyway.

@simonsmith
Copy link

ExecJS is used for the server-side rendering. From the repo:

Why can't I use CommonJS require() inside ExecJS?

ExecJS provides a lowest common denominator interface to any JavaScript runtime. Use ExecJS when it doesn't matter which JavaScript interpreter your code runs in. If you want to access the Node API, you should check another library like commonjs.rb designed to provide a consistent interface.

I'm in a similar position and have found some joy with Webpack and building it with an option to expose all the components to the global object. It's still less than ideal when it comes to sharing dependencies though.

@bowd
Copy link
Contributor

bowd commented Dec 10, 2014

@alexfedoseev check out my answer in #120 it might help you out, I have a similar CommonJS build but I'm using component.js and I to my server side rendering using require.

@alex35mil
Copy link
Author

@bogdan-dumitru thanks! gonna check out this weekend

@alex35mil
Copy link
Author

After months of wandering I've came to this approach: https://github.com/alexfedoseev/generator-flux-on-rails
I'm quite happy with it, so closing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants