Skip to content

Commit

Permalink
Update import resolution for files and package exports
Browse files Browse the repository at this point in the history
In an npm workspace environment, wrangler will now be able to
successfully resolve package exports.

Previously, wrangler would only be able to resolve modules in a relative
`node_modules` directory and not workspace root `node_modules`
directory.
  • Loading branch information
nickbabcock committed Oct 30, 2024
1 parent 6cf64de commit 5583934
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 103 deletions.
20 changes: 0 additions & 20 deletions packages/wrangler/src/__tests__/module-collection.test.ts

This file was deleted.

72 changes: 2 additions & 70 deletions packages/wrangler/src/deployment-bundle/module-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import { readdirSync } from "node:fs";
import { readFile } from "node:fs/promises";
import path from "node:path";
import globToRegExp from "glob-to-regexp";
import { sync as resolveSync } from "resolve";
import { exports as resolveExports } from "resolve.exports";
import { UserError } from "../errors";
import { logger } from "../logger";
import { getBuildConditions } from "./bundle";
import {
findAdditionalModules,
findAdditionalModuleWatchDirs,
Expand Down Expand Up @@ -71,25 +68,6 @@ export const noopModuleCollector: ModuleCollector = {
},
};

// Extracts a package name from a string that may be a file path
// or a package name. Returns null if the string is not a valid
// Handles `wrangler`, `wrangler/example`, `wrangler/example.wasm`,
// `@cloudflare/wrangler`, `@cloudflare/wrangler/example`, etc.
export function extractPackageName(packagePath: string) {
if (packagePath.startsWith(".")) {
return null;
}

const match = packagePath.match(/^(@[^/]+\/)?([^/]+)/);

if (match) {
const scoped = match[1] || "";
const packageName = match[2];
return `${scoped}${packageName}`;
}
return null;
}

export function createModuleCollector(props: {
entry: Entry;
findAdditionalModules: boolean;
Expand Down Expand Up @@ -284,55 +262,9 @@ export function createModuleCollector(props: {
// Check if this file is possibly from an npm package
// and if so, validate the import against the package.json exports
// and resolve the file path to the correct file.
if (args.path.includes("/") && !args.path.startsWith(".")) {
// get npm package name from string, taking into account scoped packages
const packageName = extractPackageName(args.path);
if (!packageName) {
throw new Error(
`Unable to extract npm package name from ${args.path}`
);
}
const packageJsonPath = path.join(
process.cwd(),
"node_modules",
packageName,
"package.json"
);
// Try and read the npm package's package.json
// and then resolve the import against the package's exports
// and then finally override filePath if we find a match.
try {
const packageJson = JSON.parse(
await readFile(packageJsonPath, "utf8")
);
const testResolved = resolveExports(
packageJson,
args.path.replace(`${packageName}/`, ""),
{
conditions: getBuildConditions(),
}
);
if (testResolved) {
filePath = path.join(
process.cwd(),
"node_modules",
packageName,
testResolved[0]
);
}
} catch (e) {
// We tried, now it'll just fall-through to the previous behaviour
// and ENOENT if the absolute file path doesn't exist.
}
}

// Next try to resolve using the node module resolution algorithm
try {
const resolved = resolveSync(args.path, {
basedir: args.resolveDir,
});
filePath = resolved;
} catch (e) {
filePath = require.resolve(args.path, { paths: [args.resolveDir] });
} catch (ex) {
// We tried, now it'll just fall-through to the previous behaviour
// and ENOENT if the absolute file path doesn't exist.
}
Expand Down
30 changes: 17 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5583934

Please sign in to comment.