Skip to content
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

Fix symlink and copy logic to standalone directory when using outputStandalone #35535

Merged
merged 17 commits into from Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 1 addition & 4 deletions packages/next/build/utils.ts
Expand Up @@ -1172,10 +1172,7 @@ export async function copyTracedFiles(

if (symlink) {
console.log('symlink', path.relative(tracingRoot, symlink))
await fs.symlink(
path.relative(tracingRoot, symlink),
fileOutputPath
)
await fs.symlink(symlink, fileOutputPath)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

symlink is already a relative path, no need to use path.relative

} else {
await fs.copyFile(tracedFilePath, fileOutputPath)
}
Expand Down
2 changes: 2 additions & 0 deletions test/integration/pnpm-support/app-multi-page/.npmrc
@@ -0,0 +1,2 @@
# put modules outside of the app folder, to simulate what happens in a pnpm workspace
virtual-store-dir=../pnpm
9 changes: 9 additions & 0 deletions test/integration/pnpm-support/app-multi-page/next.config.js
@@ -0,0 +1,9 @@
const path = require('path')

module.exports = {
experimental: {
outputStandalone: true,
// pnpm virtual-store-dir is outside the app directory
outputFileTracingRoot: path.resolve(__dirname, '../'),
},
}
5 changes: 5 additions & 0 deletions test/integration/pnpm-support/app/next.config.js
@@ -0,0 +1,5 @@
module.exports = {
experimental: {
outputStandalone: true,
},
}
91 changes: 85 additions & 6 deletions test/integration/pnpm-support/test/index.test.js
Expand Up @@ -13,8 +13,33 @@ const APP_DIRS = {
'app-multi-page': path.join(__dirname, '..', 'app-multi-page'),
}

// runs a command showing logs and returning the stdout
const runCommand = (cwd, cmd, args) => {
const proc = execa(cmd, [...args], {
cwd,
stdio: [process.stdin, 'pipe', process.stderr],
})

let stdout = ''
proc.stdout.on('data', (data) => {
const s = data.toString()
process.stdout.write(s)
stdout += s
})
return new Promise((resolve, reject) => {
proc.on('exit', (code) => {
if (code === 0) {
return resolve({ ...proc, stdout })
}
reject(
new Error(`Command ${cmd} ${args.join(' ')} failed with code ${code}`)
)
})
})
}

const runNpm = (cwd, ...args) => execa('npm', [...args], { cwd })
const runPnpm = (cwd, ...args) => execa('npx', ['pnpm', ...args], { cwd })
const runPnpm = (cwd, ...args) => runCommand(cwd, 'npx', ['pnpm', ...args])

async function usingTempDir(fn) {
const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2))
Expand Down Expand Up @@ -134,24 +159,78 @@ describe('pnpm support', () => {
expect(packageJson.pnpm.overrides[dependency]).toMatch(/^file:/)
}

const { stdout, stderr } = await runPnpm(appDir, 'run', 'build')
console.log(stdout, stderr)
const { stdout } = await runPnpm(appDir, 'run', 'build')

expect(stdout).toMatch(/Compiled successfully/)
})
})

it('should execute client-side JS on each page in outputStandalone', async () => {
await usingPnpmCreateNextApp(APP_DIRS['app-multi-page'], async (appDir) => {
const { stdout } = await runPnpm(appDir, 'run', 'build')

expect(stdout).toMatch(/Compiled successfully/)

let appPort
let appProcess
let browser
try {
appPort = await findPort()
const standaloneDir = path.resolve(appDir, '.next/standalone/app')

// simulate what happens in a Dockerfile
await fs.remove(path.join(appDir, 'node_modules'))
await fs.copy(
path.resolve(appDir, './.next/static'),
path.resolve(standaloneDir, './.next/static'),
{ overwrite: true }
)
appProcess = execa('node', ['server.js'], {
cwd: standaloneDir,
env: {
PORT: appPort,
},
stdio: 'inherit',
})

await waitFor(1000)

await renderViaHTTP(appPort, '/')

browser = await webdriver(appPort, '/', {
waitHydration: false,
})
expect(await browser.waitForElementByCss('#world').text()).toBe('World')
await browser.close()

browser = await webdriver(appPort, '/about', {
waitHydration: false,
})
expect(await browser.waitForElementByCss('#world').text()).toBe('World')
await browser.close()
} finally {
await killProcess(appProcess.pid)
await waitFor(5000)
}
})
})

it('should execute client-side JS on each page', async () => {
await usingPnpmCreateNextApp(APP_DIRS['app-multi-page'], async (appDir) => {
const { stdout, stderr } = await runPnpm(appDir, 'run', 'build')
console.log(stdout, stderr)
const { stdout } = await runPnpm(appDir, 'run', 'build')

expect(stdout).toMatch(/Compiled successfully/)

let appPort
let appProcess
let browser
try {
appPort = await findPort()
appProcess = runPnpm(appDir, 'run', 'start', '--', '--port', appPort)
appProcess = execa('pnpm', ['run', 'start', '--', '--port', appPort], {
cwd: appDir,
stdio: 'inherit',
})

await waitFor(5000)

await renderViaHTTP(appPort, '/')
Expand Down