-
Notifications
You must be signed in to change notification settings - Fork 86
fix: edge cases for custom react module resolution #2188
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
Changes from 3 commits
83f8ea6
3441150
a766105
fb0093f
7c23568
c712906
3e41a08
78fc4d6
09509b9
17371ad
013b210
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* eslint-disable n/no-extraneous-require, no-underscore-dangle, @typescript-eslint/no-explicit-any */ | ||
/* eslint-disable no-underscore-dangle, @typescript-eslint/no-explicit-any */ | ||
|
||
// This is a modified version of the require hooks from Next.js | ||
// https://github.com/vercel/next.js/blob/b04c70573ac199a9bb3ea42201e0865e610d5b67/packages/next/src/server/require-hook.ts | ||
|
@@ -11,86 +11,89 @@ const resolveFilename = (mod as any)._resolveFilename | |
const requireHooks = new Map<string, Map<string, string>>() | ||
|
||
export const overrideRequireHooks = (config: NextConfig) => { | ||
// we may have changed the working directory in the handler | ||
const opts = { | ||
paths: [process.cwd()], | ||
} | ||
setRequireHooks(config) | ||
resolveRequireHooks() | ||
} | ||
|
||
const setRequireHooks = (config: NextConfig) => { | ||
requireHooks.set( | ||
'default', | ||
new Map([ | ||
['react', require.resolve(`react`, opts)], | ||
['react/jsx-runtime', require.resolve(`react/jsx-runtime`, opts)], | ||
['react', `react`], | ||
['react/jsx-runtime', `react/jsx-runtime`], | ||
]), | ||
) | ||
|
||
if (config.experimental.appDir) { | ||
requireHooks.set( | ||
'next', | ||
new Map([ | ||
['react', require.resolve(`next/dist/compiled/react`, opts)], | ||
['react/jsx-runtime', require.resolve(`next/dist/compiled/react/jsx-runtime`, opts)], | ||
['react/jsx-dev-runtime', require.resolve(`next/dist/compiled/react/jsx-dev-runtime`, opts)], | ||
['react-dom', require.resolve(`next/dist/compiled/react-dom/server-rendering-stub`, opts)], | ||
['react-dom/client', require.resolve(`next/dist/compiled/react-dom/client`, opts)], | ||
['react-dom/server', require.resolve(`next/dist/compiled/react-dom/server`, opts)], | ||
['react-dom/server.browser', require.resolve(`next/dist/compiled/react-dom/server.browser`, opts)], | ||
['react-dom/server.edge', require.resolve(`next/dist/compiled/react-dom/server.edge`, opts)], | ||
[ | ||
'react-server-dom-webpack/client', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack/client`, opts), | ||
], | ||
[ | ||
'react-server-dom-webpack/client.edge', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack/client.edge`, opts), | ||
], | ||
[ | ||
'react-server-dom-webpack/server.edge', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack/server.edge`, opts), | ||
], | ||
[ | ||
'react-server-dom-webpack/server.node', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack/server.node`, opts), | ||
], | ||
['styled-jsx', require.resolve('styled-jsx', opts)], | ||
['styled-jsx/style', require.resolve('styled-jsx/style', opts)], | ||
]), | ||
) | ||
if (config.experimental.serverActions) { | ||
requireHooks.set( | ||
'experimental', | ||
new Map([ | ||
['react', `next/dist/compiled/react-experimental`], | ||
['react/jsx-runtime', `next/dist/compiled/react-experimental/jsx-runtime`], | ||
['react/jsx-dev-runtime', `next/dist/compiled/react-experimental/jsx-dev-runtime`], | ||
['react-dom', `next/dist/compiled/react-dom-experimental/server-rendering-stub`], | ||
['react-dom/client', `next/dist/compiled/react-dom-experimental/client`], | ||
['react-dom/server', `next/dist/compiled/react-dom-experimental/server`], | ||
['react-dom/server.browser', `next/dist/compiled/react-dom-experimental/server.browser`], | ||
['react-dom/server.edge', `next/dist/compiled/react-dom-experimental/server.edge`], | ||
['react-server-dom-webpack/client', `next/dist/compiled/react-server-dom-webpack-experimental/client`], | ||
[ | ||
'react-server-dom-webpack/client.edge', | ||
`next/dist/compiled/react-server-dom-webpack-experimental/client.edge`, | ||
], | ||
[ | ||
'react-server-dom-webpack/server.edge', | ||
`next/dist/compiled/react-server-dom-webpack-experimental/server.edge`, | ||
], | ||
[ | ||
'react-server-dom-webpack/server.node', | ||
`next/dist/compiled/react-server-dom-webpack-experimental/server.node`, | ||
], | ||
['styled-jsx', 'styled-jsx'], | ||
['styled-jsx/style', 'styled-jsx/style'], | ||
]), | ||
) | ||
} else { | ||
requireHooks.set( | ||
'next', | ||
new Map([ | ||
['react', `next/dist/compiled/react`], | ||
['react/jsx-runtime', `next/dist/compiled/react/jsx-runtime`], | ||
['react/jsx-dev-runtime', `next/dist/compiled/react/jsx-dev-runtime`], | ||
['react-dom', `next/dist/compiled/react-dom/server-rendering-stub`], | ||
['react-dom/client', `next/dist/compiled/react-dom/client`], | ||
['react-dom/server', `next/dist/compiled/react-dom/server`], | ||
['react-dom/server.browser', `next/dist/compiled/react-dom/server.browser`], | ||
['react-dom/server.edge', `next/dist/compiled/react-dom/server.edge`], | ||
['react-server-dom-webpack/client', `next/dist/compiled/react-server-dom-webpack/client`], | ||
['react-server-dom-webpack/client.edge', `next/dist/compiled/react-server-dom-webpack/client.edge`], | ||
['react-server-dom-webpack/server.edge', `next/dist/compiled/react-server-dom-webpack/server.edge`], | ||
['react-server-dom-webpack/server.node', `next/dist/compiled/react-server-dom-webpack/server.node`], | ||
['styled-jsx', 'styled-jsx'], | ||
['styled-jsx/style', 'styled-jsx/style'], | ||
]), | ||
) | ||
} | ||
} | ||
} | ||
|
||
if (config.experimental.serverActions) { | ||
requireHooks.set( | ||
'experimental', | ||
new Map([ | ||
['react', require.resolve(`next/dist/compiled/react-experimental`, opts)], | ||
['react/jsx-runtime', require.resolve(`next/dist/compiled/react-experimental/jsx-runtime`, opts)], | ||
['react/jsx-dev-runtime', require.resolve(`next/dist/compiled/react-experimental/jsx-dev-runtime`, opts)], | ||
['react-dom', require.resolve(`next/dist/compiled/react-dom-experimental/server-rendering-stub`, opts)], | ||
['react-dom/client', require.resolve(`next/dist/compiled/react-dom-experimental/client`, opts)], | ||
['react-dom/server', require.resolve(`next/dist/compiled/react-dom-experimental/server`, opts)], | ||
['react-dom/server.browser', require.resolve(`next/dist/compiled/react-dom-experimental/server.browser`, opts)], | ||
['react-dom/server.edge', require.resolve(`next/dist/compiled/react-dom-experimental/server.edge`, opts)], | ||
[ | ||
'react-server-dom-webpack/client', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack-experimental/client`, opts), | ||
], | ||
[ | ||
'react-server-dom-webpack/client.edge', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack-experimental/client.edge`, opts), | ||
], | ||
[ | ||
'react-server-dom-webpack/server.edge', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack-experimental/server.edge`, opts), | ||
], | ||
[ | ||
'react-server-dom-webpack/server.node', | ||
require.resolve(`next/dist/compiled/react-server-dom-webpack-experimental/server.node`, opts), | ||
], | ||
['styled-jsx', require.resolve('styled-jsx', opts)], | ||
['styled-jsx/style', require.resolve('styled-jsx/style', opts)], | ||
]), | ||
) | ||
} | ||
const resolveRequireHooks = () => { | ||
// we may have changed the working directory in the handler | ||
const opts = { paths: [process.cwd()] } | ||
|
||
// resolve require hooks with module paths | ||
requireHooks.forEach((mode) => { | ||
mode.forEach((hook, path) => { | ||
try { | ||
const resolvedPath = require.resolve(path, opts) | ||
mode.set(hook, resolvedPath) | ||
} catch { | ||
// ignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need any logging here for our observability or is it safe to just ignore? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hey @MarcL, this is safe to ignore here because it's not actually an error - we want to delete the hook in this case because it happens when a module isn't found, i.e. an older version of Next |
||
mode.delete(hook) | ||
} | ||
}) | ||
}) | ||
} | ||
|
||
export const applyRequireHooks = () => { | ||
|
@@ -103,12 +106,12 @@ export const applyRequireHooks = () => { | |
isMain: boolean, | ||
options: any, | ||
) { | ||
const reactMode = process.env.__NEXT_PRIVATE_PREBUNDLED_REACT ?? 'default' | ||
const reactMode = process.env.__NEXT_PRIVATE_PREBUNDLED_REACT || 'default' | ||
const resolvedRequest = hooks.get(reactMode)?.get(request) ?? request | ||
|
||
return originalResolveFilename.call(mod, resolvedRequest, parent, isMain, options) | ||
|
||
// We use `bind` here to avoid referencing outside variables to create potential memory leaks. | ||
}.bind(null, resolveFilename, requireHooks) | ||
} | ||
/* eslint-enable n/no-extraneous-require, no-underscore-dangle, @typescript-eslint/no-explicit-any */ | ||
/* eslint-enable no-underscore-dangle, @typescript-eslint/no-explicit-any */ |
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.
Consider only deleting the hook when the error thrown is
MODULE_NOT_FOUND
, otherwise rethrow.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.
@nickytonline good plan, have updated in 78fc4d6