Files
next.js/test/development/basic/barrel-optimization.test.ts
T
Shu DingandGitHub 9b671046b9 Flatten recursive wildcard exports in barrel optimization (#56489)
This PR flattens the recursive optimization logic of our barrel optimization loader. So now if there're any recursive `export * from ...`, they won't be created as multiple individual Webpack modules, but optimized in one module.

With this change, we are running SWC transform to get the export map directly inside the barrel loader (instead of a separate loader rule). And that map is recursively calculated and cached in memory.

I also published https://unpkg.com/browse/[email protected]/ to give this a test. It contains 4 levels of 10 `export *` expressions, which is 10,000 modules in total. Without this change, it takes ~30s to compile and with this change, it goes down to ~7s.
2023-10-06 15:39:15 +00:00

152 lines
4.6 KiB
TypeScript

import { join } from 'path'
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { shouldRunTurboDevTest } from '../../lib/next-test-utils'
describe('optimizePackageImports', () => {
let next: NextInstance
beforeAll(async () => {
next = await createNext({
env: {
NEXT_TEST_MODE: '1',
},
files: {
app: new FileRef(join(__dirname, 'barrel-optimization/app')),
pages: new FileRef(join(__dirname, 'barrel-optimization/pages')),
components: new FileRef(
join(__dirname, 'barrel-optimization/components')
),
'next.config.js': new FileRef(
join(__dirname, 'barrel-optimization/next.config.js')
),
node_modules_bak: new FileRef(
join(__dirname, 'barrel-optimization/node_modules_bak')
),
},
packageJson: {
scripts: {
setup: `cp -r ./node_modules_bak/* ./node_modules`,
build: `yarn setup && next build`,
dev: `yarn setup && next ${
shouldRunTurboDevTest() ? 'dev --turbo' : 'dev'
}`,
start: 'next start',
},
},
installCommand: 'yarn',
startCommand: (global as any).isNextDev ? 'yarn dev' : 'yarn start',
buildCommand: 'yarn build',
dependencies: {
'lucide-react': '0.264.0',
'@headlessui/react': '1.7.17',
'@heroicons/react': '2.0.18',
'@visx/visx': '3.3.0',
'recursive-barrel': '1.0.0',
},
})
})
afterAll(() => next.destroy())
it('app - should render the icons correctly without creating all the modules', async () => {
let logs = ''
next.on('stdout', (log) => {
logs += log
})
const html = await next.render('/')
// Ensure the icons are rendered
expect(html).toContain('<svg xmlns="http://www.w3.org/2000/svg"')
const modules = [
...logs.matchAll(
/Compiled (\/[\w-]+)*\s*in \d+(\.\d+)?(s|ms) \((\d+) modules\)/g
),
]
expect(modules.length).toBeGreaterThanOrEqual(1)
for (const [, , , , moduleCount] of modules) {
// Ensure that the number of modules is less than 1000 - otherwise we're
// importing the entire library.
expect(parseInt(moduleCount)).toBeLessThan(1000)
}
})
it('pages - should render the icons correctly without creating all the modules', async () => {
let logs = ''
next.on('stdout', (log) => {
logs += log
})
const html = await next.render('/pages-route')
// Ensure the icons are rendered
expect(html).toContain('<svg xmlns="http://www.w3.org/2000/svg"')
const modules = [
...logs.matchAll(
/Compiled (\/[\w-]+)*\s*in \d+(\.\d+)?(s|ms) \((\d+) modules\)/g
),
]
expect(modules.length).toBeGreaterThanOrEqual(1)
for (const [, , , , moduleCount] of modules) {
// Ensure that the number of modules is less than 1000 - otherwise we're
// importing the entire library.
expect(parseInt(moduleCount)).toBeLessThan(1000)
}
})
it('app - should optimize recursive wildcard export mapping', async () => {
let logs = ''
next.on('stdout', (log) => {
logs += log
})
await next.render('/recursive-barrel-app')
const modules = [...logs.matchAll(/\((\d+) modules\)/g)]
expect(modules.length).toBeGreaterThanOrEqual(1)
for (const [, moduleCount] of modules) {
// Ensure that the number of modules is less than 1000 - otherwise we're
// importing the entire library.
expect(parseInt(moduleCount)).toBeLessThan(1000)
}
})
it('pages - should optimize recursive wildcard export mapping', async () => {
let logs = ''
next.on('stdout', (log) => {
logs += log
})
await next.render('/recursive-barrel')
const modules = [...logs.matchAll(/\((\d+) modules\)/g)]
expect(modules.length).toBeGreaterThanOrEqual(1)
for (const [, moduleCount] of modules) {
// Ensure that the number of modules is less than 1000 - otherwise we're
// importing the entire library.
expect(parseInt(moduleCount)).toBeLessThan(1000)
}
})
it('should handle recursive wildcard exports', async () => {
const html = await next.render('/recursive')
expect(html).toContain('<h1>42</h1>')
})
it('should support visx', async () => {
const html = await next.render('/visx')
expect(html).toContain('<linearGradient')
})
it('should not break "use client" directive in optimized packages', async () => {
const html = await next.render('/client')
expect(html).toContain('this is a client component')
})
})