Skip to content

Commit ccf79b7

Browse files
committed
fix: windows compat
1 parent 7355322 commit ccf79b7

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

src/build/content/server.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
writeFile,
1111
} from 'node:fs/promises'
1212
import { createRequire } from 'node:module'
13-
import { dirname, join, relative, sep } from 'node:path'
14-
import { join as posixJoin, sep as posixSep } from 'node:path/posix'
13+
import { dirname, join, sep } from 'node:path'
14+
import { join as posixJoin, relative as posixRelative, sep as posixSep } from 'node:path/posix'
1515

1616
import { trace } from '@opentelemetry/api'
1717
import { wrapTracer } from '@opentelemetry/api/experimental'
@@ -26,7 +26,11 @@ import type { PluginContext, RequiredServerFilesManifest } from '../plugin-conte
2626

2727
const tracer = wrapTracer(trace.getTracer('Next runtime'))
2828

29-
const toPosixPath = (path: string) => path.split(sep).join(posixSep)
29+
const toPosixPath = (path: string) =>
30+
path
31+
.replace(/^\\+\?\\+/, '') // https://github.com/nodejs/node/blob/81e05e124f71b3050cd4e60c95017af975568413/lib/internal/fs/utils.js#L370-L372
32+
.split(sep)
33+
.join(posixSep)
3034

3135
function isError(error: unknown): error is NodeJS.ErrnoException {
3236
return error instanceof Error
@@ -173,6 +177,7 @@ export const copyNextServerCode = async (ctx: PluginContext): Promise<void> => {
173177
* @returns
174178
*/
175179
async function recreateNodeModuleSymlinks(src: string, dest: string, org?: string): Promise<void> {
180+
console.log('recreateNodeModuleSymlinks', { src, dest, org })
176181
const dirents = await readdir(join(src, org || ''), { withFileTypes: true })
177182

178183
await Promise.all(
@@ -309,17 +314,21 @@ export const copyNextDependencies = async (ctx: PluginContext): Promise<void> =>
309314
await tracer.withActiveSpan('copyNextDependencies', async () => {
310315
const promises: Promise<void>[] = []
311316

312-
const nodeModulesLocationsInStandalone = new Set<string>()
317+
const nodeModulesLocations = new Set<{ source: string; destination: string }>()
313318
const commonFilter = ctx.constants.IS_LOCAL ? undefined : nodeModulesFilter
314319

315-
const dotNextDir = join(ctx.standaloneDir, ctx.nextDistDir)
320+
const dotNextDir = toPosixPath(join(ctx.standaloneDir, ctx.nextDistDir))
321+
322+
const standaloneRootDir = toPosixPath(ctx.standaloneRootDir)
323+
const outputFileTracingRoot = toPosixPath(ctx.outputFileTracingRoot)
316324

317325
await cp(ctx.standaloneRootDir, ctx.serverHandlerRootDir, {
318326
recursive: true,
319327
verbatimSymlinks: true,
320328
force: true,
321-
filter: async (sourcePath: string) => {
322-
if (sourcePath === dotNextDir) {
329+
filter: async (sourcePath: string, destination: string) => {
330+
const posixSourcePath = toPosixPath(sourcePath)
331+
if (posixSourcePath === dotNextDir) {
323332
// copy all except the distDir (.next) folder as this is handled in a separate function
324333
// this will include the node_modules folder as well
325334
return false
@@ -328,18 +337,23 @@ export const copyNextDependencies = async (ctx: PluginContext): Promise<void> =>
328337
if (sourcePath.endsWith('node_modules')) {
329338
// keep track of node_modules as we might need to recreate symlinks
330339
// we are still copying them
331-
nodeModulesLocationsInStandalone.add(sourcePath)
340+
nodeModulesLocations.add({
341+
source: posixSourcePath,
342+
destination: toPosixPath(destination),
343+
})
332344
}
333345

334346
// finally apply common filter if defined
335347
return commonFilter?.(sourcePath) ?? true
336348
},
337349
})
338350

339-
for (const nodeModulesLocationInStandalone of nodeModulesLocationsInStandalone) {
340-
const relativeToRoot = relative(ctx.standaloneRootDir, nodeModulesLocationInStandalone)
341-
const locationInProject = join(ctx.outputFileTracingRoot, relativeToRoot)
342-
const locationInServerHandler = join(ctx.serverHandlerRootDir, relativeToRoot)
351+
for (const {
352+
source: nodeModulesLocationInStandalone,
353+
destination: locationInServerHandler,
354+
} of nodeModulesLocations) {
355+
const relativeToRoot = posixRelative(standaloneRootDir, nodeModulesLocationInStandalone)
356+
const locationInProject = posixJoin(outputFileTracingRoot, relativeToRoot)
343357

344358
promises.push(recreateNodeModuleSymlinks(locationInProject, locationInServerHandler))
345359
}

src/build/plugin-context.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from 'node:fs'
22
import { readFile } from 'node:fs/promises'
33
import { createRequire } from 'node:module'
44
import { join, relative, resolve, sep } from 'node:path'
5-
import { join as posixJoin, relative as posixRelative, sep as posixSep } from 'node:path/posix'
5+
import { join as posixJoin, relative as posixRelative } from 'node:path/posix'
66
import { fileURLToPath } from 'node:url'
77

88
import type {
@@ -20,8 +20,6 @@ import type {
2020
} from 'next-with-cache-handler-v2/dist/build/index.js'
2121
import { satisfies } from 'semver'
2222

23-
const toPosixPath = (path: string) => path.split(sep).join(posixSep)
24-
2523
const MODULE_DIR = fileURLToPath(new URL('.', import.meta.url))
2624
const PLUGIN_DIR = join(MODULE_DIR, '../..')
2725
const DEFAULT_PUBLISH_DIR = '.next'
@@ -100,7 +98,7 @@ export class PluginContext {
10098
}
10199

102100
if (!this.relativeAppDir.includes('..')) {
103-
// For newer Next.js versions this is not written to the output directly anymore, but we can use appDir and relativeAppDir to compute it.
101+
// For newer Next.js versions outputFileTracingRoot is not written to the output directly anymore, but we can use appDir and relativeAppDir to compute it.
104102
// This assumes that relative app dir will never contain '..' segments. Some monorepos support workspaces outside of the monorepo root (verified with pnpm)
105103
// However Next.js itself have some limits on it:
106104
// - turbopack by default would throw "Module not found: Can't resolve '<name_of_package_outside_of_root>'"
@@ -110,8 +108,7 @@ export class PluginContext {
110108
// because parts of application would be outside of "standalone" directory
111109
// - if it's not marked as external it will be included in next.js produced chunks
112110

113-
const depth =
114-
this.relativeAppDir === '' ? 0 : toPosixPath(this.relativeAppDir).split(posixSep).length
111+
const depth = this.relativeAppDir === '' ? 0 : this.relativeAppDir.split(sep).length
115112

116113
const computedOutputFileTracingRoot = resolve(
117114
this.requiredServerFiles.appDir,

0 commit comments

Comments
 (0)