Update February 2016: A more comprehensive article on bundling and exporting Aurelia applications has been published here. This post will remain, but it is encouraged to take a look at the newer post which answers things more clearly and gives examples.
If you’re using the JSPM Package Manager with Aurelia, then this post is for you. There is a lot of uncertainty about bundling an Aurelia application and what deploying to production actually looks like. Until Aurelia comes with a proper bundling solution (the Aurelia CLI has been dropped), then we’re left to scratch our heads and use snippets from blog posts. There is now an official Aurelia bundler released which means we don’t have to glue together bundling solutions anymore.
Even after you have bundled your application, what does the rest of the workflow look like? What files get deployed, what folders and what needs to change?
Some questions you might have:
- What do I bundle in my Aurelia application and do I bundle everything or just Aurelia dependencies?
- Do I commit the config.js file into my repository?
- Do I commit my app-bundle.js file into my repository?
- Should the
jspm_packages
folder be committed into my repository? - Does the
jspm_packages
folder get deployed to production?
Don’t bundle everything
My initial approach in my Aurelia application was to bundle everything. Not just Aurelia’s dependencies, but absolutely everything in my project. Some examples from a current project I am working on; Moment.js, Dexie.js, Select2, To Markdown, Showdown, jQuery, Sortable and a couple of other dependencies.
This is the incorrect approach to take. While JSPM supports creating multiple bundles, I could never find the right medium to have multiple dependency bundles within Aurelia.
I soon realised that bundling up just Aurelia and its dependencies first (because they’re global to the entire application) made a lot of sense. But bundling in jQuery or Select2 (when it might not always be needed), made zero sense. Why include everything when the user might only ever use 50% of your bundle?
Not bundling all of your dependencies also makes a lot of sense if you’re using HTTP/2 with its multiplexing features which basically render the need to minify or combine files useless.
However, support isn’t completely there yet, but when it is, having your jspm_packages
folder there ready to switch everything over will be a lot easier.
What to commit
The config.js
file is made to be committed to your Git repository. In-fact, if you look at any Aurelia dependency (or the Skeleton Navigation application), you will see a config.js
file in the root directory of the repository.
JSPM is a smart package manager in that it selectively replaces parts of your application (map and bundles), whilst allowing you to specify configuration options that don’t get overwritten.
You might be tempted to also commit your bundled Javascript file into your repository. Do NOT do this. You will encounter a mountain of migraines courtesy of Git conflicts if you commit a dynamically generated bundle.
If someone were to remove a package and commit the bundle, it would most certainly cause merge conflicts. This file is made to be built as part of your application build process, not within your codebase.
As is always a rule of thumb with any package manager, under no circumstances should you commit your jspm_packages
folder. This gets built when you run the jspm install -y
command.
The same also applies to any package manager like Bower or NPM, do NOT commit the packages folder. If you’re experiencing issues with your build server and cannot generate a Github token (or whatever) for JSPM, commit your jspm_packages
folder as a last resort.
How to bundle
Previously I detailed a custom way of bundling your Aurelia application into bundles, but since publishing the official Aurelia bundler has been released.
Before you copy or configure anything, make sure you install the bundler by opening up your console and typing: npm install aurelia-bundler --save-dev
To bundle your existing applications, you’ll want to copy over the build/tasks/bundle.js Gulp task file within the Aurelia Skeleton Navigation repository to your build/tasks
folder.
If you are not using Bootstrap in your application, you’ll want to remove the line which includes the CSS into the bundle or you’ll run into some errors: 'bootstrap/css/bootstrap.css!text'
— If you’re also not using the aurelia-animator-css dependency, you’ll want to remove the line that tries to bundle it as well: 'aurelia-animator-css'
If you’re planning on bundling CSS, you’ll need the text plugin to do so. The original blog post didn’t detail this step for those wanting to bundle existing applications. Simply install it by running in your console: jspm install text
To generate a bundle simply type: gulp bundle
or if you want to unbundle type: gulp unbundle
When your application is loaded, JSPM will first look in your bundle when a dependency is requested. If it is not found, it will load it using the map and get it from the jspm_packages
folder. And because we specified we wanted to inject our bundle, we don’t need to do anything as config.js
already knows about it.
Deployment
There are many different approaches you can take to deploy an application. You might be using a build deployment/continuous integration platform like TeamCity or you might be working directly on the server. You need to make sure your jspm_packages
folder is on the deployed server.
As mentioned above: do NOT commit your jspm_packages
folder into your Git repository. This is a dynamically created folder that is built and modified during installation, updating and removal of JSPM packages.
Because we’re not bundling all of our dependencies, we will need this folder. But more importantly, we need system.js which is inside of this folder to handle loading everything.
Conclusion
You probably were aware of some of the things mentioned here. This is to clear up some confusion around using JSPM and bundling an Aurelia application. This applies to even non-Aurelia applications using JSPM as well.
While tools like JSPM improve our workflow and processes on the front-end, sometimes it can be difficult to know where things sit within the overall flow and structure of a modern front-end application.
In the deployment phase, how are you handling cache busting? The objective would be to run one bundle command that generates a differently named app-bundle each time.
Wish this article went into more details.
@Alex
What else would you like to know? Ask your questions in a comment and I would be happy to elaborate or explain any question that you have further than the article did.
The navigation skeleton does a great job at setting up the bundling. It was relatively easy to get it to work. I played with the configuration a bit to reduce the bundle size to an absolute minimum.
At first it wasn’t clear to me that the defaultConfiguration in main.js would load extra dependencies, but to be fair, it’s covered in the docs.
I added my settings at the end of this article in case it helps someone else:
http://www.syntaxsuccess.com/viewarticle/comment-component-in-aurelia
In my case I only need templating, data binding and the fetch client.