KyleAMathews / react-spinkit

A collection of loading indicators animated with CSS for React
http://kyleamathews.github.io/react-spinkit/
MIT License
1.49k stars 73 forks source link

requiring in node raises error #20

Closed jangxyz closed 7 years ago

jangxyz commented 9 years ago

I'm currently doing a server-side rendering as an optimization, and react-spinkit chokes when is required from node directly:

SyntaxError: .../node_modules/react-spinkit/css/fade-in.css:1
(function (exports, require, module, __filename, __dirname) { @-webkit-keyfram
                                                              ^
Unexpected token ILLEGAL

Seems like require("react-spinkit") loads dist/index.js, which requires css files. This works correctly on client because browserify transforms with cssify, but on node it just tries to read the CSS file and expects a JavaScript syntax.

What am I suppose to do? Is there a way to build the dist file with the css files already transformed in it?

KyleAMathews commented 9 years ago

This is no easy solution to this afaik. The only solution I know is https://github.com/petehunt/webpack-require

You can also in node look for browser globals before requireing like if (window) { require('react-spinkit') }

jangxyz commented 9 years ago

Digging it deeper, I did manage to render it in server.

I attempted to "build" my own version of react-spinkit with browserify, and require that as a shim for node.

browserify -t coffee-reactify --no-browser-field --bare --standalone spinkit node_modules/react-spinkit/src/index.cjsx -o libs/react-spinkit.bundle.js

Then I require the bundle from app's code. Since now the ./libs/react-spinkit.bundle.js is actually a module stuffed with all of its dependencies, requiring css is nothing more than just calling an inner function. I could require the new bundle file in node.

I check the browser and load different type of 'react-spinkit' module.

var Spinner;
if (ui.isBrowser()) {
    Spinner = require('react-spinkit');
} else {
    Spinner = require('../libs/react-spinkit.bundle.js');
}

This is what happens:

  1. When rendering SpinKit in node, it calls the require function with css filenames. Since it's not a node require, but just some inner function, node would not choke.
  2. <Spinner /> would be correctly rendered as HTML.
    Upto now, there is CSS string applied. Node hasn't render the CSS anywhere else.
  3. When the page is loaded by the browser, the same render method is called, requiring react-spinkit and render it once again.
  4. This time, when requiring the css file, require("cssify")(stringifiedCss); is called.
  5. The cssify module builds the style tag with the stringifiedCss and appends to the head.
  6. Now the <Spinner /> tag is applied with proper CSS.

And voila! I can see the spinner on the browser, and React doesn't complain about anything :smiley:

Maybe this could be built into the default build process in react-spinkit. What do you think?

dijs commented 8 years ago

Ran into this as well... Any update on this?

merrywhether commented 7 years ago

Addressed in 3.0; can now use REACT_SPINKIT_NO_STYLES environment variable to opt out