diff --git a/.changeset/thick-ties-glow.md b/.changeset/thick-ties-glow.md new file mode 100644 index 000000000000..7932bced48bb --- /dev/null +++ b/.changeset/thick-ties-glow.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +Revert support for custom unenv resolve path to address an issue with Wrangler failing to deploy Pages projects with `nodejs_compat_v2` in some cases diff --git a/fixtures/nodejs-hybrid-app/tests/index.test.ts b/fixtures/nodejs-hybrid-app/tests/index.test.ts index da7e2f26f0ec..fb46992c03c9 100644 --- a/fixtures/nodejs-hybrid-app/tests/index.test.ts +++ b/fixtures/nodejs-hybrid-app/tests/index.test.ts @@ -64,7 +64,7 @@ describe("nodejs compat", () => { } }); - test("require unenv aliased packages", async ({ expect }) => { + test("import unenv aliased packages", async ({ expect }) => { const { ip, port, stop } = await runWranglerDev( resolve(__dirname, "../src"), ["--port=0", "--inspector-port=0"] diff --git a/packages/wrangler/package.json b/packages/wrangler/package.json index 7f222f6c64e2..3a49ac019072 100644 --- a/packages/wrangler/package.json +++ b/packages/wrangler/package.json @@ -83,7 +83,7 @@ "resolve": "^1.22.8", "selfsigned": "^2.0.1", "source-map": "^0.6.1", - "unenv": "npm:unenv-nightly@2.0.0-20241212-153011-af71c96", + "unenv": "npm:unenv-nightly@2.0.0-20241204-140205-a5d5190", "workerd": "1.20241205.0", "xxhash-wasm": "^1.0.1" }, diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index 5488768ef321..9c8089be5392 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -10310,7 +10310,7 @@ export default{ fs.writeFileSync( "index.js", ` - import path from 'node:path'; + import path from 'path'; console.log(path); export default {} ` @@ -10331,7 +10331,7 @@ export default{ } `); expect(fs.readFileSync("dist/index.js", { encoding: "utf-8" })).toContain( - `import path from "node:path";` + `import path from "path";` ); }); diff --git a/packages/wrangler/src/deployment-bundle/bundle.ts b/packages/wrangler/src/deployment-bundle/bundle.ts index bb35d4519de8..c5f920d03d0a 100644 --- a/packages/wrangler/src/deployment-bundle/bundle.ts +++ b/packages/wrangler/src/deployment-bundle/bundle.ts @@ -5,7 +5,6 @@ import * as esbuild from "esbuild"; import { getBuildConditionsFromEnv, getBuildPlatformFromEnv, - getUnenvResolvePathsFromEnv, } from "../environment-variables/misc-variables"; import { UserError } from "../errors"; import { getFlag } from "../experimental-flags"; @@ -391,8 +390,6 @@ export async function bundleWorker( }, }; - const unenvResolvePaths = getUnenvResolvePathsFromEnv()?.split(","); - const buildOptions: esbuild.BuildOptions & { metafile: true } = { // Don't use entryFile here as the file may have been changed when applying the middleware entryPoints: [entry.file], @@ -438,10 +435,7 @@ export async function bundleWorker( plugins: [ aliasPlugin, moduleCollector.plugin, - ...getNodeJSCompatPlugins({ - mode: nodejsCompatMode ?? null, - unenvResolvePaths, - }), + ...getNodeJSCompatPlugins(nodejsCompatMode ?? null), cloudflareInternalPlugin, buildResultPlugin, ...(plugins || []), diff --git a/packages/wrangler/src/deployment-bundle/esbuild-plugins/hybrid-nodejs-compat.ts b/packages/wrangler/src/deployment-bundle/esbuild-plugins/hybrid-nodejs-compat.ts index 052039086953..e5a6ff9960f8 100644 --- a/packages/wrangler/src/deployment-bundle/esbuild-plugins/hybrid-nodejs-compat.ts +++ b/packages/wrangler/src/deployment-bundle/esbuild-plugins/hybrid-nodejs-compat.ts @@ -1,45 +1,25 @@ import { builtinModules } from "node:module"; import nodePath from "node:path"; import dedent from "ts-dedent"; -import { cloudflare, defineEnv } from "unenv"; +import { cloudflare, env, nodeless } from "unenv"; import { getBasePath } from "../../paths"; import type { Plugin, PluginBuild } from "esbuild"; const REQUIRED_NODE_BUILT_IN_NAMESPACE = "node-built-in-modules"; const REQUIRED_UNENV_ALIAS_NAMESPACE = "required-unenv-alias"; -/** - * ESBuild plugin to apply the unenv preset. - * - * @param unenvResolvePaths Root paths used to resolve absolute paths. - * @returns ESBuild plugin - */ -export function nodejsHybridPlugin(unenvResolvePaths?: string[]): Plugin { - // Get the resolved environment. - const { env } = defineEnv({ - nodeCompat: true, - presets: [cloudflare], - resolve: { - paths: unenvResolvePaths, - }, - }); - const { alias, inject, external } = env; - // Get the unresolved alias. - const unresolvedAlias = defineEnv({ - nodeCompat: true, - presets: [cloudflare], - resolve: false, - }).env.alias; +export const nodejsHybridPlugin: () => Plugin = () => { + const { alias, inject, external } = env(nodeless, cloudflare); return { name: "hybrid-nodejs_compat", setup(build) { errorOnServiceWorkerFormat(build); handleRequireCallsToNodeJSBuiltins(build); - handleUnenvAliasedPackages(build, unresolvedAlias, alias, external); + handleUnenvAliasedPackages(build, alias, external); handleNodeJSGlobals(build, inject); }, }; -} +}; const NODEJS_MODULES_RE = new RegExp(`^(node:)?(${builtinModules.join("|")})$`); @@ -107,41 +87,45 @@ function handleRequireCallsToNodeJSBuiltins(build: PluginBuild) { ); } -/** - * Handles aliased NPM packages. - * - * @param build ESBuild PluginBuild. - * @param unresolvedAlias Unresolved aliases from the presets. - * @param alias Aliases resolved to absolute paths. - * @param external external modules. - */ function handleUnenvAliasedPackages( build: PluginBuild, - unresolvedAlias: Record, alias: Record, external: string[] ) { - const UNENV_ALIAS_RE = new RegExp(`^(${Object.keys(alias).join("|")})$`); + // esbuild expects alias paths to be absolute + const aliasAbsolute: Record = {}; + for (const [module, unresolvedAlias] of Object.entries(alias)) { + try { + aliasAbsolute[module] = require + .resolve(unresolvedAlias) + .replace(/\.cjs$/, ".mjs"); + } catch (e) { + // this is an alias for package that is not installed in the current app => ignore + } + } + + const UNENV_ALIAS_RE = new RegExp( + `^(${Object.keys(aliasAbsolute).join("|")})$` + ); build.onResolve({ filter: UNENV_ALIAS_RE }, (args) => { - const unresolved = unresolvedAlias[args.path]; + const unresolvedAlias = alias[args.path]; // Convert `require()` calls for NPM packages to a virtual ES Module that can be imported avoiding the require calls. // Note: Does not apply to Node.js packages that are handled in `handleRequireCallsToNodeJSBuiltins` if ( args.kind === "require-call" && - (unresolved.startsWith("unenv/runtime/npm/") || - unresolved.startsWith("unenv/runtime/mock/")) + (unresolvedAlias.startsWith("unenv/runtime/npm/") || + unresolvedAlias.startsWith("unenv/runtime/mock/")) ) { return { path: args.path, namespace: REQUIRED_UNENV_ALIAS_NAMESPACE, }; } - // Resolve the alias to its absolute path and potentially mark it as external return { - path: alias[args.path], - external: external.includes(unresolved), + path: aliasAbsolute[args.path], + external: external.includes(unresolvedAlias), }; }); diff --git a/packages/wrangler/src/deployment-bundle/esbuild-plugins/nodejs-plugins.ts b/packages/wrangler/src/deployment-bundle/esbuild-plugins/nodejs-plugins.ts index 30448b347f9f..b59d8fa190d7 100644 --- a/packages/wrangler/src/deployment-bundle/esbuild-plugins/nodejs-plugins.ts +++ b/packages/wrangler/src/deployment-bundle/esbuild-plugins/nodejs-plugins.ts @@ -10,13 +10,7 @@ import type { NodeJSCompatMode } from "miniflare"; /** * Returns the list of ESBuild plugins to use for a given compat mode. */ -export function getNodeJSCompatPlugins({ - mode, - unenvResolvePaths, -}: { - mode: NodeJSCompatMode; - unenvResolvePaths?: string[]; -}): Plugin[] { +export function getNodeJSCompatPlugins(mode: NodeJSCompatMode): Plugin[] { switch (mode) { case "als": return [asyncLocalStoragePlugin, nodejsCompatPlugin(mode)]; @@ -30,7 +24,7 @@ export function getNodeJSCompatPlugins({ case "v1": return [nodejsCompatPlugin(mode)]; case "v2": - return [nodejsHybridPlugin(unenvResolvePaths)]; + return [nodejsHybridPlugin()]; case null: return [nodejsCompatPlugin(mode)]; } diff --git a/packages/wrangler/src/environment-variables/factory.ts b/packages/wrangler/src/environment-variables/factory.ts index 8a2124386ff7..91d481ed3a6f 100644 --- a/packages/wrangler/src/environment-variables/factory.ts +++ b/packages/wrangler/src/environment-variables/factory.ts @@ -25,7 +25,6 @@ type VariableNames = | "WRANGLER_CI_MATCH_TAG" | "WRANGLER_BUILD_CONDITIONS" | "WRANGLER_BUILD_PLATFORM" - | "WRANGLER_UNENV_RESOLVE_PATHS" | "WRANGLER_REGISTRY_PATH"; type DeprecatedNames = diff --git a/packages/wrangler/src/environment-variables/misc-variables.ts b/packages/wrangler/src/environment-variables/misc-variables.ts index 3af8754f4664..a19426a316c0 100644 --- a/packages/wrangler/src/environment-variables/misc-variables.ts +++ b/packages/wrangler/src/environment-variables/misc-variables.ts @@ -126,19 +126,6 @@ export const getBuildPlatformFromEnv = getEnvironmentVariableFactory({ variableName: "WRANGLER_BUILD_PLATFORM", }); -/** - * `WRANGLER_UNENV_RESOLVE_PATHS` lists the paths used to resolve unenv. - * - * Note: multiple comma separated paths can be specified. - * - * By default wrangler uses the unenv preset version installed from the package.json. - * - * Setting root paths allow to use a different version of the preset. - */ -export const getUnenvResolvePathsFromEnv = getEnvironmentVariableFactory({ - variableName: "WRANGLER_UNENV_RESOLVE_PATHS", -}); - /** * `WRANGLER_REGISTRY_PATH` specifies the file based dev registry folder */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abb9fdfa83b8..82e4e781d402 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1812,8 +1812,8 @@ importers: specifier: ^0.6.1 version: 0.6.1 unenv: - specifier: npm:unenv-nightly@2.0.0-20241212-153011-af71c96 - version: unenv-nightly@2.0.0-20241212-153011-af71c96 + specifier: npm:unenv-nightly@2.0.0-20241204-140205-a5d5190 + version: unenv-nightly@2.0.0-20241204-140205-a5d5190 workerd: specifier: 1.20241205.0 version: 1.20241205.0 @@ -9602,9 +9602,6 @@ packages: unenv-nightly@2.0.0-20241204-140205-a5d5190: resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==} - unenv-nightly@2.0.0-20241212-153011-af71c96: - resolution: {integrity: sha512-Yugb9yPs/EZsPOY+IHloqVVEcZeJ0uwwViTedsZjOtVeYO8I29B1rzU/p84FMT0R1Ht3bHsKkNV/rzrjSd07QA==} - unenv-nightly@2.0.0-20241216-144314-7e05819: resolution: {integrity: sha512-HpRspwDDxEwb6f9jOJYdL8iuZ054GIJ61LWHui7FPcgSVUPIXjZ3Nf0bh0qVIEqSGb3bNU/C1Zcw6fKHVl4lDg==} @@ -16181,7 +16178,7 @@ snapshots: miniflare@3.20241205.0: dependencies: '@cspotcode/source-map-support': 0.8.1 - acorn: 8.14.0 + acorn: 8.11.3 acorn-walk: 8.3.2 capnp-ts: 0.7.0(patch_hash=l4yimnxyvkiyj6alnps2ec3sii) exit-hook: 2.2.1 @@ -18502,7 +18499,7 @@ snapshots: mkdist: 1.6.0(typescript@5.6.3)(vue-tsc@2.0.29(typescript@5.6.3)) mlly: 1.7.3 pathe: 1.1.2 - pkg-types: 1.2.1 + pkg-types: 1.0.3 pretty-bytes: 6.1.1 rollup: 3.29.5 rollup-plugin-dts: 6.1.1(rollup@3.29.5)(typescript@5.6.3) @@ -18545,14 +18542,6 @@ snapshots: pathe: 1.1.2 ufo: 1.5.4 - unenv-nightly@2.0.0-20241212-153011-af71c96: - dependencies: - defu: 6.1.4 - mlly: 1.7.3 - ohash: 1.1.4 - pathe: 1.1.2 - ufo: 1.5.4 - unenv-nightly@2.0.0-20241216-144314-7e05819: dependencies: defu: 6.1.4