diff --git a/.changeset/add-graphiql-cdn-package.md b/.changeset/add-graphiql-cdn-package.md
new file mode 100644
index 00000000000..1c8c9cae626
--- /dev/null
+++ b/.changeset/add-graphiql-cdn-package.md
@@ -0,0 +1,5 @@
+---
+'@graphiql/cdn': major
+---
+
+Initial release. `@graphiql/cdn` is a pre-bundled CDN distribution of GraphiQL: a single ESM file (`dist/graphiql.js`) that loads in the browser from any static CDN with no build step, no importmap entries for transitive dependencies, and no third-party bundler in the request path. The package inlines `graphiql`, `@graphiql/react`, `@graphiql/plugin-explorer`, `@graphiql/toolkit`, and `graphql`; `react` and `react-dom` stay external. Monaco workers are emitted to `dist/workers/*` and loaded from the same origin as the bundle.
diff --git a/packages/graphiql-cdn/README.md b/packages/graphiql-cdn/README.md
new file mode 100644
index 00000000000..ab1ca0d8b52
--- /dev/null
+++ b/packages/graphiql-cdn/README.md
@@ -0,0 +1,76 @@
+# `@graphiql/cdn`
+
+A pre-bundled CDN distribution of [GraphiQL](https://github.com/graphql/graphiql). Load GraphiQL in a browser from a static CDN with no build step, no importmap, and no third-party bundler in the request path.
+
+The package ships a single ESM file (`dist/graphiql.js`) with the GraphiQL UI, the default plugins, and all dependencies inlined. `react` and `react-dom` stay external and must be supplied by the page.
+
+## Usage
+
+```html
+
+
+
+
+ GraphiQL
+
+
+
+
+
+
+
+
+
+```
+
+Pin a specific `` for production use.
+
+## What is exported
+
+- `GraphiQL` — the main component (also the default export)
+- `HISTORY_PLUGIN` — the history plugin instance
+- `explorerPlugin` — the schema explorer plugin factory
+- `createGraphiQLFetcher` — convenience fetcher for `GraphiQL`'s `fetcher` prop
+- `createLocalStorage` — convenience storage factory for multi-instance pages
+- `GraphiQLReact` — the full `@graphiql/react` namespace, for advanced customization
+- `GraphQL` — the full `graphql-js` namespace, so plugins can reuse the same instance
+
+## When not to use this package
+
+If you have a build step (Vite, webpack, Next.js, etc.), install `graphiql` and the plugins you want from npm directly. This package exists for the no-build-step CDN use case.
diff --git a/packages/graphiql-cdn/package.json b/packages/graphiql-cdn/package.json
new file mode 100644
index 00000000000..e3cacf15665
--- /dev/null
+++ b/packages/graphiql-cdn/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "@graphiql/cdn",
+ "version": "0.0.0",
+ "description": "Pre-bundled CDN distribution of GraphiQL: load GraphiQL in a browser from a static CDN with no build step.",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/graphql/graphiql",
+ "directory": "packages/graphiql-cdn"
+ },
+ "homepage": "https://github.com/graphql/graphiql/tree/main/packages/graphiql-cdn#readme",
+ "bugs": {
+ "url": "https://github.com/graphql/graphiql/issues?q=issue+label:@graphiql/cdn"
+ },
+ "license": "MIT",
+ "type": "module",
+ "main": "dist/graphiql.js",
+ "module": "dist/graphiql.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist"
+ ],
+ "exports": {
+ "./package.json": "./package.json",
+ "./style.css": "./dist/style.css",
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/graphiql.js"
+ }
+ },
+ "scripts": {
+ "types:check": "tsgo --noEmit",
+ "build": "vite build"
+ },
+ "peerDependencies": {
+ "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0-alpha.2 || ^17.0.0",
+ "react": "^18 || ^19",
+ "react-dom": "^18 || ^19"
+ },
+ "dependencies": {
+ "@graphiql/plugin-explorer": "^5.1.1",
+ "@graphiql/react": "^0.37.0",
+ "@graphiql/toolkit": "^0.12.0",
+ "graphiql": "^5.2.0"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-react": "^4",
+ "lightningcss": "^1.30.1",
+ "react": "^19",
+ "react-dom": "^19",
+ "terser": "^5",
+ "vite": "^6",
+ "vite-plugin-dts": "^4.5.4"
+ }
+}
diff --git a/packages/graphiql-cdn/src/env.d.ts b/packages/graphiql-cdn/src/env.d.ts
new file mode 100644
index 00000000000..2a3c835b1e3
--- /dev/null
+++ b/packages/graphiql-cdn/src/env.d.ts
@@ -0,0 +1,7 @@
+///
+declare module '*.css';
+
+declare namespace globalThis {
+ import type * as monaco from 'monaco-editor';
+ var MonacoEnvironment: monaco.Environment | undefined;
+}
diff --git a/packages/graphiql-cdn/src/index.ts b/packages/graphiql-cdn/src/index.ts
new file mode 100644
index 00000000000..ef4c57c429d
--- /dev/null
+++ b/packages/graphiql-cdn/src/index.ts
@@ -0,0 +1,22 @@
+import * as GraphiQLReact from '@graphiql/react';
+import { explorerPlugin } from '@graphiql/plugin-explorer';
+import { createGraphiQLFetcher, createLocalStorage } from '@graphiql/toolkit';
+import * as GraphQL from 'graphql';
+import { GraphiQL, HISTORY_PLUGIN } from 'graphiql';
+import 'graphiql/style.css';
+import '@graphiql/plugin-explorer/style.css';
+// Configure MonacoEnvironment with workers inlined as blob URLs, so the
+// bundle can be loaded from a CDN onto pages of any origin.
+import './setup-workers.js';
+
+export {
+ GraphiQL,
+ HISTORY_PLUGIN,
+ GraphiQLReact,
+ GraphQL,
+ createGraphiQLFetcher,
+ createLocalStorage,
+ explorerPlugin,
+};
+
+export default GraphiQL;
diff --git a/packages/graphiql-cdn/src/setup-workers.ts b/packages/graphiql-cdn/src/setup-workers.ts
new file mode 100644
index 00000000000..66fb658f33d
--- /dev/null
+++ b/packages/graphiql-cdn/src/setup-workers.ts
@@ -0,0 +1,24 @@
+/**
+ * CDN-targeted Monaco worker setup. Workers are inlined as blob URLs
+ * (Vite's `?worker&inline`) so the spawning page can be any origin: there
+ * is no cross-origin `new Worker(url)` to fail.
+ *
+ * Equivalent to `@graphiql/react/setup-workers/vite`, but with `&inline`
+ * because the consumer-side bundler isn't in the picture.
+ */
+/* eslint-disable import-x/default -- false positive */
+import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker&inline';
+import GraphQLWorker from 'monaco-graphql/esm/graphql.worker.js?worker&inline';
+import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker&inline';
+
+globalThis.MonacoEnvironment = {
+ getWorker(_workerId: string, label: string) {
+ switch (label) {
+ case 'json':
+ return new JsonWorker();
+ case 'graphql':
+ return new GraphQLWorker();
+ }
+ return new EditorWorker();
+ },
+};
diff --git a/packages/graphiql-cdn/tsconfig.json b/packages/graphiql-cdn/tsconfig.json
new file mode 100644
index 00000000000..ee54eec68ce
--- /dev/null
+++ b/packages/graphiql-cdn/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../graphiql-react/tsconfig.json"
+}
diff --git a/packages/graphiql-cdn/vite.config.mts b/packages/graphiql-cdn/vite.config.mts
new file mode 100644
index 00000000000..a1591f98031
--- /dev/null
+++ b/packages/graphiql-cdn/vite.config.mts
@@ -0,0 +1,75 @@
+import { defineConfig } from 'vite';
+import dts from 'vite-plugin-dts';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ // Emit relative asset/worker URLs so the bundle can be served from any
+ // CDN path (jsdelivr/unpkg/esm.sh `?raw`) rather than only the origin root.
+ // Without this, Vite hard-codes `new Worker("/workers/json.worker.js", ...)`
+ // which resolves to `https:///workers/...` (404) instead of
+ // `https:///.../dist/workers/...`.
+ base: './',
+ define: {
+ // graphql v17
+ 'globalThis.process.env.NODE_ENV': 'true',
+ // https://github.com/graphql/graphql-js/blob/16.x.x/website/pages/docs/going-to-production.mdx
+ 'globalThis.process': 'true',
+ 'process.env.NODE_ENV': '"production"',
+ },
+ plugins: [
+ react(),
+ dts({
+ include: ['src/**'],
+ outDir: ['dist'],
+ }),
+ ],
+ css: {
+ transformer: 'lightningcss',
+ },
+ build: {
+ minify: 'terser',
+ sourcemap: true,
+ lib: {
+ entry: 'src/index.ts',
+ formats: ['es'],
+ fileName: 'graphiql',
+ cssFileName: 'style',
+ },
+ rollupOptions: {
+ external: id =>
+ id === 'react' ||
+ id.startsWith('react/') ||
+ id === 'react-dom' ||
+ id.startsWith('react-dom/') ||
+ id === 'graphql' ||
+ id.startsWith('graphql/'),
+ output: {
+ // Inline every lazy `import(...)` into the main bundle. Critical for
+ // the CDN use case: monaco-editor's language contributions lazy-load
+ // their tokenizers via dynamic imports; if those land in separate
+ // chunks they ship as separate URLs that fragment monaco-editor into
+ // multiple instances at runtime. A single self-contained file
+ // guarantees one instance.
+ inlineDynamicImports: true,
+ },
+ },
+ },
+ worker: {
+ format: 'es',
+ rollupOptions: {
+ output: {
+ entryFileNames: 'workers/[name].js',
+ // Just to group worker assets, add shared/internal chunks too
+ chunkFileNames: 'workers/[name].js',
+ // Workers are inlined as blob URLs (Vite's `?worker&inline`). The
+ // default sourcemap setting writes a `.js.map` next to the worker
+ // and appends `//# sourceMappingURL=foo.worker.js.map` to the
+ // source — but blob URLs have no real origin, so the comment
+ // resolves to `blob://nullnull/foo.worker.js.map` and the browser
+ // logs a CORS/local-resource error trying to fetch it. Suppress
+ // worker sourcemaps to keep the consumer's console clean.
+ sourcemap: false,
+ },
+ },
+ },
+});
diff --git a/yarn.lock b/yarn.lock
index 6ddce0fc312..40172f20952 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3008,6 +3008,28 @@ __metadata:
languageName: node
linkType: hard
+"@graphiql/cdn@workspace:packages/graphiql-cdn":
+ version: 0.0.0-use.local
+ resolution: "@graphiql/cdn@workspace:packages/graphiql-cdn"
+ dependencies:
+ "@graphiql/plugin-explorer": "npm:^5.1.1"
+ "@graphiql/react": "npm:^0.37.0"
+ "@graphiql/toolkit": "npm:^0.12.0"
+ "@vitejs/plugin-react": "npm:^4"
+ graphiql: "npm:^5.2.0"
+ lightningcss: "npm:^1.30.1"
+ react: "npm:^19"
+ react-dom: "npm:^19"
+ terser: "npm:^5"
+ vite: "npm:^6"
+ vite-plugin-dts: "npm:^4.5.4"
+ peerDependencies:
+ graphql: ^15.5.0 || ^16.0.0 || ^17.0.0-alpha.2 || ^17.0.0
+ react: ^18 || ^19
+ react-dom: ^18 || ^19
+ languageName: unknown
+ linkType: soft
+
"@graphiql/plugin-code-exporter@npm:^5.1.2, @graphiql/plugin-code-exporter@workspace:packages/graphiql-plugin-code-exporter":
version: 0.0.0-use.local
resolution: "@graphiql/plugin-code-exporter@workspace:packages/graphiql-plugin-code-exporter"
@@ -3055,7 +3077,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@graphiql/plugin-explorer@npm:^5.1.2, @graphiql/plugin-explorer@workspace:packages/graphiql-plugin-explorer":
+"@graphiql/plugin-explorer@npm:^5.1.1, @graphiql/plugin-explorer@npm:^5.1.2, @graphiql/plugin-explorer@workspace:packages/graphiql-plugin-explorer":
version: 0.0.0-use.local
resolution: "@graphiql/plugin-explorer@workspace:packages/graphiql-plugin-explorer"
dependencies:
@@ -3099,7 +3121,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@graphiql/react@npm:^0.37.4, @graphiql/react@npm:^0.37.5, @graphiql/react@workspace:packages/graphiql-react":
+"@graphiql/react@npm:^0.37.0, @graphiql/react@npm:^0.37.4, @graphiql/react@npm:^0.37.5, @graphiql/react@workspace:packages/graphiql-react":
version: 0.0.0-use.local
resolution: "@graphiql/react@workspace:packages/graphiql-react"
dependencies:
@@ -12950,7 +12972,7 @@ __metadata:
languageName: unknown
linkType: soft
-"graphiql@npm:^5.2.3, graphiql@workspace:packages/graphiql":
+"graphiql@npm:^5.2.0, graphiql@npm:^5.2.3, graphiql@workspace:packages/graphiql":
version: 0.0.0-use.local
resolution: "graphiql@workspace:packages/graphiql"
dependencies:
@@ -13155,9 +13177,9 @@ __metadata:
linkType: hard
"graphql@npm:^16, graphql@npm:^16.11.0, graphql@npm:^16.13.2, graphql@npm:^16.9.0":
- version: 16.13.2
- resolution: "graphql@npm:16.13.2"
- checksum: 10c0/64e822a0a0e4398781e4bc9765b88d370c08261498b517add4b878038ef7be2005b6b394a79a5102b9379d57052f60bc7f23fec8f39808d101984a74772ebd9d
+ version: 16.14.0
+ resolution: "graphql@npm:16.14.0"
+ checksum: 10c0/baaa368fcfeb7bf2cdf94b9f31bf916e97eaa9e7e82148a7046f31cbd49b760b38190f22393b024cbdd9ca0f4f46287515de0136b6a0cc164074b36ad7b50618
languageName: node
linkType: hard
@@ -15009,92 +15031,102 @@ __metadata:
languageName: node
linkType: hard
-"lightningcss-darwin-arm64@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-darwin-arm64@npm:1.29.3"
+"lightningcss-android-arm64@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-android-arm64@npm:1.32.0"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"lightningcss-darwin-arm64@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-darwin-arm64@npm:1.32.0"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
-"lightningcss-darwin-x64@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-darwin-x64@npm:1.29.3"
+"lightningcss-darwin-x64@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-darwin-x64@npm:1.32.0"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
-"lightningcss-freebsd-x64@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-freebsd-x64@npm:1.29.3"
+"lightningcss-freebsd-x64@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-freebsd-x64@npm:1.32.0"
conditions: os=freebsd & cpu=x64
languageName: node
linkType: hard
-"lightningcss-linux-arm-gnueabihf@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-linux-arm-gnueabihf@npm:1.29.3"
+"lightningcss-linux-arm-gnueabihf@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-linux-arm-gnueabihf@npm:1.32.0"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
-"lightningcss-linux-arm64-gnu@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-linux-arm64-gnu@npm:1.29.3"
+"lightningcss-linux-arm64-gnu@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-linux-arm64-gnu@npm:1.32.0"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
-"lightningcss-linux-arm64-musl@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-linux-arm64-musl@npm:1.29.3"
+"lightningcss-linux-arm64-musl@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-linux-arm64-musl@npm:1.32.0"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
-"lightningcss-linux-x64-gnu@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-linux-x64-gnu@npm:1.29.3"
+"lightningcss-linux-x64-gnu@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-linux-x64-gnu@npm:1.32.0"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
-"lightningcss-linux-x64-musl@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-linux-x64-musl@npm:1.29.3"
+"lightningcss-linux-x64-musl@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-linux-x64-musl@npm:1.32.0"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
-"lightningcss-win32-arm64-msvc@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-win32-arm64-msvc@npm:1.29.3"
+"lightningcss-win32-arm64-msvc@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-win32-arm64-msvc@npm:1.32.0"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
-"lightningcss-win32-x64-msvc@npm:1.29.3":
- version: 1.29.3
- resolution: "lightningcss-win32-x64-msvc@npm:1.29.3"
+"lightningcss-win32-x64-msvc@npm:1.32.0":
+ version: 1.32.0
+ resolution: "lightningcss-win32-x64-msvc@npm:1.32.0"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
-"lightningcss@npm:^1.29.3":
- version: 1.29.3
- resolution: "lightningcss@npm:1.29.3"
+"lightningcss@npm:^1.29.3, lightningcss@npm:^1.30.1":
+ version: 1.32.0
+ resolution: "lightningcss@npm:1.32.0"
dependencies:
detect-libc: "npm:^2.0.3"
- lightningcss-darwin-arm64: "npm:1.29.3"
- lightningcss-darwin-x64: "npm:1.29.3"
- lightningcss-freebsd-x64: "npm:1.29.3"
- lightningcss-linux-arm-gnueabihf: "npm:1.29.3"
- lightningcss-linux-arm64-gnu: "npm:1.29.3"
- lightningcss-linux-arm64-musl: "npm:1.29.3"
- lightningcss-linux-x64-gnu: "npm:1.29.3"
- lightningcss-linux-x64-musl: "npm:1.29.3"
- lightningcss-win32-arm64-msvc: "npm:1.29.3"
- lightningcss-win32-x64-msvc: "npm:1.29.3"
+ lightningcss-android-arm64: "npm:1.32.0"
+ lightningcss-darwin-arm64: "npm:1.32.0"
+ lightningcss-darwin-x64: "npm:1.32.0"
+ lightningcss-freebsd-x64: "npm:1.32.0"
+ lightningcss-linux-arm-gnueabihf: "npm:1.32.0"
+ lightningcss-linux-arm64-gnu: "npm:1.32.0"
+ lightningcss-linux-arm64-musl: "npm:1.32.0"
+ lightningcss-linux-x64-gnu: "npm:1.32.0"
+ lightningcss-linux-x64-musl: "npm:1.32.0"
+ lightningcss-win32-arm64-msvc: "npm:1.32.0"
+ lightningcss-win32-x64-msvc: "npm:1.32.0"
dependenciesMeta:
+ lightningcss-android-arm64:
+ optional: true
lightningcss-darwin-arm64:
optional: true
lightningcss-darwin-x64:
@@ -15115,7 +15147,7 @@ __metadata:
optional: true
lightningcss-win32-x64-msvc:
optional: true
- checksum: 10c0/6817846ecc0767b31de7a22cfe977dfc679e7dd7be8b1f811364ce7c1f8db079d6d2161e9d5d4e6a7ecb166f920dfb20fe7f60fba328a1c60c3dc358ec3b45f2
+ checksum: 10c0/70945bd55097af46fc9fab7f5ed09cd5869d85940a2acab7ee06d0117004a1d68155708a2d462531cea2fc3c67aefc9333a7068c80b0b78dd404c16838809e03
languageName: node
linkType: hard
@@ -20380,9 +20412,9 @@ __metadata:
languageName: node
linkType: hard
-"terser@npm:^5.10.0, terser@npm:^5.17.4, terser@npm:^5.31.1":
- version: 5.46.2
- resolution: "terser@npm:5.46.2"
+"terser@npm:^5, terser@npm:^5.10.0, terser@npm:^5.17.4, terser@npm:^5.31.1":
+ version: 5.47.1
+ resolution: "terser@npm:5.47.1"
dependencies:
"@jridgewell/source-map": "npm:^0.3.3"
acorn: "npm:^8.15.0"
@@ -20390,7 +20422,7 @@ __metadata:
source-map-support: "npm:~0.5.20"
bin:
terser: bin/terser
- checksum: 10c0/476f1820160c42e6b2f611410115b00321c4666d421f12db87f13810f8789de45cb254e3ad5178650696d0ba6b706f5a0a239272255d6d1be95816c660f8cbbb
+ checksum: 10c0/e7017001aff657b8eb444edb4c4ad2425b90c141c5329f06b1939161f38884622972ec7b12d197207229c8079d24d20bf44be93852f735fe3bb4b32d80775775
languageName: node
linkType: hard
@@ -21450,9 +21482,9 @@ __metadata:
languageName: node
linkType: hard
-"vite-plugin-dts@npm:^4.0.1, vite-plugin-dts@npm:^4.5.3":
- version: 4.5.3
- resolution: "vite-plugin-dts@npm:4.5.3"
+"vite-plugin-dts@npm:^4.0.1, vite-plugin-dts@npm:^4.5.3, vite-plugin-dts@npm:^4.5.4":
+ version: 4.5.4
+ resolution: "vite-plugin-dts@npm:4.5.4"
dependencies:
"@microsoft/api-extractor": "npm:^7.50.1"
"@rollup/pluginutils": "npm:^5.1.4"
@@ -21469,7 +21501,7 @@ __metadata:
peerDependenciesMeta:
vite:
optional: true
- checksum: 10c0/e86ff3a92bda138b5d69696297f520e796282d65af8f459c2ed7870e79fc67b3ea74afabe79678c2141e1ab651ec73c3928d8ae255ff08ff0c9e08477f8b1bcf
+ checksum: 10c0/5fcb7f3739d115f36195a692c0e9f9fca4e504bbbbabe29e71ee06630dd05ea2920169371e80e548eb4779d2eca14107277497838d7df588d53e1fadf84be861
languageName: node
linkType: hard