RaveJS / rave

Zero-configuration application bootstrap and development
278 stars 8 forks source link

Create a rave-start-react Starter? #26

Closed unscriptable closed 10 years ago

unscriptable commented 10 years ago

A few folks at jsconf -- as well as a Pivotal person -- expressed interest in using rave with Facebook React. Thoughts?

KidkArolis commented 10 years ago

Would the jsx compilation happen in the browser via a loader? In general, do you think that's a .. scalable approach? Isn't it better to compile+cache on the server? I suppose you could combine rave loader with a serverside element that serves jsx (coffee etc.) files as js. I know that's out of scope for rave, just talking to myself at this point.

fabricematrat commented 10 years ago

more than interested also in the unidirectional data flow !

On Mon, Jun 2, 2014 at 8:58 PM, John Hann notifications@github.com wrote:

A few folks at jsconf -- as well as a Pivotal person -- expressed interest in using rave with Facebook React. Thoughts?

— Reply to this email directly or view it on GitHub https://github.com/RaveJS/rave/issues/26.

Best regards,

┏( ^◡^)┛ ┗(^◡^ )┓ I rock RaveJS! ┏( ^◡^)┛ ┗(^◡^ )┓

http://rivieragug.org/ http://3musket33rs.github.com/ http://fabricematrat.github.io/

unscriptable commented 10 years ago

I think my favorite pattern is to do the compilation (jsx or other kinds) inside the translate hook of the ES6 loader if the files aren't already pre-compiled. The pre-compile step would be performed by the build process, too, of course. In this case (pre-compiled), the translate step would be skipped in the browser. I'm putting together a proposed plan for the build process and will post it this week.

KidkArolis commented 10 years ago

Would you require such files with the extension? e.g. require("./my-component.jsx"). Because for some reason I feel like I would prefer to require them as javascript files require("./my-component"), especially if you think about distributing such components via npm for others to consume. "Pretending" they're just JS wouldn't require others to setup their loaders in any specific way.

In general, in case of .jsx, .coffee, .less, etc. there are currently 3 ways of pulling such files in.

And to make those work, you can either

I'm just trying to figure out if there's the best way of doing these things - agreeing on one way of doing it would be good for interop? If we could agree on how these requires() should be written, and how the translation step could be described via package.json, suddenly all npm packages could be requiring in all these extra assets in a consistent way, so tools like webpack, browserify, rave, jspm, etc. could all load those packages and correctly resolve the requires (even if the implementations of the actual loaders are different). Or is this a pipe dream?

I'm assuming the AMD style loader plugins are likely going away, so we can focus on the file extension based approach. For anything that's not javascript, we just always use an extension. The only question then is with compile-to-js files - you can either compile them to js pre publishing to npm and use extensionless requires, or require them with an extension (e.g. jsx, coffee) and translate in whatever tool you're using. Ok, I guess this is fairly simple. The "decribe how to translate in package.json" seems to be a lot more difficult, unless we agree on the "loader api", which is quite unlikely as browserify, and webpack, and rave already have different loaders.. so an html transform in browserify might do something different from an html loader in rave. In fact in webpack, for example, an html loader does some image inlining or smth. It's fine to do whatever you want in your own application, but when publishing packages to npm, I'm wondering if there's a way to interop, other than webpack and rave implementing support for browserify transforms, webpack and browserify implementing support for rave loaders and so on.

Anyways, sorry for such a long comment, don't mean to waste anyone's time, just trying to understand things..

Btw, the translate hook that can understand if something is precompiled sounds awesome, cause it means you can choose if you want to compile on the browser on the fly, or precompile on your server at serve time. How do you know if something has been precompiled?

KidkArolis commented 10 years ago

I've created a rave-load-jsx extension (https://github.com/KidkArolis/rave-load-jsx) as a starting point.

I couldn't get react from npm to load via rave, so I used their browser build (http://fb.me/react-0.10.0.js) in the example. But would probably be great to get the npm package working next. On the other hand - the browser build is 1 file whereas the npm version is like >100 files.

phated commented 10 years ago

I want react to work with Rave, including transpiling JSX. The npm version should be a priority.

KidkArolis commented 10 years ago

The only reason react doesn't currently work in rave is the use of process.env.NODE_ENV check in one place (lib/invariant.js). process is undefined in the browser and so that breaks. In browserify they use envify to transform process.env.NODE_ENV to a string, e.g. "development". Not sure yet how they do it in webpack.

So currently to use react you can install it via bower, since that has the built browser version. Or you can put in <script>window.process = {env: {}};</script> on the page and the rest of npm react works.

