Skip to content
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

Compatibility with webpack for server-side-rendering #29

Closed
benoneal opened this issue Jan 9, 2015 · 20 comments
Closed

Compatibility with webpack for server-side-rendering #29

benoneal opened this issue Jan 9, 2015 · 20 comments

Comments

@benoneal
Copy link

benoneal commented Jan 9, 2015

I'm creating an isomorphic React app with Express4 and Webpack, and I'm trying to include css files using the Webpack method of requiring them in my components (as per this loader). Unfortunately, on the server-side, node-jsx is attempting to transform the components, and throws an error if they include css:

Error: Error transforming [component/style.css] to JSX: Error: Parse Error: Line 1: Unexpected token .

This is a real pain in the butt.

@benoneal
Copy link
Author

Just confirmed that there is also a conflict with other modules when attempting to render on the server. It errors with react-fa (font-awesome component module) with the following error:

Error transforming [app_path]/node_modules/react-fa/node_modules/font-awesome/css/font-awesome.css to JSX: Error: Parse Error: Line 7: Unexpected token ILLEGAL

@0nn0
Copy link

0nn0 commented Jan 15, 2015

Running into the same problem.

@gpbl
Copy link

gpbl commented Jan 15, 2015

You can't just require a css in node, eventually you need to build the node part with webpack (or alternatives).

An easier solution is to require those components only client side, ie adding if BROWSER require(...), and use them after the component has been mounted.

I would just use components working on both the environments: a component for font awesome sounds useless imho :)

@rmarscher
Copy link

I've had some luck using if (process.pid) { } to determine if the code is executing on the server or client. Then only require files processed by the webpack loaders if executing on the client. Similarly, you can decide whether to use render() or renderToString().

A webpack loader to remove requiring node-jsx could be useful. Something like:

module.exports = function(source) {
    this.cacheable();
    return source.replace(/require\(\s*'node-jsx'\s*\).install\(.*?\);\n/, "");
};

@benoneal
Copy link
Author

Requiring css only on the client side defeats the purpose of an isomorphic app. I need to be able to process the css during server-render, so that the page can be delivered with css. I'd like to be able to take advantage of webpack's module bundling so that css is bundled with React components that require them, but as long as node-jsx errors on css files, all my styles have to be managed with a separate (gulp) pipeline, completely defeating the modular approach.

@gpbl
Copy link

gpbl commented Feb 19, 2015

@benoneal node itself (not node-jsx) does not accept a CSS. Requiring CSS on the client is intended as "skip requiring css on the server, but deliver them on the client with webpack" .
You can indeed require a single CSS in your JSX files and deliver a bundled .css as usual: you don't need gulp at all. Use the webpack's ExtractTextPlugin.

// a jsx file
render() {
  if (BROWSER) require('component.css')
  return <div>Hi</div>
}

// your webpack config
module: {
loaders: [
  // will intercept all .css requires
  { test: /\.css$/, loader: ExtractTextPlugin.extract("css-loader") }
]
},
  plugins: [
    // create a bundled.css to use in your html source
    new ExtractTextPlugin("bundled.css"),
}

@todsul
Copy link

todsul commented Feb 27, 2015

@benoneal I'm working on the same problem with an isomorphic app, so would be interested in your final solution. The problem with having some styles in a standard .css file and other styles required by the client app is the FOUC before the client styles load. So really it seems all styles need to be in a .css.

This is a similar issue with state. With SSR, I'm finding that not only do I need identical states on client and server (to avoid a mismatch and another FOUC), but the only way to sync them is by essentially duplicating state in the server response (via a script tag, dataset or whatever). That's easy enough with React, but with Flux it's getting a little messy. I've seen that Yahoo and others have worked it out, but we're having fun experimenting with our own somewhat simpler solutions.

@voronianski
Copy link

