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
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
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
Now that we have our app running proudly, let's start by installing
aurelia-bundler. To do so
skeleton-navigation and run the following command:
Now, let's create a
bundle.js file in
Note that the bundle function returns a Promise.
With that file in place, let's run the command bellow:null
Here are the things that happened after gulp is finished executing the task:
- A file,
- A file,
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
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:null
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
skeleton-navigationpointed to the
distfolder, we named it
distfolder and we have a
pathrule configured in
config.jsthat points to the
distfolder, 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
!texttells the Bundler and Loader that these files will be bundled and loaded using the
*.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
!csshere. The Aurelia Loader uses
textplugin for loading css to analyze and do other interesting stuff like
excludes: This is where we specify what we want to exclude from the bundle. For example, if we usednull
*to include all the JS files in the
distfolder, and for some reason we wanted
app.jsto 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
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:null
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
buildclears/removes all the files in the
distfolder. So, any bundle file in that folder will be deleted too. This is why we always have to run the
gulp bundleafter the
buildtask is finished. If you are using
watchyou will have to be extra careful because every change you make in the source file will trigger a
buildtask that clears the
distfolder 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.htmland will be placed in the
htmlimport : This is what makes it different from other bundles. If this is set to
truethe 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 andnull
!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
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
. Thanks and we look forward to seeing what great things you will build!