Bundle the generated client for distribution

There are situations where you want to share the generated client across teams, different repositories, or distribute it via NPM. This guide shows how to bundle the generated client into a single file that can be published to NPM, Github Packages or a private package registry.

Since the generated client depends on dynamic types for TypeScript operations, it's not possible to publish it as a library. Instead, we need to bundle the generated client so that it includes all (static) TypeScript types. In this guide we will use TSUP for bundling, it uses ESBuild under the hood and is very fast.

Prerequisites

This guide assumes you already have an existing WunderGraph project inside a monorepo. If you don't have a WunderGraph project yet, you can follow the Getting Started guide to create a new project.

There's an example repository available on GitHub .

Setup

The first thing we need to do is to create a new client package inside the monorepo.

Create a new client folder inside your packages folder (or any other folder you prefer, that is configured as a workspace) and add a package.json file with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"name": "@my-org/client",
"version": "1.0.0",
"description": "WunderGraph client",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": ["dist"],
"scripts": {
"build": "tsup"
},
"dependencies": {
"@wundergraph/sdk": "^0.149.1"
},
"devDependencies": {
"tsup": "^6.7.0",
"zod": "^3.22.3"
}
}

Zod is required to build TypeScript operation endpoints for the client.

Next we need a tsconfig.json file in the client folder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"compilerOptions": {
"target": "ESNext",
"module": "commonjs",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"types": ["zod"]
},
"include": ["../../gateway/.wundergraph/**/*.ts"]
}

The include path points to the the .wundergraph folder, where the generated client code is located. It's also required to add the zod type to the types array of the compilerOptions.

The last thing we need to do is to add a tsup.config.ts file to the client folder:

1
2
3
4
5
6
7
8
9
10
11
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['../../gateway/.wundergraph/generated/client.ts'],
splitting: false,
bundle: true,
clean: true,
dts: true,
outDir: 'dist',
format: ['cjs', 'esm'],
});
  • entry points to the generated client code in our gateway.
  • splitting is disabled because we want to bundle everything into a single file.
  • bundle is enabled to bundle all imports except dependencies into a single file, this is required so TypeScript operations types are included in the bundle.
  • clean is enabled to remove the dist folder before building.
  • dts is enabled to generate type definitions.
  • outDir is set to dist to output the bundled code into the dist folder
  • format is set to cjs and esm to generate CommonJS and ES Modules. Currently the WunderGraph SDK only supports CommonJS, but we plan to support ES Modules in the future.

Now we're almost set, the last thing to do is add a new build script to the workspace root package.json that will run the WunderGraph code generation and build the client:

1
2
3
4
5
6
7
8
{
"scripts": {
"generate": "pnpm run --filter gateway generate",
"build": "WG_PUBLIC_NODE_URL=https://api.my.org pnpm generate && pnpm build:client",
"build:client": "pnpm run --filter @my-org/client build",
"publish:client": "pnpm run --filter @my-org/client publish"
}
}

The WG_PUBLIC_NODE_URL is the URL of the WunderGraph gateway that will be used to generate the client code. It defaults to http://localhost:9991 if not set. You can also set it in a .env file. You should configure it to point to the production gateway URL in your CI/CD pipeline.

Now we're ready to build the client:

1
pnpm build

After building the client, it's ready to be shared with other teams, repositories or published to NPM.

In case your backend and frontend teams work in the same repository, but you want to use static typing for the frontend, you can also add the @my-org/client package as a dependency to the frontend workspace and import the generated client from there.

1
2
3
4
// inside the frontend workspace
import { createClient } from '@my-org/client';
export const client = createClient();

Distribute the client

If you want to share the client with other teams or repositories, you can create a tarball and share it manually or via CDN, or preferably publish it to a NPM registry.

Create a tarball

Inside packages/client run:

1
pnpm pack --pack-destination ./dir

Publish to NPM

To publish the client to npmjs.com or a private NPM registry, you can run:

1
pnpm publish

Or for private packages:

1
pnpm publish --registry https://npm.my-registry.com --access restricted

Learn More

Deploy to WunderGraph Cloud

Deploy to WunderGraph

Got Questions?

Join us on Discord!

Was this article helpful to you?
Provide feedback

Edit this page