Skip to content

Commit

Permalink
Normalize 'ts-invariant/process' again in config/resolveModuleIds.ts.
Browse files Browse the repository at this point in the history
From @apollo/client@3.5.0 until my recent PR #9073 (v3.5.3),
non-relative imported module identifiers like 'ts-invariant/process'
were rewritten during the build process (during 'npm run resolve') to
include a specific module with a file extension (not a directory),
producing in this example 'ts-invariant/process/index.js'.

That rewriting was the wrong choice in general (for example, it would
rewrite 'graphql' to 'graphql/index.mjs'), so PR #9073 disabled it for
all non-relative imports.

However, the specific replacement of 'ts-invariant/process' with
'ts-invariant/process/index.js' is still useful to prevent the strange
webpack 5-specific error

  The request 'ts-invariant/process' failed to resolve only because it was resolved as fully specified

which apparently happens because the
[resolve.fullySpecified](https://webpack.js.org/configuration/module/#resolvefullyspecified)
option is true by default now, and 'ts-invariant/process/package.json'
is ignored, effectively forbidding directory-style imports like
'ts-invariant/process' when the package.json of the enclosing package
has `"type": "module"` (which became true in Apollo Client v3.5, thanks
to #8396). App developers could configure resolve.fullySpecified
explicitly false, but we (the Apollo Client team) prefer a general
workaround.
  • Loading branch information
benjamn committed Nov 18, 2021
1 parent 30f0b67 commit c767c02
Showing 1 changed file with 31 additions and 6 deletions.
37 changes: 31 additions & 6 deletions config/resolveModuleIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import * as path from "path";
import resolve from "resolve";
import { distDir, eachFile, reparse, reprint } from './helpers';

// The primary goal of the 'npm run resolve' script is to make ECMAScript
// modules exposed by Apollo Client easier to consume natively in web browsers,
// without bundling, and without help from package.json files. It accomplishes
// this goal by rewriting internal ./ and ../ (relative) imports to refer to a
// specific ESM module (not a directory), including its file extension. Because
// of this limited goal, this script only touches ESM modules that have .js file
// extensions, not .cjs CommonJS bundles.

// A secondary goal of this script is to enforce that any module using the
// __DEV__ global constant imports the @apollo/client/utilities/globals polyfill
// module first.

eachFile(distDir, (file, relPath) => new Promise((resolve, reject) => {
fs.readFile(file, "utf8", (error, source) => {
if (error) return reject(error);
Expand Down Expand Up @@ -83,12 +95,25 @@ class Transformer {
}

normalizeSourceString(file: string, source?: Node | null) {
if (source && n.StringLiteral.check(source) && this.isRelative(source.value)) {
try {
source.value = this.normalizeId(source.value, file);
} catch (error) {
console.error(`Failed to resolve ${source.value} in ${file} with error ${error}`);
process.exit(1);
if (source && n.StringLiteral.check(source)) {
// We mostly only worry about normalizing _relative_ module identifiers,
// which start with a ./ or ../ and refer to other modules within the
// @apollo/client package, but we also manually normalize one non-relative
// identifier, ts-invariant/process, to prevent webpack 5 errors
// containing the phrase "failed to resolve only because it was resolved
// as fully specified," referring to webpack's resolve.fullySpecified
// option, which is apparently now true by default when the enclosing
// package's package.json file has "type": "module" (which became true for
// Apollo Client in v3.5).
if (source.value.split("/", 2).join("/") === "ts-invariant/process") {
source.value = "ts-invariant/process/index.js";
} else if (this.isRelative(source.value)) {
try {
source.value = this.normalizeId(source.value, file);
} catch (error) {
console.error(`Failed to resolve ${source.value} in ${file} with error ${error}`);
process.exit(1);
}
}
}
}
Expand Down

0 comments on commit c767c02

Please sign in to comment.