Open jamesrwelch opened 1 year ago
In short: Reducing bundle size via lazy loading will require a restructuring of the feature modules in the project.
The idea is to group a features logic and routes into a module so that it may be lazy loaded only when the route gets hit. The process for one such feature module would look something like:
/admin/*
requests and use the loadChildren
property of route to only then dynamically load the AdminModule. You can find an example of this code in the ui-router link below. Additionally, lazy loading ag-grid and jodit would likely significantly reduce bundle size as they are the two largest packages that we currently use and are recommended starting places. Not the least of which because it might be easier to untangle their use from the rest of the src than it will be for our custom modules.
Note that we use the ui-router in mdm-ui rather than the standard angular router. Instructions for how lazy loading works in the ui-router can be found here: https://ui-router.github.io/guide/lazyloading#angular
The angular docs also have some good information re. lazy loading: https://angular.io/guide/lazy-loading-ngmodules
Finally, an interim step has been taken to use ag-grid modules instead of packages. The approach used is described in detail here: https://blog.ag-grid.com/minimising-bundle-size/. Unfortunately, we have not seen any real reduction in bundle size likely due to the fact that the community package is quite sparse to begin with so moving to modules doesn't save us much. The effect would be more noticeable if we were instead using the enterprise addition which comes loaded with many more features.
I have also been investigating the current bundle sizes based on what @abwilson23 has explained to me. Running the branch based on PR #800 I've generated this source map view (click to expand):
And created a table of these packages ordered by file size (descending):
From this output, here are some observations I made:
The following packages are pulled in:
jquery
backbone
underscore
lodash
Although our code does not use these, jquery
and backbone
seem to be dependencies of jointjs
which is used by the diagram components. (underscore
is a dependency of backbone
). It should be tested if these really could be removed to reduce size.
lodash
is a large library of functions but I've only found usage for 3 of them in the repo, yet importing the entire library is wasteful. My suggestions are to either:
lodash
completely and rewrite the code that uses those 3 functions with equivalents, orThe two largest libraries used are ag-grid-community
and jodit
(with jodit-angular
):
ag-grid-community
is actually the minimal set of packages needed to use the free version of the grid component, so this cannot really go any smaller. @abwilson23 has tried though by upgrading and using correct module imports in PR #800.jodit
seems to be a very large HTML editor in comparison to some others. It might be worth investigating some alternative controls which do the same job e.g. TinyMCEIn both cases, @abwilson23 has suggested somehow restructuring our Angular modules to split these two areas off so they are lazy loaded when those pages are required. I agree with this - editing functionality should ideally only be pulled in when necessary (for instance, users with the "reader" privilege will never require the editor controls).
brace
and code-mirror
seem to both be packages for using syntax highlighted editor controls. brace
is used for the Rule Representations and is definitely needed to support some of the more obscure language syntaxes. But perhaps code-mirror
could be replaced to just use brace
instead - the only occurance I've found of it is in the diagrams components related to Data Class Components, but I cannot get a test case available to see that working in the UI.
Another possible duplicate is ui-router
, which takes up 124KB (1.7%) of the bundle size. Since Angular already provides a router package, would ui-router
actually be necessary (apart from the sheer legacy of code)?
I agree with @abwilson23's analysis that, ultimately, a re-architecture of the the app modules which better support routed lazy-loading will be best long term. The above suggestions are only short-term measures which may hopefully reduce some of the total bundle size assuming there is only one large bundle to download.
Summarising a comment from Zulip: If we can remove unnecessary or duplicate packages for now, that would be great. It'll help reduce our package size a bit, make the code easier to maintain and reduce our susceptibility to security issues. Replacing components like Jodit will require a bit more thought, and probably a lot of code re-writing, so I'm inclined to leave those for now unless we can see a really persuasive argument. And correct modularisation is definitely in the long-term basket - I think there would be other improvements we'd want to make at the same time as a large-scale re-write.
Just a note re. @pjmonks recommendations re. Lodash: I successfully tested switching to using lodash-es
which allowed for individual function level imports, however there are several other packages that import lodash
in full and so the optimization gains are not realized. In particular, there are many build warnings from angular about our use of CommonJS modules vs ECMAScript modules which are impacting our bundling optimization.
An investigation yielded this: moving away from CommonJS modules (the node default) and towards ECMAScript modules (a more modern alternative format) will allow for significantly better tree shaking to be performed because ECMAScript modules are statically loaded vs CommonJS's dynamic loading.
Instructions on how to do that kind of thing are here: https://developapa.com/angular-lazy-load/