gearz-lab / react-ui

Bootstrap based data components for React
http://reactui.com
MIT License
13 stars 1 forks source link

Farewell AMD. Enter CommonJS #6

Open andrerpena opened 9 years ago

andrerpena commented 9 years ago

I give up. It's impossible to make React play nice with AMD. I was trying to use AMD because it's the de-facto standard for the browser, but it doesn't work with React.

The reason why it doesn't work is because RequireJS doesn't understand JSX scripts. Not without using some unofficial/unsupported JSXTransformer version. If we threw away the JSXTransformer it would work but we cannot force our users to run react-tools during development.

I also tried to not to use RequireJS for components, just for libraries. But that also doesn't work.. because the components would have to have dependencies on the libraries and it's impossible to load these dependencies synchronously while rendering the components. RequireJS doesn't have a sync-mode.

So, after hours and hours trying to figure this out, I found out Facebook doesn't use AMD, they use CommonJS. More specifically Browserify (http://browserify.org/). Instagram uses Browserify too. In fact, ReactRouter, which is the possibly most popular React component outside Facebook, also uses CommonJS. Here's a component declaration example: https://github.com/rackt/react-router/blob/master/modules/components/RouteHandler.js

So, I'm moving to Browserify and I'll update React-Components to use the exact same structure as ReactRouter.

masbicudo commented 9 years ago

Ok, but what does this mean from these perspectives:

andrerpena commented 9 years ago

@masbicudo , the reason why CommonJS/Browserify seems to be the best fit is that nothing changes from the developer perspective and there's no tooling needed. :)

andrerpena commented 9 years ago

Actually.. there's one thing developers should be aware of:

ReactRouter declares components globally inside a namespace but you can use require to use them without the namespace..

In our case, TextBox would be globally declared as ReactComponents.TextBox, so this should work just fine:

<ReactComponents.TextBox />

But you can also do this:

var TextBox = require("components/editors/textbox.js");
<TextBox />;

In the example above.. the root directory for dependency resolving is the dist directory, so the code should be compiled first. However, I'll include a Gulp task that will automatically compile ReactComponents on the fly. This Gulp task can be ran through npm, but editors like Sublime and WebStorm support Gulp from inside the IDE. So it's even easier. I'll explain exactly how this works in Wiki page.

andrerpena commented 9 years ago

I'm currently testing browserify and I'll come back here when I have any update

masbicudo commented 9 years ago

I feel much more comfortable knowing that editors support this... or at least some kind of automated task, that requires no additional burden on the developer (e.g. a one-time action is acceptable in my opinion).

Should we use ReactComponents.TextBox or endorse it's usage? It seems this goes against the principles of using a dependency resolver. What do you think?

Is it possible to merge files in a single js file and still use CommonJS?

andrerpena commented 9 years ago

Actually I was wrong about how Browserify works. I have created a sample application with a description task to help you understand how it works.

Please refer to: https://github.com/andrerpena/browserify-tests

andrerpena commented 9 years ago

Browserify is not enough because it doesn't work with JSX files natively. You need a transform to do it. This transform is called Reactify.

I created an explained sample project: https://github.com/andrerpena/browserify-reactify-tests