Builtin Bundler - Bootstrap hamburger

So still working on converting to the new bundler and running into I think my last issue where my bootstrap (4.2.1) navbar isn’t toggling correctly. (Everything works fine in webpack version of app)

Now it changes back and forth from desktop to mobile breakpoints just fine.

When in mobile breakpoint the hamburger itself opens, but it will not close.
As well one of the menu items, which is a dropdown does not toggle open in either breakpoint.

I have used the prepend in aurelia.json as show with the tempusdominus-bootstrap-4 example in the docs and have added the main import and app.html require as shown below.
Everything I have found seems to indicate that this generally happens when not all files are included, most likely the bootstrap.js file which as the example noted above has been added in prepend.

I am getting no compile errors, or browser console messages related to this.
Is there something else I am missing here?

Thanks!

aurelia.json

"prepend": [
                    "node_modules/bluebird/js/browser/bluebird.core.js",
                    {
                        "path": "node_modules/aurelia-cli/lib/resources/scripts/configure-bluebird-no-long-stacktraces.js",
                        "env": "stage & prod"
                    },
                    {
                        "path": "node_modules/aurelia-cli/lib/resources/scripts/configure-bluebird.js",
                        "env": "dev"
                    },
                    "node_modules/jquery/dist/jquery.min.js",
                    "node_modules/popper.js/dist/umd/popper.min.js",
                    "node_modules/bootstrap/dist/js/bootstrap.min.js",

                    "node_modules/@babel/polyfill/browser.js",
                    "node_modules/alameda/alameda.js"
                ],

main.ts

import 'bootstrap';

app.html

    <require from="bootstrap/css/bootstrap.min.css"></require>

You misunderstood prepend, it’s for legacy libs that doesn’t any module format. When you have bootstrap in prepend, your code import 'bootstrap' will cause bootstrap (plus jquery and popper) being bundled again as AMD modules. You end up with duplicated js (one in prepend before alameda, another packed after alameda). You probably have two copies of bootstrap trying to control same DOM.

bootstrap v4 supports AMD format, you don’t have to add jquery/popper/bootstrap to prepend list.
The reason you would want them in prepend list is to support tempusdominus-bootstrap-4 which is in legacy format. You should have jquery/popper/bootstrap/moment/tempusdominus-bootstrap-4 in prepend list for the date picker to work.

Again, once you have them in prepend, they works in legacy mode (creating global variables). Do not do any import 'bootstrap'; or import $ from 'jquery'; in your code. Just use $, jQuery, moment as global variables.

To prevent eslint complaining about those globals, add this to .eslintrc.json.

{
  //...
  "globals": {
    "$": true,
    "jQuery": true,
    "moment": true
  }
}
1 Like

@huochunpeng Thanks for straightening me out. By removing either one I was able to get the bootstrap behaviors working again.

I went ahead and used the loader pattern as I have nothing else using jquery/popper.

I will have to make sure if I end up using a non-module supported addin that uses jquery to remember to remove that from main.ts

Just as an aside I was noticing that my bundle sizes were much larger then the webpack versions. I just checked again after making that change, and with the project built with max minimization selected its much closer, but still half a meg larger. Would know if that was still being optimized?

1 Like

In dev env, aurelia-testing is bundled, try comparing the prod env.

Webpack bundle files should be smaller due to tree-shake, it depends on how many 3rd party libs you use, and how much you actually exercise them.

1 Like

BTW you can remove bluebird (the first 3 items in prepend), because babel polyfill (in your prepend list too) already provided a promise polyfill.

1 Like

I was comparing size for both versions of the bundler processed for ‘prod’, so apples to apples as there are no changes to the app other then to get it to work with the builtin bundler.

‘bluebird’ is all boilerplate code straight from ‘au new’.

Half a mega is a lot. Thanks for the information, I will have a look into the matter deeper when I got time. It might have something to do with the AMD module format wrapper, which is an overhead for every single module. Webpack doesn’t need to have similar overhead because it doesn’t support dynamic module loading. Also webpack’s tree shaking naturally reduces the final bundle size.

AMD dynamic loading opens up lots of opportunities. But in reality, 90% of the users do not use dynamic loading at runtime.

1 Like

It’s not needed anymore. I will raise a PR to remove it from the default setup.

1 Like

@huochunpeng Thanks for the additional information.

I am loader ignorant in general, so a quick question that comes to mind is: Does that mean the builtin bundler supports loading modules at runtime as it uses AMD, instead of having to be done statically at compile time like webpack? Say for a CMS system where components can be added/removed from the shell by user interaction?

Yes, you can leave a hole in the tracing process, so some module has to be supplied at runtime.

https://aurelia.io/docs/cli/cli-bundler/advanced#onrequiringmodule

1 Like

@huochunpeng Would there be a flag I can set when using ‘au build —env prod’ to see what files the bundler is including?

You can use --debug with build or run in any env. The debug mode only affects console log, there is no change in contents of the bundle files.

Ok, just ran build using --debug and I am not seeing any duplicates from a visual scan of the output. So it is still possibly the wrapper adding the extra bulk to the final bundle sizes.