Skip to content

Commit 3a62d82

Browse files
new __DEV__ handling (#10915)
Co-authored-by: Jerel Miller <[email protected]>
1 parent bbe61c2 commit 3a62d82

27 files changed

+182
-138
lines changed

.changeset/three-grapes-marry.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@apollo/client': minor
3+
---
4+
5+
Changes how development-only code is bundled in the library to more reliably enable consuming bundlers to reduce production bundle sizes while keeping compatibility with non-node environments.
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Compare Build Output
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
- release-*
7+
8+
concurrency: ${{ github.workflow }}-${{ github.ref }}
9+
10+
jobs:
11+
comparebuildoutput:
12+
name: Compare Build Output
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout repo
16+
uses: actions/checkout@v3
17+
with:
18+
# Fetch entire git history so we have the parent commit to compare against
19+
fetch-depth: 0
20+
- name: Setup Node.js 18.x
21+
uses: actions/setup-node@v3
22+
with:
23+
node-version: 18.x
24+
- name: Install dependencies (with cache)
25+
uses: bahmutov/npm-install@v1
26+
27+
- name: Run comparison script
28+
id: attw
29+
run: ./config/compare-build-output-to.sh $(git merge-base HEAD origin/${{ github.base_ref }}) > $GITHUB_STEP_SUMMARY
30+
env:
31+
RUNNER_TEMP: ${{ runner.temp }}

.github/workflows/size-limit.yml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
branches:
55
- main
66
- release-*
7+
- pr/*
78
jobs:
89
size:
910
runs-on: ubuntu-latest

.size-limit.cjs

+10-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ const checks = [
4444
"tslib",
4545
"zen-observable-ts"
4646
],
47-
}));
47+
})).flatMap((value) => value.path == "dist/apollo-client.min.cjs" ? value : [{...value, limit: undefined}, {
48+
...value,
49+
name: `${value.name} (production)`,
50+
modifyEsbuildConfig(config){
51+
config.define = {
52+
"globalThis.__DEV__": `false`,
53+
}
54+
return config
55+
}
56+
}]);
4857

4958
module.exports = checks;

config/compare-build-output-to.sh

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
upstream=$1
4+
comparison="${RUNNER_TEMP:-/tmp}/comparison_checkout"
5+
root=$(git rev-parse --show-toplevel)
6+
7+
temp=$(mktemp --tmpdir="${RUNNER_TEMP:-/tmp}")
8+
trap 'rm -f "$temp"' EXIT
9+
10+
patterndiff(){
11+
cd dist || { echo "dist folder not found"; exit 1; }
12+
count=0
13+
while IFS= read -r -d '' file
14+
do
15+
if ! filediff="$(diff <(tr "'" '"' < "$comparison/dist/$file") <(tr "'" '"' < "$root/dist/$file") -w)"; then
16+
(( count++ ))
17+
echo "$file"
18+
if [[ "$file" == *.min.* ]]; then
19+
echo "> Minified file differs."
20+
else
21+
echo "$filediff"
22+
fi
23+
fi
24+
done >"$temp" < <(find . -name "$1" -print0)
25+
26+
output="$(cat <"$temp")"
27+
28+
cat <<EOF
29+
30+
## differences in $1 files
31+
32+
<details>
33+
<summary>
34+
35+
### $count files with differences
36+
37+
</summary>
38+
39+
\`\`\`diff
40+
41+
$output
42+
43+
\`\`\`
44+
45+
</details>
46+
EOF
47+
48+
cd ..
49+
}
50+
51+
[ -z "$upstream" ] && { echo "need upstream argument"; exit 1; }
52+
53+
git worktree add --force --detach --checkout "$comparison" "$upstream" || { cd "$comparison" && git checkout "$upstream"; } || exit 1
54+
55+
cd "$comparison" || { echo "checkout failed"; exit 1; }
56+
cp -r "$root/node_modules" .
57+
npm i >&2
58+
git status >&2
59+
npm run build >&2
60+
cd "$root" || exit 1
61+
git status >&2
62+
npm run build >&2
63+
64+
set +e
65+
66+
patterndiff "*.js"
67+
patterndiff "*.cjs"
68+
patterndiff "*.d.ts"
69+
70+
cat <<EOF
71+
72+
73+
## differences in other files
74+
75+
<details>
76+
<summary>
77+
78+
### $(diff -qr "$comparison/dist" "dist" -x "*.map" -x "*.native.*" -x "*.js" -x "*.cjs" -x "*.d.ts" -w | wc -l) files with differences
79+
80+
</summary>
81+
82+
\`\`\`diff
83+
84+
$(diff -r "$comparison/dist" "dist" -x "*.map" -x "*.native.*" -x "*.js" -x "*.cjs" -x "*.d.ts" -w)
85+
86+
\`\`\`
87+
88+
</details>
89+
EOF

config/jest.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ const defaults = {
33
preset: "ts-jest",
44
testEnvironment: "jsdom",
55
setupFilesAfterEnv: ["<rootDir>/config/jest/setup.ts"],
6+
globals: {
7+
__DEV__: true,
8+
},
69
testEnvironmentOptions: {
710
url: "http://localhost",
811
},

config/postprocessDist.ts

+9-22
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ import * as path from "path";
33
import resolve from "resolve";
44
import { distDir, eachFile, reparse, reprint } from './helpers';
55

6+
const globalTypesFile = path.resolve(distDir, "utilities/globals/global.d.ts");
7+
fs.writeFileSync(globalTypesFile,
8+
fs.readFileSync(globalTypesFile, "utf8")
9+
.split("\n")
10+
.filter(line => line.trim() !== 'const __DEV__: boolean;')
11+
.join("\n"),
12+
"utf8"
13+
);
14+
615
// The primary goal of the 'npm run resolve' script is to make ECMAScript
716
// modules exposed by Apollo Client easier to consume natively in web browsers,
817
// without bundling, and without help from package.json files. It accomplishes
@@ -22,28 +31,6 @@ eachFile(distDir, (file, relPath) => new Promise((resolve, reject) => {
2231
const tr = new Transformer;
2332
const output = tr.transform(source, file);
2433

25-
if (
26-
/\b__DEV__\b/.test(source) &&
27-
// Ignore modules that reside within @apollo/client/utilities/globals.
28-
relPath.split(path.sep, 2).join("/") !== "utilities/globals"
29-
) {
30-
let importsUtilitiesGlobals = false;
31-
32-
tr.absolutePaths.forEach(absPath => {
33-
const distRelativePath =
34-
path.relative(distDir, absPath).split(path.sep).join("/");
35-
if (distRelativePath === "utilities/globals/index.js") {
36-
importsUtilitiesGlobals = true;
37-
}
38-
});
39-
40-
if (!importsUtilitiesGlobals) {
41-
reject(new Error(`Module ${
42-
relPath
43-
} uses __DEV__ but does not import @apollo/client/utilities/globals`));
44-
}
45-
}
46-
4734
if (source === output) {
4835
resolve(file);
4936
} else {

config/processInvariants.ts

+12-50
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,7 @@ function getErrorCode(
127127
}
128128

129129
function transform(code: string, relativeFilePath: string) {
130-
// If the code doesn't seem to contain anything invariant-related, we
131-
// can skip parsing and transforming it.
132-
if (!/invariant/i.test(code)) {
133-
return code;
134-
}
135-
136130
const ast = reparse(code);
137-
let addedDEV = false;
138131

139132
recast.visit(ast, {
140133
visitCallExpression(path) {
@@ -198,62 +191,31 @@ function transform(code: string, relativeFilePath: string) {
198191
if (isDEVLogicalAnd(path.parent.node)) {
199192
return newNode;
200193
}
201-
addedDEV = true;
202194
return b.logicalExpression('&&', makeDEVExpr(), newNode);
203195
}
204196
},
205197
});
206198

207-
if (addedDEV) {
208-
// Make sure there's an import { __DEV__ } from "../utilities/globals" or
209-
// similar declaration in any module where we injected __DEV__.
210-
let foundExistingImportDecl = false;
211-
199+
if (!['utilities/globals/index.js', 'config/jest/setup.js'].includes(relativeFilePath))
212200
recast.visit(ast, {
213-
visitImportDeclaration(path) {
201+
visitIdentifier(path) {
214202
this.traverse(path);
215203
const node = path.node;
216-
const importedModuleId = node.source.value;
217-
218-
// Normalize node.source.value relative to the current file.
219-
if (
220-
typeof importedModuleId === 'string' &&
221-
importedModuleId.startsWith('.')
222-
) {
223-
const normalized = posix.normalize(
224-
posix.join(posix.dirname(relativeFilePath), importedModuleId)
204+
if (isDEVExpr(node)) {
205+
return b.binaryExpression(
206+
'!==',
207+
b.memberExpression(
208+
b.identifier('globalThis'),
209+
b.identifier('__DEV__')
210+
),
211+
b.literal(false)
225212
);
226-
if (normalized === 'utilities/globals') {
227-
foundExistingImportDecl = true;
228-
if (
229-
node.specifiers?.some((s) =>
230-
isIdWithName(s.local || s.id, '__DEV__')
231-
)
232-
) {
233-
return false;
234-
}
235-
if (!node.specifiers) node.specifiers = [];
236-
node.specifiers.push(b.importSpecifier(b.identifier('__DEV__')));
237-
return false;
238-
}
239213
}
214+
215+
return node;
240216
},
241217
});
242218

243-
if (!foundExistingImportDecl) {
244-
// We could modify the AST to include a new import declaration, but since
245-
// this code is running at build time, we can simplify things by throwing
246-
// here, because we expect invariant and InvariantError to be imported
247-
// from the utilities/globals subpackage.
248-
throw new Error(
249-
`Missing import from "${posix.relative(
250-
posix.dirname(relativeFilePath),
251-
'utilities/globals'
252-
)} in ${relativeFilePath}`
253-
);
254-
}
255-
}
256-
257219
return reprint(ast);
258220
}
259221

config/rollup.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function prepareCJSMinified(input) {
9090
compress: {
9191
toplevel: true,
9292
global_defs: {
93-
'@__DEV__': 'false',
93+
'@globalThis.__DEV__': 'false',
9494
},
9595
},
9696
}),

src/cache/inmemory/__tests__/roundtrip.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { __DEV__ } from "../../../utilities/globals";
21
import { DocumentNode } from 'graphql';
32
import gql from 'graphql-tag';
43

src/cache/inmemory/object-canon.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { __DEV__ } from "../../utilities/globals";
21
import { Trie } from "@wry/trie";
32
import {
43
canUseWeakMap,

src/cache/inmemory/policies.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, newInvariantError, __DEV__ } from '../../utilities/globals';
1+
import { invariant, newInvariantError } from '../../utilities/globals';
22

33
import type {
44
InlineFragmentNode,

src/cache/inmemory/readFromStore.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, newInvariantError, __DEV__ } from '../../utilities/globals';
1+
import { invariant, newInvariantError } from '../../utilities/globals';
22

33
import type {
44
DocumentNode,

src/cache/inmemory/writeToStore.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, newInvariantError, __DEV__ } from '../../utilities/globals';
1+
import { invariant, newInvariantError } from '../../utilities/globals';
22
import { equal } from '@wry/equality';
33
import { Trie } from '@wry/trie';
44
import type {

src/core/ApolloClient.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, newInvariantError, __DEV__ } from '../utilities/globals';
1+
import { invariant, newInvariantError } from '../utilities/globals';
22

33
import type { ExecutionResult, DocumentNode } from 'graphql';
44

src/core/ObservableQuery.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, __DEV__ } from '../utilities/globals';
1+
import { invariant } from '../utilities/globals';
22
import type { DocumentNode } from 'graphql';
33
import { equal } from '@wry/equality';
44

src/core/QueryManager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, newInvariantError, __DEV__ } from '../utilities/globals';
1+
import { invariant, newInvariantError } from '../utilities/globals';
22

33
import type { DocumentNode } from 'graphql';
44
// TODO(brian): A hack until this issue is resolved (https://github.com/graphql/graphql-js/issues/3356)

src/core/index.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
/* Core */
22

3-
import { __DEV__ } from '../utilities/globals';
4-
53
export {
64
ApolloClient,
75
ApolloClientOptions,

src/link/http/createHttpLink.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { __DEV__, invariant } from '../../utilities/globals';
1+
import { invariant } from '../../utilities/globals';
22

33
import type { DefinitionNode } from 'graphql';
44

src/react/hoc/__tests__/queries/recomposeWithState.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// to avoid incurring an indirect dependency on ua-parser-js via fbjs.
33

44
import React, { createFactory, Component } from "react";
5-
import { __DEV__ } from "../../../../utilities/globals";
65

76
const setStatic =
87
(key: string, value: string) => (BaseComponent: React.ComponentClass) => {

src/react/hooks/useSuspenseQuery.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, __DEV__ } from '../../utilities/globals';
1+
import { invariant } from '../../utilities/globals';
22
import { useRef, useCallback, useMemo, useEffect, useState } from 'react';
33
import type {
44
ApolloClient,

src/react/hooks/useSyncExternalStore.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant, __DEV__ } from '../../utilities/globals';
1+
import { invariant } from '../../utilities/globals';
22
import * as React from 'react';
33

44
import { canUseLayoutEffect } from '../../utilities';
@@ -33,7 +33,7 @@ export const useSyncExternalStore: RealUseSESHookType = realHook || ((
3333
// always synchronous.
3434
const value = getSnapshot();
3535
if (
36-
// DEVIATION: Using our own __DEV__ polyfill (from ../../utilities/globals).
36+
// DEVIATION: Using __DEV__
3737
__DEV__ &&
3838
!didWarnUncachedGetSnapshot &&
3939
// DEVIATION: Not using Object.is because we know our snapshots will never

0 commit comments

Comments
 (0)