1
1
import { existsSync } from 'node:fs'
2
2
import { cp , mkdir , readFile , readdir , readlink , symlink , writeFile } from 'node:fs/promises'
3
- import { dirname , join } from 'node:path'
3
+ import { createRequire } from 'node:module'
4
+ // eslint-disable-next-line no-restricted-imports
5
+ import { dirname , join , resolve } from 'node:path'
4
6
5
7
import glob from 'fast-glob'
6
8
@@ -73,7 +75,7 @@ async function recreateNodeModuleSymlinks(src: string, dest: string, org?: strin
73
75
// if it is an organization folder let's create the folder first
74
76
await mkdir ( join ( dest , org ) , { recursive : true } )
75
77
}
76
- await symlink ( symlinkDest , symlinkSrc )
78
+ await symlink ( symlinkTarget , symlinkSrc )
77
79
}
78
80
}
79
81
} ) ,
@@ -90,7 +92,7 @@ export const copyNextDependencies = async (ctx: PluginContext): Promise<void> =>
90
92
}
91
93
const src = join ( ctx . standaloneDir , entry )
92
94
const dest = join ( ctx . serverHandlerDir , entry )
93
- await cp ( src , dest , { recursive : true } )
95
+ await cp ( src , dest , { recursive : true , verbatimSymlinks : true } )
94
96
95
97
if ( entry === 'node_modules' ) {
96
98
await recreateNodeModuleSymlinks ( ctx . resolve ( 'node_modules' ) , dest )
@@ -101,19 +103,30 @@ export const copyNextDependencies = async (ctx: PluginContext): Promise<void> =>
101
103
const rootSrcDir = join ( ctx . standaloneRootDir , 'node_modules' )
102
104
const rootDestDir = join ( ctx . serverHandlerRootDir , 'node_modules' )
103
105
104
- // TODO: @Lukas Holzer test this in monorepos
105
106
// use the node_modules tree from the process.cwd() and not the one from the standalone output
106
107
// as the standalone node_modules are already wrongly assembled by Next.js.
107
108
// see: https://github.com/vercel/next.js/issues/50072
108
109
if ( existsSync ( rootSrcDir ) && ctx . standaloneRootDir !== ctx . standaloneDir ) {
109
110
promises . push (
110
- cp ( rootSrcDir , rootDestDir , { recursive : true } ) . then ( ( ) =>
111
- recreateNodeModuleSymlinks ( ctx . resolve ( 'node_modules' ) , rootDestDir ) ,
111
+ cp ( rootSrcDir , rootDestDir , { recursive : true , verbatimSymlinks : true } ) . then ( ( ) =>
112
+ recreateNodeModuleSymlinks ( resolve ( 'node_modules' ) , rootDestDir ) ,
112
113
) ,
113
114
)
114
115
}
115
116
116
117
await Promise . all ( promises )
118
+
119
+ // detect if it might lead to a runtime issue and throw an error upfront on build time instead of silently failing during runtime
120
+ const require = createRequire ( ctx . serverHandlerDir )
121
+ try {
122
+ require . resolve ( 'styled-jsx' )
123
+ require . resolve ( 'next' )
124
+ } catch {
125
+ throw new Error (
126
+ 'node_modules are not installed correctly, if you are using pnpm please set the public hoist pattern to: `public-hoist-pattern[]=*`.\n' +
127
+ 'Refer to your docs for more details: https://docs.netlify.com/integrations/frameworks/next-js/overview/#pnpm-support' ,
128
+ )
129
+ }
117
130
}
118
131
119
132
export const writeTagsManifest = async ( ctx : PluginContext ) : Promise < void > => {
0 commit comments