Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.
1<div align="center">
2 <h2 align="center">graphql-web-lite</h2>
3 <p align="center"><strong>The small sibling of the <code>graphql</code> package, slimmed down for client-side libraries</strong></p>
4 <br />
5 <a href="https://npmjs.com/package/graphql-web-lite">
6 <img alt="NPM Version" src="https://img.shields.io/npm/v/graphql-web-lite.svg" />
7 </a>
8 <a href="https://npmjs.com/package/use-interactions">
9 <img alt="License" src="https://img.shields.io/npm/l/graphql-web-lite.svg" />
10 </a>
11 <a href="https://bundlephobia.com/result?p=graphql-web-lite">
12 <img alt="Minified gzip size" src="https://img.shields.io/bundlephobia/minzip/graphql-web-lite.svg?label=gzip%20size" />
13 </a>
14 <br />
15 <br />
16</div>
17
18The `graphql` package serves two purposes in being the reference implementation of the
19[GraphQL specification](https://spec.graphql.org/) and being used as the shared toolkit
20for implementing GraphQL in client-side and server-side JavaScript applications. This
21can cause bloat for client-side apps, where we'd rather choose lower bundlesize impact
22over fidelity.
23
24`graphql-web-lite` is an **experimental** library, providing an alias package that can
25be swapped in for the standard `graphql` package in client-side applications.
26It aims to reduce the size of imports that are in common use by GraphQL clients and
27users, while still providing most `graphql` exports that are used in other contexts.
28
29## Installation
30
31`graphql-web-lite` mirrors the folder structure of the regular `graphql` package and
32includes mostly the same files and imports as the `graphql` package, minus a couple
33that aren't commonly used for client-side GraphQL.
34This offers us several installation options, depending on how the package is aliased
35to the regular `"graphql"` import.
36
37<details>
38<summary><strong>Installation with <code>package.json</code> aliases</strong></summary>
39
40When your dependencies and `node_modules` folder isn't used by a _GraphQL server_ and
41only used by a _GraphQL clients_, you can use a quick and easy npm installation alias.
42In your `package.json` file you can define your `graphql` installation to use
43`graphql-web-lite` instead, which is supported by both Yarn and npm:
44
45```diff
46{
47 "dependencies": {
48- "graphql": "^15.5.0"
49+ "graphql": "npm:graphql-web-lite@^15.5.1001"
50 }
51}
52```
53
54Alternatively, you can run an installation command to alias the package:<br />
55
56```sh
57npm install --save graphql@npm:graphql-web-lite
58# or
59yarn add graphql@npm:graphql-web-lite
60```
61
62When this isn't suitable — for instance, because the same dependencies are shared
63with an API or server-side GraphQL consumer, or you're working inside a monorepo —
64you can try one of the other aliasing techniques below.
65
66</details>
67
68<details>
69<summary><strong>Installation with Webpack aliases</strong></summary>
70
71First, we'll need to install `graphql-web-lite` _alongside_ the regular `graphql`
72package.
73
74```sh
75npm install --save graphql-web-lite
76# or
77yarn add graphql-web-lite
78```
79
80To alias a package in Webpack, an entry must be added to your Webpack
81configuration's `resolve.alias` section. Depending on your implementation,
82the configuration may already contain some keys inside `resolve.alias`, and
83you'd want to add another entry for `"graphql"`.
84
85```js
86const webpackConfig = {
87 // ...
88 resolve: {
89 alias: {
90 graphql: 'graphql-web-lite',
91 },
92 },
93};
94```
95
96</details>
97
98<details>
99<summary><strong>Installation with Next.js</strong></summary>
100
101First, we'll need to install `graphql-web-lite` _alongside_ the regular `graphql`
102package.
103
104```sh
105npm install --save graphql-web-lite
106# or
107yarn add graphql-web-lite
108```
109
110In your [Next.js configuration file](https://nextjs.org/docs/api-reference/next.config.js/introduction),
111under `next.config.js`, you can add an additional `webpack()` function that is
112able to modify Next's Webpack configuration to add an alias for `graphql`.
113
114```js
115module.exports = {
116 webpack(config, { isServer }) {
117 if (!isServer) {
118 config.resolve.alias = {
119 ...config.resolve.alias,
120 graphql: 'graphql-web-lite',
121 };
122 }
123 return config;
124 },
125};
126```
127
128Here we're also ensuring that the alias isn't applied on the server-side, in case
129an API route is using `graphql` for a server-side GraphQL schema.
130
131</details>
132
133<details>
134<summary><strong>Installation with Rollup's alias plugin</strong></summary>
135
136First, we'll need to install `graphql-web-lite` _alongside_ the regular `graphql`
137package.
138
139```sh
140npm install --save graphql-web-lite
141# or
142yarn add graphql-web-lite
143```
144
145In Rollup, the easiest way to add a new alias is to use `@rollup/plugin-alias`.
146We'll have to install this plugin and ensure that every import and deep import
147to `graphql` is aliased to `graphql-web-lite`.
148
149Any Rollup-based build will fail when the import name of the package does not
150match the `name` field in the module's `package.json` file, so this step is
151necessary.
152
153```js
154import alias from '@rollup/plugin-alias';
155
156module.exports = {
157 plugins: [
158 alias({
159 entries: [{ find: 'graphql', replacement: 'graphql-web-lite' }],
160 }),
161 ],
162};
163```
164
165</details>
166
167<details>
168<summary><strong>Installation with Vite</strong></summary>
169
170First, we'll need to install `graphql-web-lite` _alongside_ the regular `graphql`
171package.
172
173```sh
174npm install --save graphql-web-lite
175# or
176yarn add graphql-web-lite
177```
178
179In your [Vite configuration file](https://vitejs.dev/config/#config-file-resolving)
180you may add a new entry for its `resolve.alias` entries. This entry works the same
181as Rollup's alias plugin.
182
183```js
184import { defineConfig } from 'vite';
185
186export default defineConfig({
187 resolve: {
188 alias: {
189 graphql: 'graphql-web-lite',
190 },
191 },
192});
193```
194
195Here we're also ensuring that the alias isn't applied on the server-side, in case
196an API route is using `graphql` for a server-side GraphQL schema.
197
198</details>
199
200<details>
201<summary><strong>Installation with Parcel</strong></summary>
202
203First, we'll need to install `graphql-web-lite` _alongside_ the regular `graphql`
204package.
205
206```sh
207npm install --save graphql-web-lite
208# or
209yarn add graphql-web-lite
210```
211
212In Parcel, we can add an entry in our `package.json` file for an alias. Specifically,
213the `alias` property may contain an object that maps packages to their aliases.
214
215```diff
216{
217 "alias": {
218+ "graphql": "graphql-web-lite"
219 }
220}
221```
222
223</details>
224
225<details>
226<summary><strong>Installation with Jest's module mapping</strong></summary>
227
228First, we'll need to install `graphql-web-lite` _alongside_ the regular `graphql`
229package.
230
231```sh
232npm install --save graphql-web-lite
233# or
234yarn add graphql-web-lite
235```
236
237Jest allows any module names to be remapped using regular expression-based
238mappings. In your Jest config you'll need to add an entry for `graphql` that
239remaps all imports and deep imports to `graphql-web-lite`.
240
241```json
242{
243 "moduleNameMapper": {
244 "graphql(.*)": "graphql-web-lite$1"
245 }
246}
247```
248
249</details>
250
251## Impact & Changes
252
253In short, most utilities, functions, and classes exported by the `graphql`
254package are only used for server-side GraphQL. Some of them have been removed
255in `graphql-web-lite` to discourage its server-side usage, and help bundlers
256exlude them if tree-shaking were to fail.
257
258Most GraphQL clients rely on importing the parser, printer, visitor, and the
259`GraphQLError` class. These have all been modified to reduce their bundlesize
260impact and to remove any support for
261[GraphQL's schema language and type system](https://spec.graphql.org/June2018/#sec-Type-System).
262
263Any debugging calls, development-time warnings, and other non-production code
264is also being transpiled away, and `process.env.NODE_ENV` has been compiled
265away.
266
267<details>
268<summary><strong>Full List of Changes</strong></summary>
269
270| Export | Changes | Notes |
271| -------------------------- | ----------- | ------------------------------------------------------------------- |
272| `getVisitFn` | _unchanged_ | n/a |
273| `visitInParallel` | _unchanged_ | n/a |
274| `BREAK` | _unchanged_ | n/a |
275| `visit` | _modified_ | works recursively and does not detect invalid AST nodes |
276| `print` | _modified_ | won't output any schema nodes and does not detect invalid AST nodes |
277| `printLocation` | _modified_ | won't output source snippets |
278| `printSourceLocation` | _modified_ | won't output source snippets |
279| `parse` | _modified_ | won't parse schema nodes or throw precise syntax errors |
280| `parseType` | _modified_ | won't throw precise syntax errors |
281| `parseValue` | _modified_ | won't throw precise syntax errors |
282| `GraphQLError` | _modified_ | doesn't handle locations and Error stacks |
283| `syntaxError` | _removed_ | n/a |
284| `printType` | _removed_ | n/a |
285| `printSchema` | _removed_ | n/a |
286| `printIntrospectionSchema` | _removed_ | n/a |
287| `lexicographicSortSchema` | _removed_ | n/a |
288| `isSchema` | _removed_ | n/a |
289| `isInterfaceType` | _removed_ | n/a |
290| `getDescription` | _removed_ | n/a |
291| `findDeprecatedUsages` | _removed_ | n/a |
292| `buildSchema` | _removed_ | n/a |
293| `buildASTSchema` | _removed_ | n/a |
294| `assertSchema` | _removed_ | n/a |
295| `assertInterfaceType` | _removed_ | n/a |
296| `assertCompositeType` | _removed_ | n/a |
297| `assertAbstractType` | _removed_ | n/a |
298| `TokenKind` | _removed_ | n/a |
299| `Token` | _removed_ | n/a |
300| `Lexer` | _removed_ | n/a |
301| `GraphQLUnionType` | _removed_ | n/a |
302| `GraphQLInterfaceType` | _removed_ | n/a |
303| `GraphQLInputObjectType` | _removed_ | n/a |
304
305</details>
306
307### Bundlesize Impact
308
309Most GraphQL client-side libraries use the following common set of imports from the `graphql` library.
310Assuming a transformation like [`babel-plugin-modular-graphql`](https://github.com/kitten/babel-plugin-modular-graphql/)
311or granular imports in general this creates a short list of utilities.
312
313```js
314export { valueFromASTUntyped } from 'graphql/utilities/valueFromASTUntyped.mjs';
315export { GraphQLError } from 'graphql/error/GraphQLError.mjs';
316export { Kind } from 'graphql/language/kinds.mjs';
317export { parse } from 'graphql/language/parser.mjs';
318export { print } from 'graphql/language/printer.mjs';
319export { visit } from 'graphql/language/visitor.mjs';
320```
321
322The minzipped size of the imports is about `11.2kB` in a given output bundle, which assumes all the above imports are
323in use. When the GraphQL language parser is dropped from the bundle, for instance by precompiling queries and excluding
324it in a compilation step, the resulting minzipped size drops to `5.55kB`.
325
326When `graphql-web-lite` replaces the `graphql` package the minzipped size drops from the `11.2kB` figure down to `5.44kB`,
327and `3.19kB` without the parser.