How should Umbraco v9 handle runtime minification of App_Plugins? #10469
Replies: 7 comments 6 replies
-
Loading many small files vs fewer larger ones should probably be configurable in itself. Over HTTP2/3 browsers perform better with multiple smaller bundles, over HTTP1.1 fewer larger bundles are better. That's a great point about assetsService @Shazwazza An important question to ask then is not just what we want to load, but when do we need to actually load it. To my mind, the JS referenced in app-manifest is better if it's just a lightweight file that's then responsible for bootstrapping any other assets in the most efficient way for the user (ideally as they need them and only if they do) - this could be via the assetService or "native" dynamic import. To that end, I think the min.js approach would work well for me Presumably that has the added benefit that the min.js files are cached separately from the rest of the bundle? i.e. if another package is installed and the bundle(s) rebuilt, that doesn't actually affect my package's min.js file and the browser will load from its cache? If that's the case then I'd have thought the extra hit of fetching a few more files on the first backoffice load is far outweighed by the more efficient caching from that point on. In fact, if I think about it that way, why would we want to bundle/minify different packages JS together at all? Some packages are updated frequently, some are not and not everyone installs updates as frequently as they should. With that in mind wouldn't we want to only ever load the JS that has actually changed? |
Beta Was this translation helpful? Give feedback.
-
@JasonElkin I think that makes sense - there's definite benefits in shipping multiple smaller bundles compared to one large, catch-all bundle. It does shift the responsibility onto the developer to ensure they're providing minified/optimized bundles, but that's not an unfair expectation if that developer is also wanting to do things outside of the expected Umbraco patterns. I've tried building my bundle as I'm trying an approach with a separate loader referenced in the manifest, which then injects the script tag for the main bundle. Benefit of doing it this way is that I can then specify Would be interesting too to know what the new backoffice UI approach will be - I've had a poke around the repo, the source is all using JS modules, but that doesn't mean the backoffice necessarily does the same. Does make sense though to try to align approaches so that the package dev experience can be as pleasant as possible. |
Beta Was this translation helpful? Give feedback.
-
I think the main affect i would be looking for from a package development point of view is that the JS in the package is presented to the user as is. be that minified or not by the package dev. While there are lots of us with build processes and minifications (that we would probably like to keep) - there are also many property editor style packages where there is a couple of files added to the package.manifest and then sent over - i don't think we should be introducing a new set of build steps for people needing to develop a simple package like this. The consequences of packages effecting each other in the one large concatenated file could be reduced by only combining files from any given package manifest (e.g per package) but i don't think its a massive deal to have them all in one to be honest. |
Beta Was this translation helpful? Give feedback.
-
For the upcoming beta what I'll do is:
We can still implement other ideas (see above) if anyone thinks they are important. |
Beta Was this translation helpful? Give feedback.
-
Hey @Shazwazza, these changes sound perfect - a light touch for development is ideal. I like the idea of additional manifest options too, giving additional opt-in control means devs can chose to be a bit cleverer in how they provide their assets. I'd certainly be interested in lazy loading parts of Plumber (eg if users don't have access to the backoffice section, they don't need to load the JavaScript). I did try loading via the assets service, but would need to do it in the application boot pipeline, to make sure it runs before any views are rendered and potentially referencing yet-to-be loaded scripts. Hadn't got back around to trying that change, but wouldn't be necessary with these changes. |
Beta Was this translation helpful? Give feedback.
-
Here's the plan The latest (beta4) changes will be helpful to package devs but we should go a step further by allowing having the package.manifest dictate how a packages assets will be bundled.
I think this should cater for all cases. Thoughts? |
Beta Was this translation helpful? Give feedback.
-
Hi all, I've submitted a PR for this functionality here #10691 If anyone has time for feedback/testing that would be most appreciated! |
Beta Was this translation helpful? Give feedback.
-
Umbraco version
v9
Description
There have been some questions raised on Twitter about how v9 does runtime minification on JS/CSS files in App_Plugins. This is different to how v8 did it but that is for specific reasons. However, the settings implemented are naively configured based on past history and experience with how JS worked. In recent times, these settings do not work for some scenarios but the discussion should take this further by determining what should actually be done. I have listed a description and options below.
Debug mode
Debug mode is when the debug switch is configured in the config. This should never be used in production, only pre-prod/testing.
v8 Cache busting
The cache busting value was directly taken from ClientDependency.config file, it was a hard coded value and requires a developer to update this.
v8 Composite files
(Composite files mean files that are joined into 1 and processed - like minified and other processes)
in debug mode, v8 wouldn't do anything with the files in app_plugins, it would serve them as-is in separate files. It would also append the current cache buster value.
Problems would arise sometimes when a site was pushed to production with the debug flag set to false and then composite files were enabled since the files hadn't been previously tested with composite files.
No source maps are ever created in v8.
v9 Cache busting
Cache busting in v9 is controlled by an abstraction:
IRuntimeMinifier.CacheBuster
. This abstraction is implemented by Smidge. And this is determined by a few settings that Umbraco configures as seen here inSmidgeRuntimeMinifier.CreateJsBundle
. Umbraco sets the cache buster type to either:appsettings.Development.json
config file. You can set it like: "RuntimeMinification"/"cacheBuster" = "Timestamp". This will mean that your files are always cache busted on every refresh because the value is based on the current timestamp. NOTE: I realize on twitter I said this would be set if in Debug mode, but that is not the case, it's only set in "Development" mode when working with the source code. Developers should also use theappsettings.{Environment}.json
switch to customize their development experience by have Development specific config settings and in which case you should probably use the Timestamp setting.v9 Composite files
In v9, composite files for app_plugins are enabled all of the time. (NOTE: on twitter I said that it wouldn't minifiy in debug, but i was wrong). The settings for that are here.
In debug mode a file watcher is enabled which means that no matter what type of cache buster setting you use, changes to your app_plugins files should auto-cache bust.
Composite files are enabled in debug mode because Source Maps are created in v9 so it's still easy to debug and step through code even though composite files are enabled. This also mitigates the issues in v8 of devs not testing what happens to their files when composite files are enabled.
In v9, any
.min.js
or.min.css
files are not included in minification since it's assumed they are already minified. In this case, they are just added to the bundle as-is.Release mode
v8
composite files are enabled
v9
file watching is not enabled
What do we actually want?
Source maps have been raised as an issue on Twitter if folks are creating custom JS bundles with their own source maps and then having those included in the app_plugins bundle. In this case, the custom source maps won't work because the source map declaration will be embedded within the bundle and the declaration won't get used. I don't think it's (easily) possible to have a bundle of a bundle with nested source maps. In this case though, it would be worth testing that these custom bundles have the
.min.js
extension to tell Smidge to not JS process the file.Another alternative for folks that don't want any runtime minifier interaction is to just load in your scripts/css lazily in the back office using the umbraco
assetsService
and don't register them in the package.manifest.We could make Umbraco's bundler ignore certain files and have them loaded individually in the back office - like any
.min.js
files? But this may end up with all developers making .min.js files and then all app_plugins JS files are loaded individually, and in which case, we might as well remove composite file processing all together. This is another option... But this could lead to having tons of individual JS files loaded when the back office loads.The good news is that v9 is super flexible in how it handles this so we should be able to configure the right approach.
How can you help?
If you would like to suggest a change in behavior, please ensure you have read and understood the above and then leave your suggestions below :)
Beta Was this translation helpful? Give feedback.
All reactions