2022-10-19 15:29:01 +00:00
|
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import fsp from 'node:fs/promises'
|
2023-06-28 13:49:50 +00:00
|
|
|
import { beforeAll, describe, expect, it } from 'vitest'
|
2022-10-19 15:29:01 +00:00
|
|
|
import { execaCommand } from 'execa'
|
|
|
|
import { globby } from 'globby'
|
|
|
|
import { join } from 'pathe'
|
|
|
|
|
2023-06-07 20:07:58 +00:00
|
|
|
describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM_CI)('minimal nuxt application', () => {
|
2022-10-19 15:29:01 +00:00
|
|
|
const rootDir = fileURLToPath(new URL('./fixtures/minimal', import.meta.url))
|
|
|
|
|
|
|
|
beforeAll(async () => {
|
2023-06-28 13:49:50 +00:00
|
|
|
await Promise.all([
|
|
|
|
execaCommand(`pnpm nuxi build ${rootDir}`, { env: { EXTERNAL_VUE: 'false' } }),
|
|
|
|
execaCommand(`pnpm nuxi build ${rootDir}`, { env: { EXTERNAL_VUE: 'true' } })
|
|
|
|
])
|
2022-10-19 15:29:01 +00:00
|
|
|
}, 120 * 1000)
|
|
|
|
|
2023-06-28 13:49:50 +00:00
|
|
|
// Identical behaviour between inline/external vue options as this should only affect the server build
|
|
|
|
for (const outputDir of ['.output', '.output-inline']) {
|
|
|
|
it('default client bundle size', async () => {
|
|
|
|
const clientStats = await analyzeSizes('**/*.js', join(rootDir, outputDir, 'public'))
|
2023-07-31 12:22:42 +00:00
|
|
|
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot('"97.4k"')
|
2023-06-28 13:49:50 +00:00
|
|
|
expect(clientStats.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
|
|
|
[
|
|
|
|
"_nuxt/entry.js",
|
|
|
|
]
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
}
|
2022-10-19 15:29:01 +00:00
|
|
|
|
|
|
|
it('default server bundle size', async () => {
|
2023-06-28 13:49:50 +00:00
|
|
|
const serverDir = join(rootDir, '.output/server')
|
|
|
|
|
|
|
|
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
2023-07-30 21:36:11 +00:00
|
|
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"64.4k"')
|
2022-10-19 15:29:01 +00:00
|
|
|
|
|
|
|
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
2023-08-03 17:39:40 +00:00
|
|
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2346k"')
|
2022-10-19 15:29:01 +00:00
|
|
|
|
|
|
|
const packages = modules.files
|
|
|
|
.filter(m => m.endsWith('package.json'))
|
|
|
|
.map(m => m.replace('/package.json', '').replace('node_modules/', ''))
|
|
|
|
.sort()
|
|
|
|
expect(packages).toMatchInlineSnapshot(`
|
|
|
|
[
|
|
|
|
"@babel/parser",
|
2022-11-15 16:26:38 +00:00
|
|
|
"@unhead/dom",
|
2023-02-16 11:44:31 +00:00
|
|
|
"@unhead/shared",
|
2022-11-15 16:26:38 +00:00
|
|
|
"@unhead/ssr",
|
2022-10-19 15:29:01 +00:00
|
|
|
"@vue/compiler-core",
|
|
|
|
"@vue/compiler-dom",
|
|
|
|
"@vue/compiler-ssr",
|
|
|
|
"@vue/reactivity",
|
|
|
|
"@vue/runtime-core",
|
|
|
|
"@vue/runtime-dom",
|
|
|
|
"@vue/server-renderer",
|
|
|
|
"@vue/shared",
|
|
|
|
"cookie-es",
|
2023-06-22 09:38:26 +00:00
|
|
|
"debug",
|
2022-11-15 17:36:57 +00:00
|
|
|
"defu",
|
2022-10-19 15:29:01 +00:00
|
|
|
"destr",
|
2023-04-07 10:34:35 +00:00
|
|
|
"devalue",
|
2022-10-19 15:29:01 +00:00
|
|
|
"estree-walker",
|
|
|
|
"h3",
|
2023-06-22 09:38:26 +00:00
|
|
|
"has-flag",
|
2022-10-19 15:29:01 +00:00
|
|
|
"hookable",
|
2023-06-22 09:38:26 +00:00
|
|
|
"http-graceful-shutdown",
|
2023-02-09 06:02:07 +00:00
|
|
|
"iron-webcrypto",
|
2023-05-06 08:44:07 +00:00
|
|
|
"klona",
|
2023-06-22 09:38:26 +00:00
|
|
|
"ms",
|
2022-10-19 15:29:01 +00:00
|
|
|
"node-fetch-native",
|
2022-11-15 14:33:43 +00:00
|
|
|
"ofetch",
|
2022-10-19 15:29:01 +00:00
|
|
|
"ohash",
|
|
|
|
"pathe",
|
|
|
|
"radix3",
|
|
|
|
"scule",
|
2023-05-11 08:37:32 +00:00
|
|
|
"source-map-js",
|
2023-06-22 09:38:26 +00:00
|
|
|
"supports-color",
|
2022-10-19 15:29:01 +00:00
|
|
|
"ufo",
|
2023-02-07 10:00:24 +00:00
|
|
|
"uncrypto",
|
2022-10-19 15:29:01 +00:00
|
|
|
"unctx",
|
|
|
|
"unenv",
|
2023-02-16 11:44:31 +00:00
|
|
|
"unhead",
|
2022-10-19 15:29:01 +00:00
|
|
|
"unstorage",
|
|
|
|
"vue",
|
|
|
|
"vue-bundle-renderer",
|
|
|
|
]
|
|
|
|
`)
|
|
|
|
})
|
2023-06-28 13:49:50 +00:00
|
|
|
|
|
|
|
it('default server bundle size (inlined vue modules)', async () => {
|
|
|
|
const serverDir = join(rootDir, '.output-inline/server')
|
|
|
|
|
|
|
|
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
|
|
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"370k"')
|
|
|
|
|
|
|
|
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
2023-08-03 17:39:40 +00:00
|
|
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"608k"')
|
2023-06-28 13:49:50 +00:00
|
|
|
|
|
|
|
const packages = modules.files
|
|
|
|
.filter(m => m.endsWith('package.json'))
|
|
|
|
.map(m => m.replace('/package.json', '').replace('node_modules/', ''))
|
|
|
|
.sort()
|
|
|
|
expect(packages).toMatchInlineSnapshot(`
|
|
|
|
[
|
|
|
|
"@unhead/dom",
|
|
|
|
"@unhead/shared",
|
|
|
|
"@unhead/ssr",
|
|
|
|
"cookie-es",
|
|
|
|
"debug",
|
|
|
|
"defu",
|
|
|
|
"destr",
|
|
|
|
"devalue",
|
|
|
|
"h3",
|
|
|
|
"has-flag",
|
|
|
|
"hookable",
|
|
|
|
"http-graceful-shutdown",
|
|
|
|
"iron-webcrypto",
|
|
|
|
"klona",
|
|
|
|
"ms",
|
|
|
|
"node-fetch-native",
|
|
|
|
"ofetch",
|
|
|
|
"ohash",
|
|
|
|
"pathe",
|
|
|
|
"radix3",
|
|
|
|
"scule",
|
|
|
|
"supports-color",
|
|
|
|
"ufo",
|
|
|
|
"uncrypto",
|
|
|
|
"unctx",
|
|
|
|
"unenv",
|
|
|
|
"unhead",
|
|
|
|
"unstorage",
|
|
|
|
]
|
|
|
|
`)
|
|
|
|
})
|
2022-10-19 15:29:01 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
async function analyzeSizes (pattern: string | string[], rootDir: string) {
|
|
|
|
const files: string[] = await globby(pattern, { cwd: rootDir })
|
|
|
|
let totalBytes = 0
|
|
|
|
for (const file of files) {
|
2023-01-20 16:17:31 +00:00
|
|
|
const path = join(rootDir, file)
|
|
|
|
const isSymlink = (await fsp.lstat(path).catch(() => null))?.isSymbolicLink()
|
|
|
|
|
|
|
|
if (!isSymlink) {
|
|
|
|
const bytes = Buffer.byteLength(await fsp.readFile(path))
|
|
|
|
totalBytes += bytes
|
|
|
|
}
|
2022-10-19 15:29:01 +00:00
|
|
|
}
|
|
|
|
return { files, totalBytes }
|
|
|
|
}
|
2023-04-04 12:34:29 +00:00
|
|
|
|
|
|
|
function roundToKilobytes (bytes: number) {
|
2023-04-12 08:42:45 +00:00
|
|
|
return (bytes / 1024).toFixed(bytes > (100 * 1024) ? 0 : 1) + 'k'
|
2023-04-04 12:34:29 +00:00
|
|
|
}
|