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