Get the Newsletter

Bundling Aurelia Apps

Posted by AureliaEffect on September 11, 2015

Our latest Aurelia release has made significant advances, with more on the horizon. Today, Core Team Member Ahmed Shuhel will share how our bundling strategy is evolving to support the framework and our community.

Previously, Aurelia Loader used HTML Imports to load all views. Now, as it is apparent that HTML Imports is not going to be standardized in its current form, we have replaced our default view loading mechanism with a SystemJS text-based solution. The same solution has been applied to CSS loading as well. To learn more about this change, you can read our recent release notes post . We are emphasizing this again here because these changes affect bundling, as you will see below.

Also, previously we were using Aurelia CLI to bundle our apps. However, we have decided to set aside the CLI effort for now since it mostly duplicated great work already done by tools like gulp, grunt, yeoman, etc. Instead, we are providing first class support for these tools via a small focused bundling library Aurelia Bundler that can be used from a gulp task or any other tool.

In the remainder of this post we will see how we can use Aurelia Bundler to create a gulp task for bundling our app. Let's jump right into it. We will use skeleton-navigation as our app to bundle. If you don't have that setup. Follow these steps .

Now that we have our app running proudly, let's start by installing aurelia-bundler. To do so cd into skeleton-navigation and run the following command:


Now, let's create a bundle.js file in build/tasks/bundle.js as:


Note that the bundle function returns a Promise.

With that file in place, let's run the command bellow:


Here are the things that happened after gulp is finished executing the task:

  • A file, dist/app-build.js is created.
  • A file, dist/aurelia.js is created.
  • config.js is updated.

Now, if we refresh/reload the app from the browser, we will see much less network traffic, which means our app is properly bundled.

Let us now take a closer look at the config object. We will skip force and packagePath for the moment. bundles is where we will focus first.

We can create as many bundles as we want. Here we have created two: one for the app source and another for the Aurelia libs. Again, we can create just a single bundle if we want that combines both application source and Aurelia libs. The number of bundles we would like to have mostly depends on our application structure and the usage patterns of our app. For example, if our app has a design that actually makes it a collection of child-apps/sections, then a "common" bundle and a "bundle per section" makes much more sense and performs better than a huge single bundle that needs to be loaded upfront.

Here is a typical bundle configuration with all it's glory:

  • dist/app-build : This is the name of the bundle and also where the bundle file will be placed. The name of the bundle file will be app-build.js. Since the baseURL for skeleton-navigation pointed to the dist folder, we named it dist/app-build.

  • includes : We will specify all the modules/files that we want to include here. Since all our JavaScript modules are in the dist folder and we have a path rule configured in config.js that points to the dist folder, if we simply specify *, all our JS modules will be included. We can specify */**/* here if we want to include all the subfolders.

  • *.html!text: This includes all the templates/views in the bundle. the !text tells the Bundler and Loader that these files will be bundled and loaded using the text plugin.

  • *.css!text: Like html templates, we are including all the css here. If you have previously used plugin-css, note that we are not using !css here. The Aurelia Loader uses text plugin for loading css to analyze and do other interesting stuff like scoping etc.

  • excludes: This is where we specify what we want to exclude from the bundle. For example, if we used * to include all the JS files in the dist folder, and for some reason we wanted app.js to be excluded from the bundle, we would write:


Now, let's open src/main.js and add this line: aurelia.use.plugin('aurelia-html-import-template-loader'). After that change, main.js should look like this:


With this little change Aurelia Loader will now use HTML Imports to load all the views. Now, back in our bundle task, we will add a config like this:


And, we will also change the first bundle a little bit to exclude all the html and css files. Finally our bundle.js file should look like this:


We have changed the source code (src/main.js), so we need to rebuild our app. The command bellow should do that:


Now, let's run gulp bundle in a new command/console tab. If we now refresh/reload our app from the browser keeping the developer tools open, we should see the difference.

Note that order of running the tasks is important here. The build clears/removes all the files in the dist folder. So, any bundle file in that folder will be deleted too. This is why we always have to run the gulp bundle after the build task is finished. If you are using watch you will have to be extra careful because every change you make in the source file will trigger a build task that clears the dist folder and any bundles as well.

Let's examine the configuration now. If you were using the CLI previously this may look familiar. The only difference here is that we have introduced some uniformity in the config api. Let's examine this config one property at a time:

  • dist/view-bundle : The name of the bundle file is view-bundle.html and will be placed in the dist folder.

  • htmlimport : This is what makes it different from other bundles. If this is set to true the bundler will treat it as an html import-based bundle and the Aurelia loader will give it a different treatment as well.

  • includes: This is where we will specify what goes in the bundle. All the glob patterns are supported here including arrays of patterns and ! based exclusion. For example:


There are two final important notes about bundling. First, our new bundling is designed to work with the latest version of Aurelia. So, you will need to update your libraries to use this. Second, now that our default view loading is based on the text plugin, you must install plugin-text with jspm install text for text-based bundling to work. This dependency is only needed at build time.

We hope this makes clear how to use bundling, as well as simplifies the process for you and helps you integrate it into your existing tool chain. If you have any issues regarding bundling be sure to raise issues here . Thanks and we look forward to seeing what great things you will build!