Update - I may be switching from webpack to rollup, which is written by Rich Harris as well. I didn't find rollup until I tried figuring out how to make this component loader work with es6. Oops.

I've switched from ractive-loader to the ractive-component-loader, and it's pretty dandy. If you're not familiar with setting up webpack or a webpack loader, read my previous post about ractive-loader for a sample webpack config. If you would prefer to keep your templates separate from your component's logic, that post is probably more appropriate for you, too.

Instead of having, for example... Loading.js, and Loading.html, I now have just Loading.html:

<p>
	<i class="fa fa-spinner fa-pulse fa-2x fa-fw" /> <!-- font-awesome spinning icon -->
	{{message}}
</p>

<script>
	component.exports = {
		data: function () {
			return { message: 'Loading...' }; // default message
		}
	};
</script>

The ractive-component-loader for webpack compiles the html template portion to javascript, sets it into component.exports.template, and sets module.exports = Ractive.extend(component.exports). So now I can use my Loading component like so:

var Loading = require('./Loading.html');
new Loading({ el: '#SomeContainer' });

Or, from other components...

<link rel="ractive" name="Loading" href="./Loading.html" />

<h1>App</h1>
{{#if !user && !error}} <!-- if the user data isn't loaded and there's no error set, show loading message -->
	<Loading message="Loading profile data..." />
{{/if}

<script>
	var userService = require('../services/UserService.js');

	component.exports = {
		oninit: function(){
			var me = this; // could also use bind on handler

			// pretend the user service returns a jQuery 
			userService.getCurrentUser().done(function(response){
				me.set('user', response);
			}).error(function(response){
				me.set('error', response.responseJSON);
			});
		}
	};
</script>

Couple things:

  • ractive-component-loader compiles your template, sets it into component.exports.template, then sets module.exports = Ractive.extend(component.exports)
  • any tags will be set into component.exports.components by name
  • it also looks for styles and will set them into component.css, if you're doing that.
  • Note that the github README documentation on resolving child components is a bit off. You use a <link ... /> tag, not an <import .../> tag.
  • Also note that you can also still use components: { name: value } here, if you need to do something more complicated, like returning a string name of a component from a function (eg: http://stackoverflow.com/questions/31075341/how-to-create-ractives-subcomponents-dynamically-and-change-them-programmatical)