-
Notifications
You must be signed in to change notification settings - Fork 26.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Turbopack + app router: always use externals for predefined packages #56440
Changes from 13 commits
6c8e952
7b13a60
ab6e12f
6a4acc7
ec9ab85
3485e0a
60fd82a
5b0dbd2
c149b0c
cd83ef3
6a23aa6
35b00e1
6495fb5
4f13a77
fb9878a
e8a27f6
7f516f3
f9cafbc
2ffc50c
5380705
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export const metadata = { | ||
title: 'Next.js', | ||
description: 'Generated by Next.js', | ||
} | ||
|
||
export default function RootLayout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { foo } from 'external-package' | ||
|
||
export default function Index() { | ||
return <div>{foo}</div> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { foo } from 'sqlite3' | ||
|
||
export default function Predefined() { | ||
return <div>{foo}</div> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
experimental: { | ||
serverComponentsExternalPackages: ['external-package'], | ||
}, | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* eslint-env jest */ | ||
|
||
import fs from 'fs/promises' | ||
import { join } from 'path' | ||
import { | ||
killApp, | ||
launchApp, | ||
findPort, | ||
renderViaHTTP, | ||
waitFor, | ||
} from 'next-test-utils' | ||
|
||
const appDir = join(__dirname, '../') | ||
|
||
describe('app bundle externals ', () => { | ||
describe('dev mode', () => { | ||
it('should have externals for those in config.experimental.serverComponentsExternalPackages', async () => { | ||
const port = await findPort() | ||
const app = await launchApp(appDir, port) | ||
await renderViaHTTP(port, '/') | ||
await waitFor(1000) | ||
if (process.env.TURBOPACK) { | ||
const appBundles = await getAppPageChunkPaths(appDir) | ||
const bundleTexts = await Promise.all( | ||
appBundles.map((b) => fs.readFile(b, 'utf8')) | ||
) | ||
expect( | ||
bundleTexts.find((t) => | ||
t.includes( | ||
'__turbopack_external_require__("external-package", true)' | ||
) | ||
) | ||
).not.toBeUndefined() | ||
} else { | ||
const output = await fs.readFile( | ||
join(appDir, '.next/server/app/page.js'), | ||
'utf8' | ||
) | ||
expect(output).toContain('require("external-package")') | ||
} | ||
await killApp(app) | ||
}) | ||
|
||
it('uses externals for predefined list in server-external-packages.json', async () => { | ||
const port = await findPort() | ||
const app = await launchApp(appDir, port) | ||
await renderViaHTTP(port, '/predefined') | ||
await waitFor(1000) | ||
if (process.env.TURBOPACK) { | ||
const appBundles = await getAppPageChunkPaths(appDir, 'predefined') | ||
const bundleTexts = await Promise.all( | ||
appBundles.map((b) => fs.readFile(b, 'utf8')) | ||
) | ||
expect( | ||
bundleTexts.find((t) => | ||
t.includes('__turbopack_external_require__("sqlite3", true)') | ||
) | ||
).not.toBeUndefined() | ||
} else { | ||
const output = await fs.readFile( | ||
join(appDir, '.next/server/app/predefined/page.js'), | ||
'utf8' | ||
) | ||
expect(output).toContain('require("sqlite3")') | ||
} | ||
await killApp(app) | ||
}) | ||
}) | ||
}) | ||
|
||
async function getAppPageChunkPaths(appDir, pageName) { | ||
const rscPath = join(appDir, '.next/server/chunks/rsc') | ||
const pageRegex = new RegExp( | ||
`app${pageName ? '_' + pageName : ''}_page_[0-9a-f]+.js$` | ||
) | ||
|
||
return (await fs.readdir(rscPath)) | ||
.filter((p) => p.match(pageRegex)) | ||
.map((basename) => join(rscPath, basename)) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* eslint-env jest */ | ||
|
||
import fs from 'fs/promises' | ||
import { join } from 'path' | ||
import { | ||
killApp, | ||
launchApp, | ||
findPort, | ||
File, | ||
renderViaHTTP, | ||
waitFor, | ||
} from 'next-test-utils' | ||
|
||
const appDir = join(__dirname, '../') | ||
|
||
describe('default', () => { | ||
it('should use externals for unvendored node_modules reachable from the project', async () => { | ||
const port = await findPort() | ||
const config = new File(join(appDir, 'next.config.js')) | ||
config.delete() | ||
try { | ||
const app = await launchApp(appDir, port) | ||
await renderViaHTTP(port, '/') | ||
if (process.env.TURBOPACK) { | ||
const ssrPath = join(appDir, '.next/server/chunks/ssr') | ||
const pageBundleBasename = (await fs.readdir(ssrPath)).find((p) => | ||
p.match(/pages_index_[0-9a-f]+\.js$/) | ||
) | ||
expect(pageBundleBasename).not.toBeUndefined() | ||
const output = await fs.readFile( | ||
join(ssrPath, pageBundleBasename), | ||
'utf8' | ||
) | ||
expect(output).toContain( | ||
'__turbopack_external_require__("external-package", true)' | ||
) | ||
} else { | ||
const output = await fs.readFile( | ||
join(appDir, '.next/server/pages/index.js'), | ||
'utf8' | ||
) | ||
expect(output).toContain('require("external-package")') | ||
} | ||
await killApp(app) | ||
} finally { | ||
config.restore() | ||
} | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this just be done with
ExternalCjsModulesResolvePlugin
?