Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ jobs:
- run: pnpm build
- run: pnpm vitest --coverage
- run: pnpm tsc --noEmit
- name: Run benchmarks
if: matrix.os == 'ubuntu-latest'
uses: CodSpeedHQ/action@v3
with:
run: pnpm bench
- uses: codecov/codecov-action@v5
151 changes: 151 additions & 0 deletions benchmark/fixtures/large-vite-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
{
"entry-client.ts": {
"file": "assets/entry-client.js",
"src": "entry-client.ts",
"isEntry": true,
"imports": [
"_vendor.js"
],
"css": ["assets/main.css", "assets/components.css"],
"dynamicImports": [
"pages/home.vue",
"pages/about.vue",
"pages/contact.vue",
"pages/blog.vue",
"pages/profile.vue"
],
"assets": [
"assets/logo.svg",
"assets/banner.jpg"
]
},
"_vendor.js": {
"file": "assets/vendor.js"
},
"pages/home.vue": {
"file": "assets/home.js",
"src": "pages/home.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js",
"entry-client.ts"
],
"css": [
"assets/home.css"
],
"assets": [
"assets/hero-bg.jpg"
]
},
"pages/about.vue": {
"file": "assets/about.js",
"src": "pages/about.vue",
"isDynamicEntry": true,
"imports": [
"entry-client.ts"
],
"dynamicImports": [
"components/Timeline.vue",
"components/TeamMember.vue"
],
"css": [
"assets/about.css"
]
},
"pages/contact.vue": {
"file": "assets/contact.js",
"src": "pages/contact.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js",
"entry-client.ts"
],
"css": [
"assets/contact.css",
"assets/forms.css"
]
},
"pages/blog.vue": {
"file": "assets/blog.js",
"src": "pages/blog.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js"
],
"dynamicImports": [
"components/BlogPost.vue",
"components/Pagination.vue",
"components/SearchBox.vue"
],
"css": [
"assets/blog.css"
]
},
"pages/profile.vue": {
"file": "assets/profile.js",
"src": "pages/profile.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js",
"entry-client.ts"
],
"css": [
"assets/profile.css"
]
},
"components/Timeline.vue": {
"file": "assets/timeline.js",
"src": "components/Timeline.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js"
],
"css": [
"assets/timeline.css"
]
},
"components/TeamMember.vue": {
"file": "assets/team-member.js",
"src": "components/TeamMember.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js"
],
"css": [
"assets/team-member.css"
]
},
"components/BlogPost.vue": {
"file": "assets/blog-post.js",
"src": "components/BlogPost.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js"
],
"css": [
"assets/blog-post.css"
]
},
"components/Pagination.vue": {
"file": "assets/pagination.js",
"src": "components/Pagination.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js"
],
"css": [
"assets/pagination.css"
]
},
"components/SearchBox.vue": {
"file": "assets/search-box.js",
"src": "components/SearchBox.vue",
"isDynamicEntry": true,
"imports": [
"_vendor.js"
],
"css": [
"assets/search-box.css"
]
}
}
84 changes: 84 additions & 0 deletions benchmark/fixtures/large-webpack-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"publicPath": "/_nuxt/",
"all": [
"runtime.js",
"commons/app.js",
"commons/vendor.js",
"commons/polyfills.js",
"app.css",
"app.js",
"pages/home.css",
"pages/home.js",
"pages/about.css",
"pages/about.js",
"pages/contact.css",
"pages/contact.js",
"pages/blog.css",
"pages/blog.js",
"pages/profile.css",
"pages/profile.js",
"components/timeline.css",
"components/timeline.js",
"components/team-member.css",
"components/team-member.js",
"components/blog-post.css",
"components/blog-post.js",
"components/pagination.css",
"components/pagination.js",
"components/search-box.css",
"components/search-box.js",
"assets/main.css",
"assets/forms.css",
"img/logo.svg",
"img/hero-bg.jpg",
"img/banner.jpg",
"fonts/inter.woff2",
"fonts/inter-bold.woff2"
],
"initial": [
"runtime.js",
"commons/polyfills.js",
"commons/vendor.js",
"commons/app.js",
"app.css",
"assets/main.css",
"app.js"
],
"async": [
"pages/home.css",
"pages/home.js",
"pages/about.css",
"pages/about.js",
"pages/contact.css",
"pages/contact.js",
"pages/blog.css",
"pages/blog.js",
"pages/profile.css",
"pages/profile.js",
"components/timeline.css",
"components/timeline.js",
"components/team-member.css",
"components/team-member.js",
"components/blog-post.css",
"components/blog-post.js",
"components/pagination.css",
"components/pagination.js",
"components/search-box.css",
"components/search-box.js",
"assets/forms.css"
],
"modules": {
"4d87aad8": [1, 6],
"630f1d84": [2, 6],
"56940b2e": [7, 8, 26, 28],
"ab12cd34": [9, 10, 16],
"ef56gh78": [11, 12, 27],
"ij90kl12": [13, 14],
"mn34op56": [15, 16],
"qr78st90": [17, 18],
"uv12wx34": [19, 20],
"yz56ab78": [21, 22],
"cd90ef12": [23, 24],
"gh34ij56": [25, 26]
}
}
143 changes: 143 additions & 0 deletions benchmark/utils.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { bench, describe } from 'vitest'
import { isJS, isCSS, getAsType, parseResource } from '../src/utils'
import { extname } from 'node:path'

