|
@@ -1,13 +1,30 @@
|
|
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
|
|
|
+import { createRequire } from 'node:module'
|
|
|
import { tmpdir } from 'node:os'
|
|
import { tmpdir } from 'node:os'
|
|
|
import { dirname, join, resolve } from 'node:path'
|
|
import { dirname, join, resolve } from 'node:path'
|
|
|
-import { afterEach, describe, expect, it } from 'vitest'
|
|
|
|
|
|
|
+import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
import { browserBundledExternals, browserPackageOfFile, browserSourceAliases } from './browser-bundled-externals.ts'
|
|
import { browserBundledExternals, browserPackageOfFile, browserSourceAliases } from './browser-bundled-externals.ts'
|
|
|
|
|
|
|
|
|
|
+const filesystem = vi.hoisted(() => ({ preservedAlias: undefined as string | undefined }))
|
|
|
|
|
+vi.mock('node:fs', async (importOriginal) => {
|
|
|
|
|
+ const actual = await importOriginal<typeof import('node:fs')>()
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...actual,
|
|
|
|
|
+ realpathSync: Object.assign((...args: Parameters<typeof actual.realpathSync>) => {
|
|
|
|
|
+ // Windows' JavaScript realpath can retain an 8.3 alias that Vite's native resolution expands.
|
|
|
|
|
+ if (typeof args[0] === 'string' && args[0] === filesystem.preservedAlias) return args[0]
|
|
|
|
|
+ return actual.realpathSync(...args)
|
|
|
|
|
+ }, { native: actual.realpathSync.native }),
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
const roots: string[] = []
|
|
const roots: string[] = []
|
|
|
|
|
+const dependencyLinks: string[] = []
|
|
|
const repositoryRoot = resolve(import.meta.dirname, '..')
|
|
const repositoryRoot = resolve(import.meta.dirname, '..')
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
afterEach(() => {
|
|
|
|
|
+ filesystem.preservedAlias = undefined
|
|
|
|
|
+ for (const link of dependencyLinks.splice(0)) unlinkSync(link)
|
|
|
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true })
|
|
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
@@ -78,7 +95,10 @@ describe('browser dependency discovery', () => {
|
|
|
await expect(browserBundledExternals(root)).rejects.toThrow('has no browser build config')
|
|
await expect(browserBundledExternals(root)).rejects.toThrow('has no browser build config')
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- it.each([false, true])('follows shell aliases, CSS and lazy imports without writing output (symlinked root: %s)', async (linked) => {
|
|
|
|
|
|
|
+ it.each([
|
|
|
|
|
+ ['Rollup', false, false], ['Rollup', true, false], ['Rollup', true, true],
|
|
|
|
|
+ ['Rolldown', false, false], ['Rolldown', true, false], ['Rolldown', true, true],
|
|
|
|
|
+ ] as const)('follows shell aliases, CSS and lazy imports without writing output (%s, symlinked root: %s, retained alias: %s)', async (bundler, linked, preserveAlias) => {
|
|
|
const root = fixture()
|
|
const root = fixture()
|
|
|
library(root, 'shell-lib')
|
|
library(root, 'shell-lib')
|
|
|
library(root, 'lazy-lib')
|
|
library(root, 'lazy-lib')
|
|
@@ -96,7 +116,13 @@ describe('browser dependency discovery', () => {
|
|
|
].join('\n'))
|
|
].join('\n'))
|
|
|
const app = join(root, 'apps/web')
|
|
const app = join(root, 'apps/web')
|
|
|
write(root, 'apps/web/package.json', '{"name":"@fixture/web","type":"module","exports":{"./dist/*":"./dist/*"}}')
|
|
write(root, 'apps/web/package.json', '{"name":"@fixture/web","type":"module","exports":{"./dist/*":"./dist/*"}}')
|
|
|
- symlinkSync(resolve(repositoryRoot, 'apps/web/node_modules'), join(app, 'node_modules'), 'junction')
|
|
|
|
|
|
|
+ const owner = bundler === 'Rollup' ? resolve(repositoryRoot, 'apps/web/package.json')
|
|
|
|
|
+ : createRequire(resolve(repositoryRoot, 'package.json')).resolve('vitest/package.json')
|
|
|
|
|
+ const viteDirectory = dirname(createRequire(owner).resolve('vite/package.json'))
|
|
|
|
|
+ const viteLink = join(app, 'node_modules/vite')
|
|
|
|
|
+ mkdirSync(dirname(viteLink), { recursive: true })
|
|
|
|
|
+ symlinkSync(viteDirectory, viteLink, 'junction')
|
|
|
|
|
+ dependencyLinks.push(viteLink)
|
|
|
write(root, 'apps/web/index.html', '<script type="module" src="./main.ts"></script>')
|
|
write(root, 'apps/web/index.html', '<script type="module" src="./main.ts"></script>')
|
|
|
write(root, 'apps/web/main.ts', 'import { output, lazy } from "@fixture/static"; console.log(output); void lazy()')
|
|
write(root, 'apps/web/main.ts', 'import { output, lazy } from "@fixture/static"; console.log(output); void lazy()')
|
|
|
write(root, 'apps/web/vite.config.ts', `
|
|
write(root, 'apps/web/vite.config.ts', `
|
|
@@ -104,7 +130,13 @@ describe('browser dependency discovery', () => {
|
|
|
export default ({ mode }) => {
|
|
export default ({ mode }) => {
|
|
|
if (mode !== 'production') throw new Error('notice discovery must use the production build mode')
|
|
if (mode !== 'production') throw new Error('notice discovery must use the production build mode')
|
|
|
return {
|
|
return {
|
|
|
- plugins: productWebBundleIsolation(${JSON.stringify(root)}, ${JSON.stringify(app)}),
|
|
|
|
|
|
|
+ plugins: [...productWebBundleIsolation(${JSON.stringify(root)}, ${JSON.stringify(app)}), {
|
|
|
|
|
+ name: 'fixture-bundler-engine',
|
|
|
|
|
+ generateBundle() {
|
|
|
|
|
+ const actual = typeof this.meta.rolldownVersion === 'string' ? 'Rolldown' : 'Rollup'
|
|
|
|
|
+ if (actual !== ${JSON.stringify(bundler)}) throw new Error('unexpected bundler: ' + actual)
|
|
|
|
|
+ },
|
|
|
|
|
+ }],
|
|
|
build: { rollupOptions: { input: { index: ${JSON.stringify(join(app, 'index.html'))}, preview: "missing-preview.ts" } } }
|
|
build: { rollupOptions: { input: { index: ${JSON.stringify(join(app, 'index.html'))}, preview: "missing-preview.ts" } } }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -113,9 +145,11 @@ describe('browser dependency discovery', () => {
|
|
|
|
|
|
|
|
const scanRoot = linked ? join(fixture(), 'linked') : root
|
|
const scanRoot = linked ? join(fixture(), 'linked') : root
|
|
|
if (linked) symlinkSync(root, scanRoot, 'junction')
|
|
if (linked) symlinkSync(root, scanRoot, 'junction')
|
|
|
|
|
+ if (preserveAlias) filesystem.preservedAlias = scanRoot
|
|
|
try {
|
|
try {
|
|
|
expect(await browserBundledExternals(scanRoot)).toEqual(new Set(['shell-lib', 'lazy-lib', 'asset-lib']))
|
|
expect(await browserBundledExternals(scanRoot)).toEqual(new Set(['shell-lib', 'lazy-lib', 'asset-lib']))
|
|
|
} finally {
|
|
} finally {
|
|
|
|
|
+ filesystem.preservedAlias = undefined
|
|
|
if (linked) unlinkSync(scanRoot)
|
|
if (linked) unlinkSync(scanRoot)
|
|
|
}
|
|
}
|
|
|
expect(readFileSync(join(app, 'dist/sentinel.txt'), 'utf8')).toBe('untouched')
|
|
expect(readFileSync(join(app, 'dist/sentinel.txt'), 'utf8')).toBe('untouched')
|