mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
For modules that we were not using, that we're asynchronously loading,
we would still generate the loader but the file would not exist. This
meant building a Next.js app with:
```javascript
// pure.js — side-effect free: nothing observable happens on evaluation
export const version = '1.0.0'
// app/page.tsx
export default async function Page() {
const {} = await import('../pure') // ← nothing destructured out
return <p>hello world</p>
}
```
Would error with:
```
▲ Next.js 16.3.0-canary.87 (Turbopack)
Creating an optimized production build ...
FATAL: An unexpected Turbopack error occurred.
> Build error occurred
Error [TurbopackInternalError]: Failed to write app endpoint /page
Caused by:
- ModuleId not found for ident: [project]/pure.js [app-rsc] (ecmascript, async loader)
Debug info:
...
- Execution of PatternMapping::resolve_request failed
- ModuleId not found for ident: [project]/pure.js [app-rsc] (ecmascript, async loader)
```
Now, we re-write those loaders to empty promises:
```diff
async function evaluationOnly() {
- const {} = await __turbopack_context__.A("…/pure.js [test] (ecmascript, async loader)");
+ const {} = await Promise.resolve({});
}
async function named() {
const { used } = await __turbopack_context__.A("…/named.js [test] (ecmascript, async loader)");
console.log(used);
}
async function pattern(locale) {
const {} = await __turbopack_context__.f({
"./locales/effectful.js": {
id: ()=>"…/locales/effectful.js [test] (ecmascript, async loader)",
module: ()=>__turbopack_context__.A("…/locales/effectful.js …")
},
"./locales/pure.js": {
- id: ()=>"…/locales/pure.js [test] (ecmascript, async loader)",
- module: ()=>__turbopack_context__.A("…/locales/pure.js …")
+ id: ()=>undefined,
+ module: ()=>Promise.resolve({})
}
}).import(`./locales/${locale}.js`);
}
```
It turns `UnusedReferences` into a map between references and target
that can be dropped, where the target IDs are the unused targets. It
then passes the reference through to `pattern_mapping.rs` so it can
determine the `dropped_targets`. It needs to be target-specific as you
can have a situation (like above) where some targets are pure and some
aren't.
31 lines
960 B
TypeScript
31 lines
960 B
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
|
|
describe('dynamic-import-evaluation-only', () => {
|
|
const { next, skipped } = nextTestSetup({
|
|
files: __dirname,
|
|
skipDeployment: true,
|
|
skipStart: true,
|
|
})
|
|
if (skipped) return
|
|
|
|
it('should drop only the side-effect-free targets of evaluation-only dynamic imports', async () => {
|
|
const { exitCode, cliOutput } = await next.build()
|
|
|
|
expect(cliOutput).not.toContain('ModuleId not found for ident')
|
|
expect(exitCode).toBe(0)
|
|
|
|
const dir = path.join(next.testDir, '.next/server')
|
|
const output = fs
|
|
.readdirSync(dir, { recursive: true, encoding: 'utf8' })
|
|
.filter((file) => file.endsWith('.js'))
|
|
.map((file) => fs.readFileSync(path.join(dir, file), 'utf8'))
|
|
.join('\n')
|
|
|
|
expect(output).not.toContain('DROPPED_SIMPLE')
|
|
expect(output).not.toContain('DROPPED_PATTERN')
|
|
expect(output).toContain('__kept')
|
|
})
|
|
})
|