How could we solve this better (whilst using npm for everything). Some options:

  1. rave extension that injects process with env on the page (or provides that locally to the modules)
  2. rave extension like envify that transforms process.env.NODE_ENV to strings based on config (is there a concept of development/production env in rave?). In this case, how would you configure which modules should be transformed. In browserify, it's configured via package.json https://github.com/facebook/react/blob/master/npm-react/package.json#L33-L35 or globally.
  3. rave extension that supports all browserify transforms (and looks for browserify key in package.json to know which ones to apply to which package
unscriptable commented 10 years ago

Would you require such files with the extension? e.g. require("./my-component.jsx"). Because for some reason I feel like I would prefer to require them as javascript files require("./my-component"), especially if you think about distributing such components via npm for others to consume. "Pretending" they're just JS wouldn't require others to setup their loaders in any specific way.

Require-by-extension seems closest to what the node folks have already done with .cs and .json files. It's also less redundant and less AMD-like. (Unfortunately, there are lots of AMD haters.)

It's not clear to me how something could pretend to be js instead of jsx.

In general, in case of .jsx, .coffee, .less, etc. there are currently 3 ways of pulling such files in.

  • require("./component.jsx")
  • require("./component")
  • require("jsx!./component.jsx") And to make those work, you can either
  • compile on the server (e.g. with https://www.npmjs.org/package/connect-jsx)
  • compile at bundling time (e.g. webpack/browserify)
  • compile in the browser (e.g. with es6 translate hook). In this case, require("./component") is a lot trickier, since you don't know how to translate this file, unless the whole package is set to a certain type

We've been leaning heavily towards a combo of compile-at-bundle + compile-at-browser wherein the dev can switch from one to the other.

I'm just trying to figure out if there's the best way of doing these things - agreeing on one way of doing it would be good for interop? If we could agree on how these requires() should be written, and how the translation step could be described via package.json, suddenly all npm packages could be requiring in all these extra assets in a consistent way, so tools like webpack, browserify, rave, jspm, etc. could all load those packages and correctly resolve the requires (even if the implementations of the actual loaders are different). Or is this a pipe dream?

Standardizing on the module name format would be ideal, of course. That's why we're following the precedent that node has established: using file extensions.

In ES6, the translation step can be performed by the Loader, so I've been thinking that any solution should allow that pattern. webpack and browserify need to get on the ES6 bandwagon, imho.

It hadn't occurred to me that the translation hook could be described in package.json. In the long term, this could be successful. In the short term, I feel that the discussion will be long and frustrating (like they are on bower) or short and frustrating (as they are on npm). The easiest way around standardization of loader hooks is to install rave extensions that do the config work, imho.

In fact in webpack, for example, an html loader does some image inlining or smth.

Image inlining seems like a feature that could be user-configurable.

It's fine to do whatever you want in your own application, but when publishing packages to npm, I'm wondering if there's a way to interop, other than webpack and rave implementing support for browserify transforms, webpack and browserify implementing support for rave loaders and so on.

My opinion atm: publish un-transformed code to npm/bower and use .jsx file extensions. I have no idea what the industry consensus is on this, though.

Btw, the translate hook that can understand if something is precompiled sounds awesome, cause it means you can choose if you want to compile on the browser on the fly, or precompile on your server at serve time. How do you know if something has been precompiled?

I don't think there's any reliable way to know in many situations. I've been thinking that the developer has to specify which "mode" they're in explicitly. Maybe that's a topic for a different discussion. :)

unscriptable commented 10 years ago

The only reason react doesn't currently work in rave is the use of process.env.NODE_ENV check in one place (lib/invariant.js). process is undefined in the browser and so that breaks. In browserify they use envify to transform process.env.NODE_ENV to a string, e.g. "development". Not sure yet how they do it in webpack.

So typical. Too many folks assume that npm implies a node run-time.

How could we solve this better (whilst using npm for everything). Some options:

  • rave extension that injects process with env on the page (or provides that locally to the modules)
  • rave extension like envify that transforms process.env.NODE_ENV to strings based on config (is there a concept of development/production env in rave?). In this case, how would you configure which modules should be transformed. In browserify, it's configured via package.json https://github.com/facebook/react/blob/master/npm-react/package.json#L33-L35 or globally.
  • rave extension that supports all browserify transforms (and looks for browserify key in package.json to know which ones to apply to which package

Until we have a better idea of the best long-term strategy, I like the "rave extension that injects process" option as a short-term solution.

KidkArolis commented 10 years ago

I've created a rave-node-process extension (6 liner). Now it's possible to use npm's react and jsx files simply by installing the following.

npm install --save rave-load-jsx rave-node-process react

Next, I want to publish rave-load-jsx to bower and then write up the starter guide based on rave-start-angular.

A couple of interesting things:

  1. In rave-node-process I'm using the node-process module which uses browser field in it's package.json, so that browser field feature will be useful to have ;)
  2. If you run the npm install command above and try requiring in react you'll see the node_modules hierarchy issue kick in, it's trying to load esprima-fb/package.json but esprima-fb is installed one level up.
unscriptable commented 10 years ago

I've created a rave-node-process extension (6 liner).

Very nice. I'm a bit cautious of some of the process functions that they stubbed. Silent failures are sure to piss somebody off. Oh well, it's a start and we can deflect the issues onto that repo. :)

In rave-node-process I'm using the node-process module which uses browser field in it's package.json

I see you worked around this pretty easily. :)

If you run the npm install command above and try requiring in react you'll see the node_modules hierarchy issue kick in, it's trying to load esprima-fb/package.json but esprima-fb is installed one level up.

Does esprima-fb eventually get crawled/discovered?

unscriptable commented 10 years ago

Looks like @shichme has taken the lead on this: https://www.npmjs.org/package/rave-react-start

@snichme: is this ready to try?

unscriptable commented 10 years ago

Hey @snichme, I think I gave you bad advice when I asked you to publish to npm/bower. The correct way to install a Starter is to clone it or unzip into a directory.

Hmm... should we create a page or other mechanism to make it easier to discover Rave Starters? For instance, @fabricematrat also has a rave starter: https://github.com/fabricematrat/rave-start-cujo

snichme commented 10 years ago

Sure, it's not much yet but please, try it out.

Yeah, having it on npm feel wrong. How about a simple repo with a README that lists starters? Or spend some time creating a website for rave (or include it onto cujos page) with a list of starters.

unscriptable commented 10 years ago

Hey @snichme, I just tried it and it worked perfectly. I lolled when I saw your interpretation of a "Hello World" app! :) It may be a bit flashy, but it gives a really great demo, atm.

Gonna close this issue since we have a rave-start-react! Thanks!