perf: code-split the application (#2456)

Code-split the application (but without lazy loading, aka dynamic imports aka async modules, so all the assets are loaded on app load, not when requested: this is needed for ensuring an smooth experience over slow networks)

Lighthouse performance score went from 66 to 77

There's still a lot of work to do, but this is a good start.

Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
This commit is contained in:
Fernando Fernández 2024-09-09 19:59:46 +02:00 committed by GitHub
parent ef55e263f5
commit cf82a146ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 52 additions and 27 deletions

View File

@ -10,10 +10,10 @@
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>Jellyfin Vue</title>
<script type="module" src="src/splashscreen.ts"></script>
<script type="module" src="src/splashscreen.ts" fetchpriority="high"></script>
<script type="module" src="src/main.ts"></script>
</head>
<body class="j-splash">
<img src="./icon.svg" alt="Jellyfin Logo" loading="eager" decoding="async">
<img src="./icon.svg" alt="Jellyfin Logo" loading="eager" decoding="sync">
</body>
</html>

View File

@ -0,0 +1,44 @@
import type { Plugin } from 'vite';
/**
* Creates the Rollup's chunking strategy of the application (for code-splitting)
*/
export function JellyfinVueChunking(): Plugin {
return {
name: 'Jellyfin_Vue:chunking',
config: () => ({
build: {
rollupOptions: {
output: {
/**
* This is the first thing that should be debugged when there are issues
* withe the bundle. Check these issues:
* - https://github.com/vitejs/vite/issues/5142
* - https://github.com/evanw/esbuild/issues/399
* - https://github.com/rollup/rollup/issues/3888
*/
manualChunks(id) {
const match = /node_modules\/([^/]+)/.exec(id)?.[1];
if (id.includes('virtual:locales') || ((id.includes('vuetify') || id.includes('date-fns')) && id.includes('locale'))) {
return 'localization/meta';
}
if (id.includes('@intlify/unplugin-vue-i18n/messages')
) {
return 'localization/messages';
}
/**
* Split each vendor in its own chunk
*/
if (match) {
return `vendor/${match.replace('@', '')}`;
}
}
}
}
}
})
};
}

View File

@ -6,7 +6,7 @@
src="./icon.svg"
alt="Jellyfin Logo"
loading="eager"
decoding="async">
decoding="sync">
<JTransition
name="slide-y-reverse"
appear>

View File

@ -18,6 +18,7 @@ import { defineConfig } from 'vite';
import { entrypoints, localeFilesFolder, srcRoot } from './scripts/paths';
import virtualModules from './scripts/virtual-modules';
import { JellyfinVueAnalysis } from './scripts/plugins/analysis';
import { JellyfinVueChunking } from './scripts/plugins/chunking';
export default defineConfig({
appType: 'spa',
@ -25,6 +26,7 @@ export default defineConfig({
cacheDir: '../node_modules/.cache/vite',
plugins: [
JellyfinVueAnalysis(),
JellyfinVueChunking(),
Virtual(virtualModules),
VueRouter({
dts: './types/global/routes.d.ts',
@ -64,7 +66,8 @@ export default defineConfig({
compositionOnly: true,
fullInstall: false,
forceStringify: true,
include: localeFilesFolder
include: localeFilesFolder,
dropMessageCompiler: true
}),
UnoCSS(),
VueDevTools()
@ -77,7 +80,6 @@ export default defineConfig({
/**
* Disable chunk size warnings
*/
chunkSizeWarningLimit: Number.NaN,
cssCodeSplit: true,
cssMinify: 'lightningcss',
modulePreload: false,
@ -89,28 +91,7 @@ export default defineConfig({
index: entrypoints.index
},
output: {
chunkFileNames: (chunkInfo) => {
/**
* This is the default value: https://rollupjs.org/configuration-options/#output-chunkfilenames
*/
return chunkInfo.name === 'validation' ? 'assets/common-[hash].js' : '[name]-[hash].js';
},
validate: true,
/**
* This is the first thing that should be debugged when there are issues
* withe the bundle. Check these issues:
* - https://github.com/vitejs/vite/issues/5142
* - https://github.com/evanw/esbuild/issues/399
* - https://github.com/rollup/rollup/issues/3888
*/
manualChunks(id) {
if (
id.includes('virtual:locales')
|| id.includes('@intlify/unplugin-vue-i18n/messages')
) {
return 'assets/locales';
}
}
validate: true
}
}
},