@benoneal I have the same problem (the only difference that I'm using babel instead of node-jsx). Any workarounds or step by step guide?

@maletor
Copy link

maletor commented Mar 27, 2015

I'm interested in the semantic solution here too. I've seen projects override require to ignore png and CSS extensions only to be filled in later by client side code.

@voronianski
Copy link

@maletor yeah require.extensions['.css'] is the quickest.

@maletor
Copy link

maletor commented Mar 27, 2015

It's not as bad of a problem as I originally thought, since this can be isolated to development and factored into a production build.

It's still an issue, but I'm not sure it will be easy to fix at all.

@maletor
Copy link

maletor commented Mar 27, 2015

require.extensions is deprecated too.

@maletor
Copy link

maletor commented Mar 31, 2015

So I missed this in the huge documentation that is webpack but here's our answer!

http://stackoverflow.com/a/29358828/381285

@frankleng
Copy link

@maletor not sure if that would solve the problem, since that example isn't an isomorphic build. unless I'm missing something...

@ftorre104
Copy link

To expand on maletor's answer, the idea is to use webpack to create 2 bundles -- one for the client and one for your server.

You still have your single source code -- one code-base. Currently you may be creating a bundle of that code, bundle.js, to send to the client; and you run your node server directly on that code-base.

To use webpack on the server, the idea is to create 2 separate bundle files from your single code base. It requires 2 separate webpack configurations, and 2 separate builds. Your original source code will no longer run your server directly.

One webpack target will be for the client. Something like (psuedocode):
target: web, entry: app.js, extensions: [scss, jsx, coffee, etc], output: client.bundle.js

The other webpack config target will be for your server:
target: node, entry: server.js, extensions: [jsx, coffee, etc], plugin: [ignore css], output: server.bundle.js

The above is just meant to illustrate the distinction.

The client side will load client.bundle.js in the browser.
Your server, instead of running on your normal server.js, will now run on your built server.bundle.js.

This allows you to use the power of webpack -- feature flags, enhanced requires, loaders, chunks, etc -- on the server.

@maletor
Copy link

maletor commented May 11, 2015

For what it's worth, this issue has caused me to shift gears and look at
the solution Ember.js has found. With Ember 2.0 bringing all the good parts
of React on board, I think it's a much better solution overall. There is
way too too much time spent trying to configure React and WebPack.

On Mon, May 11, 2015 at 11:06 AM Fede Torre Mtz notifications@github.com
wrote:

To expand on maletor's answer, the idea is to use webpack to create 2
bundles -- one for the client and one for your server.

You still have your single source code -- one code-base. Currently you may
be creating a bundle of that code, bundle.js, to send to the client; and
you run your node server directly on that code-base.

To use webpack on the server, the idea is to create 2 separate bundle
files from your single code base. It requires 2 separate webpack
configurations, and 2 separate builds. Your original source code will no
longer run your server directly.

One webpack target will be for the client. Something like (psuedocode):
target: web, entry: app.js, extensions: [scss, jsx, coffee, etc], output:
client.bundle.js

The other webpack config target will be for your server:
target: node, entry: server.js, extensions: [jsx, coffee, etc], plugin:
[ignore css], output: server.bundle.js

The above is just meant to illustrate the distinction.

The client side will load client.bundle.js in the browser.
Your server, instead of running on your normal server.js, will now run on
your built server.bundle.js.

This allows you to use the power of webpack -- feature flags, enhanced
requires, loaders, chunks, etc -- on the server.


Reply to this email directly or view it on GitHub
#29 (comment).

@veeracs
Copy link

veeracs commented Sep 18, 2015

I'm going through the same pain!

In Home.jsx I have import '../../client/styles/home.scss';

babel-node index.js

/Users/cveera/Sites/hapi-fluxible-webpack/node_modules/node-jsx/index.js:27
throw new Error('Error transforming ' + filename + ' to JS: ' + e.toStri
^
Error: Error transforming /Users/cveera/Sites/hapi-fluxible-webpack/lib/app/views/Home.jsx to JS: Error: Parse Error: Line 3: Illegal import declaration
at Object.require.extensions.(anonymous function) as .jsx
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object. (/Users/cveera/Sites/hapi-fluxible-webpack/lib/app/views/Routes.jsx:11:15)
at Module._compile (module.js:456:26)
at Object.require.extensions.(anonymous function) as .jsx
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)

@petehunt
Copy link
Owner

You should use https://github.com/petehunt/webpack-require which does exactly what you want, not node-jsx.

@hzhu
Copy link

hzhu commented May 31, 2016

Can anyone link to a repo using webpack-require? Running into some issues, would like to see it in action, but can't locate a project using it.

@stevus
Copy link

stevus commented Feb 18, 2017

@petehunt you closed this issue, however webpack-require is only in beta. Would not consider this issue closed as a result until it is not beta software.

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