How an Ember JS Bin works and how to create your own

Summary

Cory Forsyth
Aug 29, 2015 · 9 min read

update June 2017: Ember Twiddle has clearly emerged as the best way to experiment with Ember in an in-browser editor. This post is mostly of historical interest today, although support for some of the techniques described below do still exist in today’s Ember. If you are dealing with a legacy and/or rolled-your-own Ember setup, this may be particularly relevant. If all you’re looking to do is try out some Ember code in a browser, jump over to Ember Twiddle!

tl;dr If you’re just looking to quickly make an Ember JS Bin, check out these resources:

If you’re interested in learning about how an Ember app runs inside a JS Bin, and how that process is different than an Ember-cli-based app, read on.


JS Bin is a great tool for doing simple JavaScript and front-end code experiments. When you come across something in your Ember app that leaves you scratching your head, distilling your problem case into a JS Bin is a good way to think through what’s going on.

Transferring a pathological code case from your app to a JS Bin forces you to cut extraneous code and focus in on the source of the problem. This is a useful exercise in itself because it helps you to ascertain that you have truly found a bug in framework code and not your own app code, but it also helps you to understand the bug so that you can work around or fix it.

In addition, and perhaps most importantly, having a code sample in a JS Bin makes it easier for you to share the live bug with others. Step one in fixing a bug is to be able to repeat it, so having a live JS Bin that you can include in a github issue makes it much easier for other contributors to confirm and fix the bug.

Crafting an Ember JS Bin can be something of a dark art, though. Ember-cli provides a lot of excellent tooling that isn’t available in a JS Bin, so writing an Ember JS Bin has become a different skill set than the ES6 module-importing style that is the officially sanctioned way to write a new Ember app, and is increasingly not part of the official Ember documentation.

This post describes a few of the differences between making an Ember JS Bin and the current state-of-the-art in Ember coding that you’ll find in the Ember-cli-focused guides. Hopefully the next time you discover a mysterious bug in your app you’ll be able to use the notes here to craft an example JS Bin and help get the bug fixed.

This post goes into a fair amount of detail in order to describe not just how to make an Ember JS Bin but why it works as it does. If you are more interested in learning only the nuts-and-bolts, start with this annotated Ember JS Bin and fork it for your own purposes. More JS Bin examples are included at the end of this post.

Dependencies

Ember-cli manages including your Ember dependencies for you, but in a JS Bin you’ll need to include them yourself with script tags.

To run Ember in a JS Bin you need at a minimum the following 3 libraries:

  • jQuery — Ember depends on jQuery
  • ember-template-compiler.js — Because you will embed templates in your HTML and they will be compiled at run-time. More on this below
  • ember.js — For obvious reasons

To include these dependencies, use the time-honored tradition of simply dumping them as <script> tags into the <head> of your HTML.

You can serve jQuery from Google’s CDN. Here’s the script tag for version 2.1.4:

The two ember-related scripts are hosted at builds.emberjs.com. You can choose a tagged build or a named channel build (release, beta or canary). If you suspect your bug is with a specific version of Ember, you should use a tagged release with that specific version, otherwise your Ember version will “float” and change with the release cycle. Today’s canary is next cycle’s beta, for instance. At current time of writing the release channel build is Ember 2.0.1, but it will be 2.1.0 before too long — if you are demonstrating a bug in 2.0.1 but use the release channel build of Ember in your JS Bin, in a few weeks your JS Bin may also be using 2.1.0, which may no longer include the bug your JS Bin was supposed to demonstrate!

Use the same ember-template-compiler version as your Ember version.

The Ember official site includes a list of the version-tagged builds as well as the current release, beta, and canary channel builds. Use the “Script Tag” button to copy the appropriate script tag for inclusion in your JS Bin. Unless you have a specific reason not to, use the ember.debug.js version because it includes helpful debugging information.

“Globals Mode” Ember

In a JS Bin, the ember.js script tag that you’ve included will add a top-level global, `Ember` to the window. All of the Ember primitives you’ll need are available as properties on the `Ember` global. You can use `Ember.Application`, `Ember.Route`, `Ember.Component`, and so on. In Ember-cli you `import` your Ember global, but you otherwise access the Ember primitives in the same way, so this should be familiar.

The biggest difference between an app running via Ember-cli and a JS Bin is in how you structure your code to inform Ember where to find your Routes, Components, etc. In Ember-cli, the file structure is used to determine those pieces, but in a JS Bin you don’t have separate files that can `export`, so there needs to be another way for Ember to find and use your code.


Digression about the Ember Resolver

When Ember runs your application, it needs to know how to find the custom route/controller/component/etc code you wrote. Ember-cli uses each file’s name to determine its function — if you create a file at “app/routes/application.js”, an app running Ember-cli will use the default export of that file as its Application Route.

