The graphql
package serves two purposes in being the reference implementation of the
GraphQL specification and being used as the shared toolkit
for implementing GraphQL in client-side and server-side JavaScript applications. This
can cause bloat for client-side apps, where we'd rather choose lower bundlesize impact
over fidelity.
graphql-web-lite
provides an alias package that can be swapped in for the standard
graphql
package in client-side applications.
It aims to reduce the size of imports that are in common use by GraphQL clients and
users, while still providing most graphql
exports that are used in other contexts.
It replaces the default language
exports with
@0no-co/graphql.web
for a leaner
parser, printer, and visitor, which only support the GraphQL query language and
are tested to 100% coverage and built to match GraphQL.js’ performance.
Installation
graphql-web-lite
mirrors the folder structure of the regular graphql
package and
includes mostly the same files and imports as the graphql
package, minus a couple
that aren't commonly used for client-side GraphQL.
This offers us several installation options, depending on how the package is aliased
to the regular "graphql"
import.
Installation with package.json
aliases
When your dependencies and node_modules
folder isn't used by a GraphQL server and
only used by a GraphQL clients, you can use a quick and easy npm installation alias.
In your package.json
file you can define your graphql
installation to use
graphql-web-lite
instead, which is supported by both Yarn and npm:
{
"dependencies": {
- "graphql": "^16.6.0"
+ "graphql": "npm:graphql-web-lite@^16.6.0-3"
}
}
Alternatively, you can run an installation command to alias the package:
npm install --save graphql@npm:graphql-web-lite
# or
yarn add graphql@npm:graphql-web-lite
When this isn't suitable — for instance, because the same dependencies are shared with an API or server-side GraphQL consumer, or you're working inside a monorepo — you can try one of the other aliasing techniques below.
Installation with Webpack aliases
First, we'll need to install graphql-web-lite
alongside the regular graphql
package.
npm install --save graphql-web-lite
# or
yarn add graphql-web-lite
To alias a package in Webpack, an entry must be added to your Webpack
configuration's resolve.alias
section. Depending on your implementation,
the configuration may already contain some keys inside resolve.alias
, and
you'd want to add another entry for "graphql"
.
const webpackConfig = {
// ...
resolve: {
alias: {
graphql: 'graphql-web-lite',
},
},
};
Installation with Next.js
First, we'll need to install graphql-web-lite
alongside the regular graphql
package.
npm install --save graphql-web-lite
# or
yarn add graphql-web-lite
In your Next.js configuration file,
under next.config.js
, you can add an additional webpack()
function that is
able to modify Next's Webpack configuration to add an alias for graphql
.
module.exports = {
webpack(config, { isServer }) {
if (!isServer) {
config.resolve.alias = {
...config.resolve.alias,
graphql: 'graphql-web-lite',
};
}
return config;
},
};
Here we're also ensuring that the alias isn't applied on the server-side, in case
an API route is using graphql
for a server-side GraphQL schema.
Installation with Rollup's alias plugin
First, we'll need to install graphql-web-lite
alongside the regular graphql
package.
npm install --save graphql-web-lite
# or
yarn add graphql-web-lite
In Rollup, the easiest way to add a new alias is to use @rollup/plugin-alias
.
We'll have to install this plugin and ensure that every import and deep import
to graphql
is aliased to graphql-web-lite
.
Any Rollup-based build will fail when the import name of the package does not
match the name
field in the module's package.json
file, so this step is
necessary.
import alias from '@rollup/plugin-alias';
module.exports = {
plugins: [
alias({
entries: [{ find: 'graphql', replacement: 'graphql-web-lite' }],
}),
],
};
Installation with Vite
First, we'll need to install graphql-web-lite
alongside the regular graphql
package.
npm install --save graphql-web-lite
# or
yarn add graphql-web-lite
In your Vite configuration file
you may add a new entry for its resolve.alias
entries. This entry works the same
as Rollup's alias plugin.
import { defineConfig } from 'vite';
export default defineConfig({
resolve: {
alias: {
graphql: 'graphql-web-lite',
},
},
});
Here we're also ensuring that the alias isn't applied on the server-side, in case
an API route is using graphql
for a server-side GraphQL schema.
Installation with Parcel
First, we'll need to install graphql-web-lite
alongside the regular graphql
package.
npm install --save graphql-web-lite
# or
yarn add graphql-web-lite
In Parcel, we can add an entry in our package.json
file for an alias. Specifically,
the alias
property may contain an object that maps packages to their aliases.
{
"alias": {
+ "graphql": "graphql-web-lite"
}
}
Installation with Jest's module mapping
First, we'll need to install graphql-web-lite
alongside the regular graphql
package.
npm install --save graphql-web-lite
# or
yarn add graphql-web-lite
Jest allows any module names to be remapped using regular expression-based
mappings. In your Jest config you'll need to add an entry for graphql
that
remaps all imports and deep imports to graphql-web-lite
.
{
"moduleNameMapper": {
"graphql(.*)": "graphql-web-lite$1"
}
}
Impact & Changes
In short, most utilities, functions, and classes exported by the graphql
package are only used for server-side GraphQL. Some of them have been removed
in graphql-web-lite
to discourage its server-side usage, and help bundlers
exlude them if tree-shaking were to fail.
Most GraphQL clients rely on importing the parser, printer, visitor, and the
GraphQLError
class. These have all been modified to reduce their bundlesize
impact and to remove any support for
GraphQL's schema language and type system.
Any debugging calls, development-time warnings, and other non-production code
is also being transpiled away, and process.env.NODE_ENV
has been compiled
away.
Full List of Changes
Export | Changes | Notes |
---|---|---|
visit |
modified | works recursively and does not detect invalid AST nodes |
print |
modified | won't output any schema nodes and does not detect invalid AST nodes |
printLocation |
modified | won't output source snippets |
printSourceLocation |
modified | won't output source snippets |
parse |
modified | won't parse schema nodes or throw precise syntax errors |
parseType |
modified | won't throw precise syntax errors |
parseValue |
modified | won't throw precise syntax errors |
GraphQLError |
modified | doesn't handle locations and Error stacks |
Bundlesize Impact
Most GraphQL client-side libraries use the following common set of imports from the graphql
library.
Assuming a transformation like babel-plugin-modular-graphql
or granular imports in general this creates a short list of utilities.
export { valueFromASTUntyped } from 'graphql/utilities/valueFromASTUntyped.mjs';
export { GraphQLError } from 'graphql/error/GraphQLError.mjs';
export { Kind } from 'graphql/language/kinds.mjs';
export { parse } from 'graphql/language/parser.mjs';
export { print } from 'graphql/language/printer.mjs';
export { visit } from 'graphql/language/visitor.mjs';
The minzipped size of the imports is about 11.2kB
in a given output bundle, which assumes all the above imports are
in use. When the GraphQL language parser is dropped from the bundle, for instance by precompiling queries and excluding
it in a compilation step, the resulting minzipped size drops to 5.55kB
.
When graphql-web-lite
replaces the graphql
package the minzipped size drops from the 11.2kB
figure down to 5.44kB
,
and 3.19kB
without the parser.