Skip to content

Commit 26d967e

Browse files
authored
perf: improve caching of packuments (#1642)
1 parent fcd5b7d commit 26d967e

File tree

3 files changed

+41
-45
lines changed

3 files changed

+41
-45
lines changed

app/composables/usePackageComparison.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export interface PackageComparisonData {
7070
*/
7171
export function usePackageComparison(packageNames: MaybeRefOrGetter<string[]>) {
7272
const { t } = useI18n()
73+
const { $npmRegistry } = useNuxtApp()
7374
const numberFormatter = useNumberFormatter()
7475
const compactNumberFormatter = useCompactNumberFormatter()
7576
const bytesFormatter = useBytesFormatter()
@@ -124,9 +125,7 @@ export function usePackageComparison(packageNames: MaybeRefOrGetter<string[]>) {
124125
namesToFetch.map(async (name): Promise<PackageComparisonData | null> => {
125126
try {
126127
// Fetch basic package info first (required)
127-
const pkgData = await $fetch<Packument>(
128-
`https://registry.npmjs.org/${encodePackageName(name)}`,
129-
)
128+
const { data: pkgData } = await $npmRegistry<Packument>(`/${encodePackageName(name)}`)
130129

131130
const latestVersion = pkgData['dist-tags']?.latest
132131
if (!latestVersion) return null

server/utils/dependency-resolver.ts

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Packument, PackumentVersion, DependencyDepth } from '#shared/types'
22
import { mapWithConcurrency } from '#shared/utils/async'
3-
import { encodePackageName } from '#shared/utils/npm'
43
import { maxSatisfying } from 'semver'
54

65
/** Concurrency limit for fetching packuments during dependency resolution */
@@ -17,27 +16,20 @@ export const TARGET_PLATFORM = {
1716
}
1817

1918
/**
20-
* Fetch packument with caching (returns null on error for tree traversal)
19+
* Fetch packument with caching (returns null on error for tree traversal).
20+
* Delegates to fetchNpmPackage() to share a single cache for all packument fetches.
2121
*/
22-
export const fetchPackument = defineCachedFunction(
23-
async (name: string): Promise<Packument | null> => {
24-
try {
25-
return await $fetch<Packument>(`https://registry.npmjs.org/${encodePackageName(name)}`)
26-
} catch (error) {
27-
if (import.meta.dev) {
28-
// oxlint-disable-next-line no-console -- log npm registry failures for debugging
29-
console.warn(`[dep-resolver] Failed to fetch packument for ${name}:`, error)
30-
}
31-
return null
22+
async function fetchPackument(name: string): Promise<Packument | null> {
23+
try {
24+
return await fetchNpmPackage(name)
25+
} catch (error) {
26+
if (import.meta.dev) {
27+
// oxlint-disable-next-line no-console -- log npm registry failures for debugging
28+
console.warn(`[dep-resolver] Failed to fetch packument for ${name}:`, error)
3229
}
33-
},
34-
{
35-
maxAge: 60 * 60,
36-
swr: true,
37-
name: 'packument',
38-
getKey: (name: string) => name,
39-
},
40-
)
30+
return null
31+
}
32+
}
4133

4234
/**
4335
* Check if a package version matches the target platform.

test/nuxt/composables/use-package-comparison.spec.ts

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,26 @@ describe('usePackageComparison', () => {
4848

4949
describe('lastUpdated facet', () => {
5050
it('uses version-specific publish date, not time.modified', async () => {
51+
const registryData = {
52+
'name': 'test-package',
53+
'dist-tags': { latest: '2.0.0' },
54+
'time': {
55+
// This is the WRONG value - updated by metadata changes
56+
'modified': '2024-12-01T00:00:00.000Z',
57+
// This is the CORRECT value - actual publish date
58+
'2.0.0': '2024-06-15T00:00:00.000Z',
59+
},
60+
'license': 'MIT',
61+
'versions': {
62+
'2.0.0': { dist: { unpackedSize: 15000 } },
63+
},
64+
}
5165
vi.stubGlobal(
5266
'$fetch',
53-
vi.fn().mockImplementation((url: string) => {
54-
if (url.startsWith('https://registry.npmjs.org/')) {
55-
return Promise.resolve({
56-
'name': 'test-package',
57-
'dist-tags': { latest: '2.0.0' },
58-
'time': {
59-
// This is the WRONG value - updated by metadata changes
60-
'modified': '2024-12-01T00:00:00.000Z',
61-
// This is the CORRECT value - actual publish date
62-
'2.0.0': '2024-06-15T00:00:00.000Z',
63-
},
64-
'license': 'MIT',
65-
'versions': {
66-
'2.0.0': { dist: { unpackedSize: 15000 } },
67-
},
68-
})
67+
vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => {
68+
const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url
69+
if (fullUrl.startsWith('https://registry.npmjs.org/')) {
70+
return Promise.resolve(registryData)
6971
}
7072
return Promise.resolve(null)
7173
}),
@@ -93,8 +95,9 @@ describe('usePackageComparison', () => {
9395
it('stores version-specific time in metadata', async () => {
9496
vi.stubGlobal(
9597
'$fetch',
96-
vi.fn().mockImplementation((url: string) => {
97-
if (url.startsWith('https://registry.npmjs.org/')) {
98+
vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => {
99+
const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url
100+
if (fullUrl.startsWith('https://registry.npmjs.org/')) {
98101
return Promise.resolve({
99102
'name': 'test-package',
100103
'dist-tags': { latest: '1.0.0' },
@@ -128,8 +131,9 @@ describe('usePackageComparison', () => {
128131
it('marks packages not published in 2+ years as stale', async () => {
129132
vi.stubGlobal(
130133
'$fetch',
131-
vi.fn().mockImplementation((url: string) => {
132-
if (url.startsWith('https://registry.npmjs.org/')) {
134+
vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => {
135+
const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url
136+
if (fullUrl.startsWith('https://registry.npmjs.org/')) {
133137
return Promise.resolve({
134138
'name': 'old-package',
135139
'dist-tags': { latest: '1.0.0' },
@@ -159,8 +163,9 @@ describe('usePackageComparison', () => {
159163
it('marks recently published packages as neutral', async () => {
160164
vi.stubGlobal(
161165
'$fetch',
162-
vi.fn().mockImplementation((url: string) => {
163-
if (url.startsWith('https://registry.npmjs.org/')) {
166+
vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => {
167+
const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url
168+
if (fullUrl.startsWith('https://registry.npmjs.org/')) {
164169
return Promise.resolve({
165170
'name': 'fresh-package',
166171
'dist-tags': { latest: '1.0.0' },

0 commit comments

Comments
 (0)