// Sample file names for testing
const jsFiles = [
'app.js',
'vendor.mjs',
'chunk.cjs',
'module.js?v=123',
'script',
]

const cssFiles = [
'main.css',
'components.scss',
'styles.less',
'theme.stylus',
'layout.css?v=456',
]

const assetFiles = [
'logo.svg',
'banner.jpg',
'icon.png',
'font.woff2',
'video.mp4',
'audio.mp3',
'document.pdf',
]

const mixedFiles = [...jsFiles, ...cssFiles, ...assetFiles]

describe('File Type Detection Benchmarks', () => {
bench('isJS detection on JS files', () => {
for (const file of jsFiles) {
isJS(file)
}
})

bench('isJS detection on mixed files', () => {
for (const file of mixedFiles) {
isJS(file)
}
})

bench('isCSS detection on CSS files', () => {
for (const file of cssFiles) {
isCSS(file)
}
})

bench('isCSS detection on mixed files', () => {
for (const file of mixedFiles) {
isCSS(file)
}
})
})

describe('Asset Type Detection Benchmarks', () => {
bench('getAsType on mixed files', () => {
for (const file of mixedFiles) {
const base = file.split('?', 1)[0]
const ext = extname(base).slice(1)
getAsType(ext)
}
})

bench('getAsType on JS extensions', () => {
const extensions = ['js', 'mjs', 'cjs']
for (const ext of extensions) {
getAsType(ext)
}
})

bench('getAsType on CSS extensions', () => {
const extensions = ['css', 'scss', 'less', 'stylus']
for (const ext of extensions) {
getAsType(ext)
}
})
})

describe('Resource Parsing Benchmarks', () => {
bench('parseResource on JS files', () => {
for (const file of jsFiles) {
parseResource(file)
}
})

bench('parseResource on CSS files', () => {
for (const file of cssFiles) {
parseResource(file)
}
})

bench('parseResource on asset files', () => {
for (const file of assetFiles) {
parseResource(file)
}
})

bench('parseResource on mixed files', () => {
for (const file of mixedFiles) {
parseResource(file)
}
})

bench('parseResource on mixed files (1000 iterations)', () => {
for (let i = 0; i < 1000; i++) {
for (const file of mixedFiles) {
parseResource(file)
}
}
})
})

// Test with dynamically generated file names
describe('Dynamic File Generation Benchmarks', () => {
bench('parseResource on generated JS files', () => {
for (let i = 0; i < 100; i++) {
parseResource(`chunk-${i}.js`)
parseResource(`module-${i}.mjs`)
parseResource(`bundle-${i}.cjs`)
}
})

bench('parseResource on generated CSS files', () => {
for (let i = 0; i < 100; i++) {
parseResource(`styles-${i}.css`)
parseResource(`theme-${i}.scss`)
parseResource(`layout-${i}.less`)
}
})

bench('parseResource on generated assets', () => {
for (let i = 0; i < 100; i++) {
parseResource(`image-${i}.png`)
parseResource(`icon-${i}.svg`)
parseResource(`font-${i}.woff2`)
}
})
})
Loading
Loading