Blaze <==> React Refactor Paths?

The react package supports .jsx (and .jss ? I don’t know)

Let’s say you have :

Template.Foo.helpers( {
	target() {
		return 'foo';
	}
} );

<template name='Foo'>
	<p>my text</p>
	{{#Button
		target = target
		location = 'bar'
	}}
		baz
	{{/Button}}
</template>

<template name='Button'>
	
	<button>
		{{#if target}}
			<label>{{target}}</label>
		{{/if}}
		{{location}} {{> UI.contentBlock}}
	</button>

</template>

How does the transpiler knows what is a property, a state, a variable it should put in the render function, a function it should build in the component root… Why would be target in the Button component be a props, but a function in the Foo component. You would have to analyse also all the javascript.

Jsx is html + js. You cannot do html to jsx. You have to do all your html + js to jsx. The meta analyse would be so complex.

I mean, it would be an amazing piece of code. But so much more expensive than just doing the changes by hand.

Sounds like a job for a build plugin. Defining handlers for special file extensions is something Meteor actually gives you a lot of tools for (and is how we built the default jsx package itself!)

2 Likes

Just use Webpack to build your React code. You get the added benefit of being able to do ES6 imports instead of dealing with global/local vars and file load order in pure Meteor. It outputs bundles that meteor can consume, and only took me a few hours to get working. No need to clutter the Meteor codebase with anything to support React. The only small issue I haven’t solved yet is how to get meteor to pull in the source maps that Webpack generates.

1 Like

Are you doing this with a build plugin, or some other method? If you put the Webpack compilation logic into a build plugin, you should be able to get source maps working quite easily. Here’s an example for Browserify: https://github.com/elidoran/cosmos-browserify/blob/master/plugin/browserify.coffee

This approach will become much faster/better in Meteor 1.2, which will introduce two features:

  1. Caching for built output
  2. The ability to override the default handler for .js files, so that you can process all your app’s JS code with Webpack if you so choose.

Of course, if you wait long enough I’m 100% sure someone will build a Webpack package anyway.

1 Like

A build plugin almost seems like overkill since it’s possible to run Webpack independently and have it output its bundles into the Meteor directory where meteor will automatically pick them up. Though it would simplify the launch process a bit. The only thing lacking is for Meteor to pull in the source maps that Webpack generated – seems like that would be trivial for Meteor to do? But thanks for the link, maybe I’ll be able to adapt that code to handle the source maps.

I think that’s the whole point of build plugins. For example, you could run the less compiler separately but it makes more sense as a build plugin so that you can just add a package instead of running a separate tool.

1 Like

@sashko -
Yeah, build plugin sounds like it may be a perfect solution to this. Any chance you could provide a link for the repo of the jsx package? I’ve looked all around, and can’t seem to find it (except for the package on Atmosphere; which has no GitHub link).

@fabienhuet - I’m not saying that there won’t need to be manual analysis or scrubbing of data. I’m just looking for tools that will help in the process. Most of my code is already organized by components; and pretty lean; so all I really need to do is convert

    <template name='Foo'>
 	<p>my text</p>
	<button>
          {{#if foo}}
	    <label>{{foo}}</label>
	  {{/if}}
          words
	</button>
        baz
    </template>

into something like this:

var { dom } = require("deku");

var foo =  
  <p>my text</p>
  <button>
    {{#if foo}}
      <label>{[foo]}</label>
    {{/if}}
    words
  </button>
  baz;

Ideally, the build plugin would know how to wrap a .jsx file in a var, and attach the necessary requires (no clue what this deku thing is, whether it’s a dependency, or just an example. It has no relevancy to the apps I’m writing, other than apparently being a dependency of React; so it should go in the build plugin, rather than cluttering my app code.

var { dom } = require("deku");
var foo =  

;
```
And ideally we'd be left with the following code in a ``foo.jsx`` file:

````html
  <p>my text</p>
  <button>
    {{#if foo}}
      <label>{[foo]}</label>
    {{/if}}
    words
  </button>
  baz
```

Which looks almost exactly like regular Spacebars HTML.  If I know I can convert my HTML into JSX, and expose it to my JS file; that's a huge win, and gets me a considerable step closer to converting existing Blaze apps into React.  I can write utilities that convert file extensions from ``.html`` to ``.jsx`` and replace ``{{ }}`` instances in the code into ``{[ ]}``.  That's doable.

@jedwards - Thanks for the reference for Webpack!  It took me a day or two, and a couple re-reads, to figure out exactly what it's doing; but dang, it's quite the handy little tool, isn't it?  Do you have any additional resources for using Webpack and Meteor?  Any example repos maybe?

@sashko - nevermind; just found the jsx package. jsx-templating had a link.

Also, this jsx-templating package looks great. It’s spot on. timbrandin is on exactly the right track. If folks can get the Blaze API to layer over React, that would be simply amazing. Scrap the different sections in the tutorial (which is confusing), and just have Blaze compile down to React. Then, all of refactoring and migrations become a non-issue.

+1 for what’s going on within jsx-templating

I’m trying to make a plugin. So far, I’m not sure how well it will work. For one, webpack config is specified in a Node js file, meaning it can use require, which is unavailable to my plugin (come on! the server code is running in Node anyway, hiding require from it is just mean). Secondly, the Webpack API is async – it looks like source plugins probably have to be synchronous?

Unfortunately all I’ve found about using the two together was a project that uses yet another frontend framework with Meteor: https://github.com/vuejs/vue-webpack-meteor-example I’m trying to figure out if I can make a Meteor plugin for it but…Meteor makes it quite difficult.

I think I’m just going to make a simple plugin that loads the webpack bundle and its source map. Meteor should really be loading source maps by default though.

1 Like

Arggggggh…

I wrote this simple plugin:

var fs = Npm.require('fs');
var path = Npm.require('path');

function processFile(step) {
  var options = {
    path: step.inputPath,
    data: fs.readFileSync(step.fullInputPath, {encoding: 'utf8'}),
    sourcePath: step.inputPath,
  };
  if (fs.existsSync(step.fullInputPath + '.map')) {
    options.sourceMap = fs.readFileSync(step.fullInputPath + '.map', {encoding: 'utf8'});
  }

  console.log('adding file: ' + options);

  step.addJavaScript(options);
}

Plugin.registerSourceHandler('bundle.js', processFile);

It totally works when loading just the bundle, but blows up when loading the source map: any tips?

/home/andy/.meteor/packages/meteor-tool/.1.1.3.4sddkj++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/lib/node_modules/fibers/future.js:245
throw(ex);
^
Error: “webpack:/webpack/bootstrap e0fa346f18878abd575b” is not in the SourceMap.
at SourceMapConsumer_sourceContentFor [as sourceContentFor] (/home/andy/.meteor/packages/meteor-tool/.1.1.3.4sddkj++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/lib/node_modules/source-map/lib/source-map/source-map-consumer.js:380:13)

I wish Meteor had a middleware-only version. That’s all my boss and I wanted to use it for; we didn’t want the whole jungle.

Okay, I figured out a far simpler solution to using Webpack for the frontend. Instead of having it output a bundle.js somewhere where Meteor will pick it up, you have webpack-dev-server serve up the bundle on a different port, say localhost:9000, and then in your root html file you put <script type="text/javascript" src="http://localhost:9000/assets/bundle.js"></script> That way you get the source maps, you can use the react-hot-loader, and you can view and debug on all the original ES6/jsx source files. With this you also get the benefit of being able to easily npm install whatever 3rd party React components or other tools you want to use, and then simply require/import them in your frontend code. I think I may still have to do a bit of fiddling to give the webpack bundle access to various Meteor package variables, but that shouldn’t be too hard.

@awatson1978 Hey, I set up an example repo of using webpack-dev-server and react-hot-loader together with Meteor: https://github.com/jedwards1211/meteor-webpack-react

1 Like

@awatson1978 I know this thread is almost 2 years old, but my mini-project maybe can be useful to someone:

Following two npm packages can convert Blaze source code to React source code:

https://www.npmjs.com/package/blaze2gasoline
https://www.npmjs.com/package/gasoline-turbo

Usage:

blaze2gasoline -i path_to_blaze_file.html -o ./gas.json
gasoline-turbo -i ./gas.json -o output_directory/ -f react

…and result is native .jsx file.

Don’t expect miracles, but it can save some (boring) manual work.

Note 1: it’s very fresh, so expect bugs!
Note 2: I am doing this for some other reason (my target is not converting Blaze to React or Angular)

2 Likes

Online Blaze to React converter: https://blaze2react.meteorcluster.com/

Still far from perfect but getting closer :slight_smile:

3 Likes

very cool. I

is it correct to say that this integrates helpers and events only? or is there a way to patch blaze lifecyle to react lifecycle like rendered to didMount, destroyed to willUnmount etc? (is that correct anyway?)

very useful for apps with many templates.

Thank you very much for building this!

@vectorselector thanks.

Not entire cycle is covered at the moment, but I’m using this package in my hobby project https://www.meteorkitchen.com so I am improving blaze2react occasionally when I find some free time, and one of missing features is “cover entire lifecycle” (at least onRendered as most frequently used). You can expect improvements in that direction, but I cannot promise when because it’s really just a hobby.

No worries, most of my .onCreated .onRendered .onDestroyed blaze lifecycle stuff is just setting-up state, which React will handle anyway differently, with this.state in the constructor and .setState …

I’m pleased to see all events and handlers nicely tucked-in as functions, and called from the jsx appropriately.

Great job, and useful tools!

I was looking at hours and hours of what looked like a manual job, but you managed to script it very nicely