Skip to content

Commit

Permalink
Merge pull request #29444 from sentience/fix-nextjs-react-paths-in-mo…
Browse files Browse the repository at this point in the history
…norepo

Next.js: Fix bundled react and react-dom in monorepos

(cherry picked from commit 6c829c5)
  • Loading branch information
valentinpalkovic authored and storybook-bot committed Nov 5, 2024
1 parent 625e209 commit d54f775
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
8 changes: 4 additions & 4 deletions code/frameworks/nextjs/src/config/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ export const configureConfig = async ({
addScopedAlias(baseConfig, 'react', 'next/dist/compiled/react');
}
if (tryResolve('next/dist/compiled/react-dom/cjs/react-dom-test-utils.production.js')) {
setAlias(
addScopedAlias(
baseConfig,
'react-dom/test-utils',
'next/dist/compiled/react-dom/cjs/react-dom-test-utils.production.js'
);
}
if (tryResolve('next/dist/compiled/react-dom')) {
setAlias(baseConfig, 'react-dom$', 'next/dist/compiled/react-dom');
setAlias(baseConfig, 'react-dom/client', 'next/dist/compiled/react-dom/client');
setAlias(baseConfig, 'react-dom/server', 'next/dist/compiled/react-dom/server');
addScopedAlias(baseConfig, 'react-dom$', 'next/dist/compiled/react-dom');
addScopedAlias(baseConfig, 'react-dom/client', 'next/dist/compiled/react-dom/client');
addScopedAlias(baseConfig, 'react-dom/server', 'next/dist/compiled/react-dom/server');
}

setupRuntimeConfig(baseConfig, nextConfig);
Expand Down
42 changes: 33 additions & 9 deletions code/frameworks/nextjs/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,36 @@ export const addScopedAlias = (baseConfig: WebpackConfig, name: string, alias?:
};

/**
* @example // before main script path truncation require.resolve('styled-jsx') ===
* '/some/path/node_modules/styled-jsx/index.js // after main script path truncation
* @example
*
* ```
* // before main script path truncation
* require.resolve('styled-jsx') === '/some/path/node_modules/styled-jsx/index.js
* // after main script path truncation
* scopedResolve('styled-jsx') === '/some/path/node_modules/styled-jsx'
* ```
*
* @example
*
* ```
* // referencing a named export of a package
* scopedResolve('next/dist/compiled/react-dom/client') ===
* // returns the path to the package export without the script filename
* '/some/path/node_modules/next/dist/compiled/react-dom/client';
*
* // referencing a specific file within a CJS package
* scopedResolve('next/dist/compiled/react-dom/cjs/react-dom-test-utils.production.js') ===
* // returns the path to the physical file, including the script filename
* '/some/path/node_modules/next/dist/compiled/react-dom/cjs/react-dom-test-utils.production.js';
* ```
*
* @param id The module id
* @returns A path to the module id scoped to the project folder without the main script path at the
* end
* @param id The module id or script file to resolve
* @returns An absolute path to the specified module id or script file scoped to the project folder
* @summary
* This is to help the addon in development.
* Without it, the addon resolves packages in its node_modules instead of the example's node_modules.
* Because require.resolve will also include the main script as part of the path, this function strips
* that to just include the path to the module folder
* that to just include the path to the module folder when the id provided is a package or named export.
*/
export const scopedResolve = (id: string): string => {
let scopedModulePath;
Expand All @@ -74,9 +92,15 @@ export const scopedResolve = (id: string): string => {
scopedModulePath = require.resolve(id);
}

const moduleFolderStrPosition = scopedModulePath.lastIndexOf(
id.replace(/\//g /* all '/' occurances */, sep)
);
const idWithNativePathSep = id.replace(/\//g /* all '/' occurrences */, sep);

// If the id referenced the file specifically, return the full module path & filename
if (scopedModulePath.endsWith(idWithNativePathSep)) {
return scopedModulePath;
}

// Otherwise, return just the path to the module folder or named export
const moduleFolderStrPosition = scopedModulePath.lastIndexOf(idWithNativePathSep);
const beginningOfMainScriptPath = moduleFolderStrPosition + id.length;
return scopedModulePath.substring(0, beginningOfMainScriptPath);
};

0 comments on commit d54f775

Please sign in to comment.