Closed thekid closed 3 years ago
This is how far we've come with this in our example project:
Next to the dependencies inside package.json, we now also have our bundles specified:
{
"dependencies": {
"dropzone": "^5.8",
"fomantic-ui": "^2.8",
"handlebars": "^4.7",
"jquery": "^3.6",
"simplemde": "^1.11",
"transliteration": "^2.1"
},
"bundles": {
"vendor": {
"jquery": "dist/jquery.min.js",
"fomantic-ui": "dist/semantic.min.js | dist/semantic.min.css",
"handlebars": "dist/handlebars.min.js",
"transliteration": "dist/browser/bundle.umd.min.js"
},
"editor": {
"dropzone": "dist/dropzone.min.js",
"simplemde": "dist/simplemde.min.js | dist/simplemde.min.css"
}
}
}
The following makes our bundler run every time composer update
is executed:
diff --git a/composer.json b/composer.json
index 336fa6a..fdfd4fc 100755
--- a/composer.json
+++ b/composer.json
@@ -13,7 +13,7 @@
"xp-forge/web-auth": "^2.2",
"xp-forge/rest-api": "^3.0",
"xp-forge/neo4j": "^1.0",
- "xp-forge/frontend": "^2.0",
+ "xp-forge/frontend": "dev-feature/bundler as 2.1.0",
"xp-forge/handlebars-templates": "^0.5",
"xp-forge/markdown": "^6.0",
"xp-forge/inject": "^5.0",
@@ -26,6 +26,7 @@
},
"scripts": {
+ "post-update-cmd": "xp bundle src/main/webapp/static",
"dev": "xp -supervise web -m develop -c src/main/etc/dev -a 0.0.0.0:80 com.enbw.skills.App",
"serve": "xp -supervise web -c src/main/etc/dev -a 0.0.0.0:80 com.enbw.skills.App"
}
We can now load our bundles instead of referring to them on a CDN. Note: We load editor.css on every page because we don't have an overrideable section like for scripts where each page can "extend" the layout, this would be a bigger diff
diff --git a/src/main/handlebars/edit.handlebars b/src/main/handlebars/edit.handlebars
index 4314582..1190a8d 100755
--- a/src/main/handlebars/edit.handlebars
+++ b/src/main/handlebars/edit.handlebars
@@ -90,7 +90,7 @@
<br clear="all"/>
{{/inline}}
{{#*inline "script"}}
- <script src="https://cdn.jsdelivr.net/npm/dropzone@5.8.1/dist/dropzone.min.js"></script>
+ <script src="/static/editor.js"></script>
<script type="text/javascript">
let _debounce = null;
let editor;
diff --git a/src/main/handlebars/layout.handlebars b/src/main/handlebars/layout.handlebars
index de63f89..cbf3e30 100755
--- a/src/main/handlebars/layout.handlebars
+++ b/src/main/handlebars/layout.handlebars
@@ -5,8 +5,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="msapplication-config" content="none"/>
<title>{{> title}} - Skills</title>
- <link href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css" rel="stylesheet">
- <link href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.7/dist/semantic.min.css" rel="stylesheet">
+ <link rel="preload" href="/static/themes/default/assets/fonts/icons.woff2" as="font" type="font/woff2" crossorigin>
+ <link href="/static/vendor.css" rel="stylesheet">
+ <link href="/static/editor.css" rel="stylesheet">
<style type="text/css">
nav a.active {
background-color: #3e2765 !important;
@@ -343,11 +344,7 @@
<small><a href="https://ec.europa.eu/esco/portal">ESCO</a></small>
</main>
- <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.7/dist/semantic.min.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/handlebars@v4.7.6/dist/handlebars.js"></script>
- <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
-
+ <script src="/static/vendor.js"></script>
<script type="text/javascript">
function use($selector, language) {
$selector.classList.add('loading');
However, we're still missing fingerprinting - see the discussion in https://github.com/xp-forge/frontend/issues/11#issuecomment-803981739 and https://github.com/xp-forge/frontend/issues/11#issuecomment-805078527
🐛 CSS dependencies end up in the wrong path:
-src/main/webapp/static/npm/fomantic-ui@2.8.7/dist/themes
+src/main/webapp/static/themes
Not realized in this pull request:
By using the abbreviated meta data format, we save around 10 MB of memory and also a couple of hundred milliseconds execution time!
-Bundle operations: 2 bundle(s) created in 3.400 seconds using 19244.68 kB memory
+Bundle operations: 2 bundle(s) created in 3.114 seconds using 9165.90 kB memory
See https://blog.packagecloud.io/eng/2018/01/24/npm-registry-internals/ and https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-metadata-format
By using the JSDelivr API, we can improve even further:
-Bundle operations: 2 bundle(s) created in 3.114 seconds using 9165.90 kB memory
+Bundle operations: 2 bundle(s) created in 2.653 seconds using 7096.74 kB memory
We could also leave up resolving the package to JSDelivr, see https://github.com/jsdelivr/data.jsdelivr.com#resolve-a-version-range. However, using this even more streamlined service doesn't affect performance noticeably while at the same time requring a second request for looking up available versions.
Compressing bundles with gzip or brotli
This would have a significant performance effect:
$ ls -al src/main/webapp/static/vendor.*
-rwxr-xr-x 1 timmf timmf 1362383 Mar 27 14:58 src/main/webapp/static/vendor.css
-rwxr-xr-x 1 timmf timmf 815049 Mar 27 14:58 src/main/webapp/static/vendor.js
$ gzip src/main/webapp/static/vendor.*
$ ls -al src/main/webapp/static/vendor.*
-rwxr-xr-x 1 timmf timmf 161814 Mar 27 14:58 src/main/webapp/static/vendor.css.gz
-rwxr-xr-x 1 timmf timmf 237002 Mar 27 14:58 src/main/webapp/static/vendor.js.gz
...giving us a near-perfect Lighthouse score:
See issue #11
Usage
This is the command usage:
Run
Here's an example run (inside Composer) which creates two bundles (after updating some PHP packages):
The 3.5 seconds is only for bundling, Composer adds another 7 seconds to the entire run