test(client): build an asset import end to end and keep the resolver call name stable

This commit is contained in:
imccyu committed 2026-10-20 04:55:29 +08:00
1 parent d7191fafb6
commit 1823c6bd0e
2 files changed
+29 -4

No files matched your search

+4 -3
View File
@@ -516,10 +516,11 @@ const URL_SCHEME = /^[a-z][a-z\d+.-]*:/i
* Free identifier an asset reference compiles to before rendering; the CommonJS
* render turns each call into `require.asset(...)`, the module loader's
* synchronous asset resolver, which returns the reference unchanged unless its
* carrier maps it. The random part keeps plugin strings that happen to contain
* the fixed prefix out of that rewrite.
* carrier maps it. The fixed hexadecimal suffix keeps plugin strings that happen
* to contain the shorter prefix out of that rewrite, and, unlike a per-build
* value, keeps the source maps that carry the loaded module text byte-stable.
*/
const PACKAGE_ASSET_CALL = `__dshPackageAsset_${randomBytes(6).toString('hex')}`
const PACKAGE_ASSET_CALL = '__dshPackageAsset_5f8e2c1a9b7d'
/** Compile one asset reference into the resolver call. */
function packageAssetCall(reference: string): string {
+25 -1
View File
@@ -9,7 +9,7 @@ import { existsSync } from 'node:fs'
import { mkdir, mkdtemp, realpath, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { dirname, join } from 'node:path'
import type { UserConfig } from 'tsdown'
import { build, type TsdownBundle, type UserConfig } from 'tsdown'
import { afterEach, describe, expect, it } from 'vitest'
import { packageAssetRevision } from '../packages/client/modules/src/assets.ts'
import { clientBundle } from '../packages/client/tsdown.client.ts'
@@ -244,6 +244,30 @@ describe('client bundle package asset imports', () => {
expect(renderChunk('const a = 1;\n', {}, { format: 'cjs' })).toBeNull()
})
it('builds an asset import into require.asset and keeps plugin strings that share the prefix', async () => {
const root = await assetPackage({
'src/client/assets/whale.png': WHALE,
'lib/types/client/index.js': 'import whale from "./assets/whale.png"\nexport const url = whale\nexport const text = "__dshPackageAsset("\n',
})
const config = clientFaceConfigs(root).find(candidate => candidate.platform === 'browser')
if (config === undefined) throw new Error('browser config missing')
let builds: TsdownBundle[] = []
try {
builds = await build({
...config, cwd: root, config: false, tsconfig: false,
write: false, clean: false, exports: false, report: false, logLevel: 'silent',
})
const output = builds.flatMap(bundle => bundle.chunks).find(chunk => chunk.type === 'chunk' && chunk.fileName === 'client.js')
const code = output?.type === 'chunk' ? output.code : ''
expect(code).toContain(`require.asset(${JSON.stringify(WHALE_URL)})`)
expect(code).not.toContain('__dshPackageAsset_')
expect(code).toContain('"__dshPackageAsset("')
} finally {
for (const bundle of builds) await bundle[Symbol.asyncDispose]()
}
})
it('ignores imports and modules that are not supported assets', async () => {
const root = await assetPackage({ 'src/client/index.ts': '', 'src/client/assets/font.woff2': 'font' })
const { resolveId, load } = hooks(browserPlugins(root)('dsh-package-asset'))