Aurelia CLI bundling question


#1

Apologies if this has been asked before or described somewhere, but I couldn’t find it.

Basically, I have a pretty standard project built using the new Aurelia CLI bundler. For production builds, we have revisions enabled to make sure the latest bundles get loaded when clients connect. This all works great.

My problem is actually that it somehow doesn’t feel right that my 3Mb vendor bundle changes every time I make even just a small change in my app code. I have come to the conclusion that this is the case because the app bundle is loaded by the vendor bundle, and since the filename for the app bundle changed, so does the vendor bundle contents. So if I change <h4>Heading<h4> to <h3>Heading<h3> I have to redeploy both vendor bundle and app bundle because both their filenames have changed.

What I’m asking is if there is a way to break this out somehow? Perhaps have an entry bundle that loads the vendor bundle and then the app bundle. In that case, when the change is made, the app bundle and entry bundle filename will change, but entry bundle should only be very small (because it’s only loading the other 2 files), and vendor bundle stays the same thus not needing to redeploy a 3Mb file.

Looking forward to hearing about solutions.


#2

Your “entry” bundle is actually called “vendor”.
There is nothing stopping you from keeping the vendor bundle the same as generated by the CLI and adding all your dependencies to a third bundle.

Edit: that’s how you break things up. I cannot guarantee that your third bundle will not be changed / rehashed. Someone more familiar with the bundling system code base can confirm.


#3

That’s the correct behaviour of having “revision” turned on.

When you modify your local source code, your app-bundle gets a new hash like app-bundle-12345.js. Even with no JavaScript changes, the vendor-bundle contains another piece called requirejs.config where app-bundle-12345 was written to the config for vendor-bundle to know where to find app-bundle at runtime. So vendor-bundle also got a small change, hence a new hash was generated.

To minimise the impact of “revision”, you can create multiple bundles. The idea is to move deps to other bundle files, so they are not affected by the small requirejs.config change in vendor-bundle. You still have app-bundle and vendor-bundle updating hash, but vendor-bundle is very small now.

But the downside is you need some explicit deps config in aurelia.json, for example, the aurelia-bundle.js and some-other-bundle.js would not update the hash when you touch your local source code. Note you cannot move prepend from vendor-bundle to other place, because prepend has to happen before AMD module loader (requirejs in my example).

If your app is big, you can also split app-bundle.js into multiple bundle files (use source minimatch, you can read cli doc), so local change will affect a small bundle file, not the huge app-bundle.js.

"bundles": [
      {
        "name": "app-bundle.js",
        "source": [
          "**/*.{js,json,css,html}"
        ]
      },
      {
        "name": "aurelia-bundle.js",
        "dependencies": [
          "aurelia-bootstrapper",
          "aurelia-loader-default",
          "aurelia-pal-browser",
          "aurelia-framework",
          "aurelia-router",
          "aurelia-binding",
          "aurelia-animator-css",
          "aurelia-dependency-injection",
          "aurelia-event-aggregator",
          "aurelia-fetch-client",
          "aurelia-history",
          "aurelia-history-browser",
          "aurelia-loader",
          "aurelia-pal",
          "aurelia-logging",
          "aurelia-logging-console",
          "aurelia-metadata",
          "aurelia-pal",
          "aurelia-path",
          "aurelia-polyfills",
          "aurelia-route-recognizer",
          "aurelia-task-queue",
          "aurelia-templating",
          "aurelia-templating-binding",
          "aurelia-templating-resources",
          "aurelia-templating-router",
          {
            "name": "aurelia-testing",
            "env": "dev"
          },
          "text"
        ]
      },
      {
        "name": "some-other-bundle.js",
        "dependencies": [
          "jquery",
          "some-thing"
        ]
      },
      {
        "name": "vendor-bundle.js",
        "prepend": [
          "node_modules/requirejs/requirejs.js"
        ]
      }
    ],

#4

Thanks, this is exactly the kind of info I meant. I tried to split it as above with a new bundle for external libraries, and a vendor bundle with the prepend section still there, but I kept on getting errors about not being able to find dependencies when loading the page, and if I moved other things around the external libraries bundle would usually be empty. You above example gives me hope to figure something out, thank you.