Ember uses a `Resolver` to do know how to find your app code. Ember-cli does two things that together make it possible for it to know that the file at “app/routes/application.js” holds your Application Route.

First, when Ember-cli transpiles your ES6 modules to named AMD modules (for use in a browser, where ES6 modules likely aren’t yet supported), it maps file paths to AMD module names. It will create a module named “<your-app-name>/routes/application”.

Second, Ember-cli uses an AMD-module-aware resolver that knows how to map strings of the format “type:name” (like “route:application”, in this case) to the appropriate named AMD module (like “<your-app-name>/routes/application”). Thus, when your Ember-cli-based Ember app boots up it is able to find and use the Application Route that you created (if you created one — if not Ember will use a default Route).


Using Ember in “Globals Mode”

When your Ember App is running in a JS Bin, it has no ES6 modules (or transpiled named AMD modules), so it can’t use the same module-aware Resolver that Ember-cli does. Instead, Ember ships with a default Resolver that knows how to look for specifically-named properties on your `App` instance. To find a `type` with a given `name`, it looks for a property named `${camelCasedName}${camelCasedType}` on your `App`. A few examples:

  • index route (type: “route”, name “index”) `App.IndexRoute`
  • application controller `App.ApplicationController`
  • Component called “my-neat-bin-example” ➛ `App.MyNeatBinExampleComponent`

There are many more examples in the system/resolver.js file.

This was originally the only way to write an Ember app, and many apps that were started before Ember-cli (and its predecessor, Ember App Kit) was available still create their class primitives by naming them in this camel-cased “name+type” way and rely on Ember’s built-in “globals mode” Resolver to find them. When you are writing an Ember App in a JS Bin, you must use camel-cased property names on your `App` instance.

Templates

In order to be able to render your HTMLBars templates, they must first be “compiled” into runnable JavaScript functions. When you’re using Ember-cli this process happens transparently behind the scenes. In addition, because the contents of template files do not change after an app boots, and there is a small performance penalty to compile them, Ember-cli compiles your templates at build time and only includes the compiled templates in the built version of your app. Since compilation will not happen at run time, the template compiler code is not included in your built app so that it has a smaller total JavaScript payload.

None of the above applies to an Ember Application running in a JS Bin, however — when your app runs in a JS Bin it must compile your templates at run (not build) time. This is why you must include the template compiler that ships separately from Ember. If you forget to include the template compiler in your JS Bin, Ember will helpful shout at you when it tries to compile your templates with this error: “Error: Cannot call `compile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compile`.”

Ember-cli uses the ember-cli-htmlbars addon to compile your templates and create named AMD modules for them that match the file’s path. The Ember-cli resolver also knows to look for, e.g., “template:application” in an AMD module name “<your-app>/templates/application”.

In a JS Bin, though, your compiled templates need to be where the globals mode resolver can find them. Looking back the the system/resolver.js file, we see that it looks for templates on an `Ember.TEMPLATES` object. The resolver will find the application template if it (its compiled version) is available as `Ember.TEMPLATES[‘application’]`.

The next step, therefore, is to figure out how to make your compiled templates available at `Ember.TEMPLATES`. Although you could certainly compile them yourself and set their values on the templates global yourself, Ember provides a simpler way. In the bootstrap code for Ember-HTMLBars, Ember uses jQuery to find script tags with type “text/x-handlebars” and “text/x-raw-handlebars” and compiles those. For the template name, it uses the `data-template-name` attribute or, if that doesn’t exist, the “id” of the script (or, if both are not present, defaults to the name “application”).

So, to create your templates in a JS Bin, make `<script type=”text/x-handlebars”></script>` tags in the HTML section of your bin. Give them a `data-template-name=”your-template-name”` attribute. The template name should be the same as the file path after “templates/” that you would use in your Ember-cli app. A few examples:

  • Application template “application”
  • my-select component template “components/my-select”

The usage of `<script>` tags to define your templates is a convenience that is facilitated by Ember’s bootstrap code knowing how to find and compile those templates, but it’s not doing anything else unexpected. You could use the template compiler programmatically yourself and forego the script templates altogether if you wanted to, as long as you set the values on `Ember.TEMPLATES` properly. I wouldn’t recommend this, as it much less convenient, but here’s an example JS Bin that does that. Notice no template script tags in the HTML.

Examples

The simplest way to make an Ember JS Bin is to clone an existing one and modify it for your needs. There are a few places to go looking:

Alternatives

Ember Twiddle is an excellent alternative to JS Bin for creating shareable, live Ember apps. It utilizes a workflow much more aligned with the Ember-cli workflow including ES6-style imports and exports, a file drawer, and more. It will likely soon overtake JS Bin as the de facto spot for creating shareable apps.

28

28 claps
Cory Forsyth

Written by

Hacker &c in NYC. I co-founded outside.in (acquired by AOL in 2011) and currently run 201-created.com, a JavaScript consultancy.