Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/danielroe/roe.dev. This is the code and content for my personal website, built in Nuxt. roe.dev
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336/** @vitest-environment node */
import { fileURLToPath } from 'node:url'import fsp from 'node:fs/promises'import { execSync } from 'node:child_process'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'import { globby } from 'globby'import { join } from 'pathe'
describe('project sizes', () => { const rootDir = fileURLToPath(new URL('../..', import.meta.url)) const publicDir = join(rootDir, '.output/public') const serverDir = join(rootDir, '.output/server')
const stats = { client: { totalBytes: 0, files: [] as string[] }, server: { totalBytes: 0, files: [] as string[] }, }
beforeAll(async () => { execSync('pnpm nuxt build', { cwd: rootDir, env: { ...process.env, NODE_ENV: 'production', DISABLE_PRERENDER: 'true' }, }) }, 120 * 1000)
afterAll(async () => { await fsp.writeFile( join(rootDir, '.output/test-stats.json'), JSON.stringify(stats, null, 2), ) })
it('default client bundle size', async () => { stats.client = await analyzeSizes('**/*.js', publicDir) expect .soft(roundToKilobytes(stats.client.totalBytes)) .toMatchInlineSnapshot(`"489k"`) expect.soft(stats.client.files.map(f => f.replace(/\..*\.js/, '.js').replace(/_scripts\/.*\.js/, '_scripts/script.js')).sort()) .toMatchInlineSnapshot(` [ "_nuxt/CalSchedule.js", "_nuxt/ProseA.js", "_nuxt/ProseBlockquote.js", "_nuxt/ProseCode.js", "_nuxt/ProseEm.js", "_nuxt/ProseH1.js", "_nuxt/ProseH2.js", "_nuxt/ProseH3.js", "_nuxt/ProseH4.js", "_nuxt/ProseH5.js", "_nuxt/ProseH6.js", "_nuxt/ProseHr.js", "_nuxt/ProseImg.js", "_nuxt/ProseLi.js", "_nuxt/ProseOl.js", "_nuxt/ProseP.js", "_nuxt/ProsePre.js", "_nuxt/ProseScript.js", "_nuxt/ProseStrong.js", "_nuxt/ProseTable.js", "_nuxt/ProseTbody.js", "_nuxt/ProseTd.js", "_nuxt/ProseTh.js", "_nuxt/ProseThead.js", "_nuxt/ProseTr.js", "_nuxt/ProseUl.js", "_nuxt/SocialPost.js", "_nuxt/entry.js", "_nuxt/sqlite3-opfs-async-proxy-MFda9Fch.js", "_nuxt/sqlite3-worker1-bundler-friendly-DZqsmh1G.js", "_scripts/script.js", ] `) })
it('default server bundle size', async () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) expect .soft(roundToKilobytes(stats.server.totalBytes)) .toMatchInlineSnapshot(`"995k"`)
const modules = await analyzeSizes('node_modules/**/*', serverDir) expect .soft(roundToKilobytes(modules.totalBytes)) .toMatchInlineSnapshot(`"11449k"`)
const packages = modules.files .filter(m => m.endsWith('package.json')) .map(m => m.replace('/package.json', '').replace('node_modules/', '')) .sort() expect.soft(packages).toMatchInlineSnapshot(` [ "@atproto/api", "@atproto/common-web", "@atproto/lexicon", "@atproto/syntax", "@atproto/xrpc", "@babel/parser", "@jridgewell/sourcemap-codec", "@sanity/client", "@sanity/eventsource", "@sanity/webhook", "@shikijs/core", "@shikijs/engine-javascript", "@shikijs/engine-oniguruma", "@shikijs/langs", "@shikijs/themes", "@shikijs/transformers", "@shikijs/types", "@shikijs/vscode-textmate", "@sindresorhus/is", "@ungap/structured-clone", "@unocss/core", "@unocss/extractor-arbitrary-variants", "@unocss/preset-mini", "@unocss/preset-wind3", "@unocss/rule-utils", "@vue/compiler-core", "@vue/compiler-core/node_modules/entities", "@vue/compiler-dom", "@vue/compiler-ssr", "@vue/reactivity", "@vue/runtime-core", "@vue/runtime-dom", "@vue/server-renderer", "@vue/shared", "await-lock", "bail", "better-sqlite3", "bindings", "ccount", "char-regex", "character-entities", "character-entities-html4", "character-entities-legacy", "character-reference-invalid", "comma-separated-tokens", "consola", "debug", "decode-named-character-reference", "decompress-response", "detab", "devalue", "devlop", "emojilib", "emoticon", "entities", "entities/dist/esm", "escape-string-regexp", "estree-walker", "events-to-async", "events-to-async/module", "eventsource", "extend", "feed", "file-uri-to-path", "flat", "follow-redirects", "get-it", "github-slugger", "graphemer", "has-flag", "hast-util-embedded", "hast-util-format", "hast-util-from-parse5", "hast-util-from-parse5/node_modules/property-information", "hast-util-has-property", "hast-util-is-body-ok-link", "hast-util-is-element", "hast-util-minify-whitespace", "hast-util-parse-selector", "hast-util-phrasing", "hast-util-raw", "hast-util-to-html", "hast-util-to-html/node_modules/property-information", "hast-util-to-mdast", "hast-util-to-parse5", "hast-util-to-parse5/node_modules/property-information", "hast-util-to-string", "hast-util-to-text", "hast-util-whitespace", "hastscript", "hastscript/node_modules/property-information", "hookable", "html-void-elements", "html-whitespace-sensitive-tag-names", "image-meta", "inherits", "is-absolute-url", "is-alphabetical", "is-alphanumerical", "is-decimal", "is-hexadecimal", "is-plain-obj", "is-retry-allowed", "iso-datestring-validator", "longest-streak", "magic-string", "markdown-table", "mdast-util-find-and-replace", "mdast-util-from-markdown", "mdast-util-gfm", "mdast-util-gfm-autolink-literal", "mdast-util-gfm-footnote", "mdast-util-gfm-strikethrough", "mdast-util-gfm-table", "mdast-util-gfm-task-list-item", "mdast-util-phrasing", "mdast-util-to-hast", "mdast-util-to-markdown", "mdast-util-to-string", "micromark", "micromark-core-commonmark", "micromark-extension-gfm", "micromark-extension-gfm-autolink-literal", "micromark-extension-gfm-footnote", "micromark-extension-gfm-strikethrough", "micromark-extension-gfm-table", "micromark-extension-gfm-tagfilter", "micromark-extension-gfm-task-list-item", "micromark-factory-destination", "micromark-factory-label", "micromark-factory-space", "micromark-factory-title", "micromark-factory-whitespace", "micromark-util-character", "micromark-util-chunked", "micromark-util-classify-character", "micromark-util-combine-extensions", "micromark-util-decode-numeric-character-reference", "micromark-util-decode-string", "micromark-util-encode", "micromark-util-html-tag-name", "micromark-util-normalize-identifier", "micromark-util-resolve-all", "micromark-util-sanitize-uri", "micromark-util-subtokenize", "mimic-response", "ms", "multiformats", "nanoid", "nanoid/url-alphabet", "node-emoji", "oniguruma-parser", "oniguruma-to-es", "oniguruma-to-es/dist/esm", "parse-entities", "parse5", "parse5/node_modules/entities", "parse5/node_modules/entities/dist/esm", "perfect-debounce", "property-information", "readable-stream", "regex", "regex-recursion", "regex-utilities", "rehype-external-links", "rehype-minify-whitespace", "rehype-raw", "rehype-sort-attribute-values", "rehype-sort-attributes", "remark-emoji", "remark-gfm", "remark-mdc", "remark-parse", "remark-rehype", "remark-stringify", "rxjs", "safe-buffer", "sax", "scule", "shiki", "skin-tone", "source-map-js", "space-separated-tokens", "string_decoder", "stringify-entities", "supports-color", "through2", "tlds", "trim-lines", "trim-trailing-lines", "trough", "ts-custom-error", "tunnel-agent", "ufo", "uint8arrays", "unhead", "unicode-emoji-modifier-base", "unified", "unist-util-find-after", "unist-util-is", "unist-util-position", "unist-util-stringify-position", "unist-util-visit", "unist-util-visit-parents", "util-deprecate", "vfile", "vfile-location", "vfile-message", "vue", "vue-bundle-renderer", "web-namespaces", "xml-js", "yaml", "zod", "zod/dist/cjs", "zwitch", ] `) })})
async function analyzeSizes (pattern: string | string[], rootDir: string) { const files: string[] = await globby(pattern, { cwd: rootDir }) let totalBytes = 0 for (const file of files) { 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 } } return { files, totalBytes }}
function roundToKilobytes (bytes: number) { return (bytes / 1024).toFixed(bytes > 100 * 1024 ? 0 : 1) + 'k'}