Skip to content

Commit

Permalink
Include resolved external package dirs (#41706)
Browse files Browse the repository at this point in the history
We currently assume that external packages are installed via a package
manager, but actually in a monorepo they can be in local.

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)

Co-authored-by: JJ Kasper <jj@jjsweb.site>
  • Loading branch information
shuding and ijjk committed Oct 24, 2022
1 parent 13f6eff commit fbe1ffb
Showing 1 changed file with 40 additions and 6 deletions.
46 changes: 40 additions & 6 deletions packages/next/build/webpack-config.ts
Expand Up @@ -120,11 +120,19 @@ function errorIfEnvConflicted(config: NextConfigComplete, key: string) {
}
}

function isResourceInPackages(resource: string, packageNames?: string[]) {
function isResourceInPackages(
resource: string,
packageNames?: string[],
packageDirMapping?: Map<string, string>
) {
return packageNames?.some((p: string) =>
resource.includes(
path.sep + pathJoin('node_modules', p.replace(/\//g, path.sep)) + path.sep
)
packageDirMapping && packageDirMapping.has(p)
? resource.startsWith(packageDirMapping.get(p)! + path.sep)
: resource.includes(
path.sep +
pathJoin('node_modules', p.replace(/\//g, path.sep)) +
path.sep
)
)
}

Expand Down Expand Up @@ -1028,6 +1036,8 @@ export default async function getBaseWebpackConfig(
...(config.experimental.serverComponentsExternalPackages || [])
)

let resolvedExternalPackageDirs: Map<string, string>

async function handleExternals(
context: string,
request: string,
Expand Down Expand Up @@ -1194,9 +1204,30 @@ export default async function getBaseWebpackConfig(

// If a package should be transpiled by Next.js, we skip making it external.
// It doesn't matter what the extension is, as we'll transpile it anyway.
if (config.experimental.transpilePackages && !resolvedExternalPackageDirs) {
resolvedExternalPackageDirs = new Map()
// We need to reoslve all the external package dirs initially.
for (const pkg of config.experimental.transpilePackages) {
const pkgRes = await resolveExternal(
dir,
config.experimental.esmExternals,
context,
pkg + '/package.json',
hasAppDir,
isEsmRequested,
getResolve,
isLocal ? isLocalCallback : undefined
)
if (pkgRes.res) {
resolvedExternalPackageDirs.set(pkg, path.dirname(pkgRes.res))
}
}
}

const shouldBeBundled = isResourceInPackages(
res,
config.experimental.transpilePackages
config.experimental.transpilePackages,
resolvedExternalPackageDirs
)

if (/node_modules[/\\].*\.[mc]?js$/.test(res)) {
Expand Down Expand Up @@ -1240,9 +1271,12 @@ export default async function getBaseWebpackConfig(
// Default behavior: bundle the code!
}

const shouldIncludeExternalDirs =
config.experimental.externalDir || !!config.experimental.transpilePackages

const codeCondition = {
test: /\.(tsx|ts|js|cjs|mjs|jsx)$/,
...(config.experimental.externalDir
...(shouldIncludeExternalDirs
? // Allowing importing TS/TSX files from outside of the root dir.
{}
: { include: [dir, ...babelIncludeRegexes] }),
Expand Down

0 comments on commit fbe1ffb

Please sign in to comment.