From 6b61f11b0a6904f1e694ad32dd3fca9d69da01c8 Mon Sep 17 00:00:00 2001 From: Edgy Date: Sat, 7 Feb 2026 01:52:42 +0800 Subject: [PATCH 1/4] fix: use stable bundle name in dev mode to avoid CDN mismatch Problem: When bumping package.json version, the homepage would try to load plugin-{new-version}-app.js from CDN, but it doesn't exist yet. This broke local development when making version changes. Solution: When NEXT_PUBLIC_IS_PLUGIN_DEV=true: - Webpack outputs to plugin-dev.js (stable name) - library.tsx loads plugin-dev.js instead of versioned file - Local builds work regardless of package.json version Changes: - webpack.config.js: Use 'plugin-dev' bundle name in dev mode - library.tsx: Same logic for runtime bundle loading - .env: Enable dev mode by default for local development - DEVELOPER_NOTES.md: Document the dev build workflow --- .env | 6 +++++- DEVELOPER_NOTES.md | 28 ++++++++++++++++++++++++++-- src/library.tsx | 6 +++++- webpack.config.js | 5 ++++- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/.env b/.env index 39e98cd..9872582 100644 --- a/.env +++ b/.env @@ -1,4 +1,8 @@ NEXT_PUBLIC_CLUSTER=mainnet-beta # Local development is similar as next public preview -NEXT_PUBLIC_IS_NEXT_PREVIEW=true \ No newline at end of file +NEXT_PUBLIC_IS_NEXT_PREVIEW=true + +# Enable plugin dev mode - uses local builds instead of CDN +# This allows version bumps without waiting for CDN upload +NEXT_PUBLIC_IS_PLUGIN_DEV=true \ No newline at end of file diff --git a/DEVELOPER_NOTES.md b/DEVELOPER_NOTES.md index cc7997b..cadbb6f 100644 --- a/DEVELOPER_NOTES.md +++ b/DEVELOPER_NOTES.md @@ -1,7 +1,31 @@ # Developer Notes -To develop, `pnpm i && pnpm dev` -To build, `pnpm build-widget` +## Quick Start + +```bash +pnpm i +pnpm dev +``` + +## Building + +```bash +# Production build (versioned: plugin-1.0.x.js) +pnpm build-widget + +# Dev build (stable name: plugin-dev.js) - for local testing +NEXT_PUBLIC_IS_PLUGIN_DEV=true pnpm build-widget +``` + +## Dev Mode Bundle Loading + +When `NEXT_PUBLIC_IS_PLUGIN_DEV=true` is set (in `.env` or environment): +- Webpack outputs to `plugin-dev.js` instead of `plugin-{version}.js` +- The loader uses the local build instead of fetching from CDN +- You can bump versions freely without breaking the homepage + +This solves the "version mismatch" issue where bumping package.json version +would cause the homepage to try loading files that don't exist on CDN yet. There's a few point of entry for Plugin, and each has specific reasons: diff --git a/src/library.tsx b/src/library.tsx index cce65ef..da368d6 100644 --- a/src/library.tsx +++ b/src/library.tsx @@ -14,7 +14,11 @@ import { ShadowDomContainer } from './components/ShadowDomContainer'; const containerId = 'jupiter-plugin-instance'; const packageJson = require('../package.json'); -const bundleName = `plugin-${packageJson.version}`; + +// Use stable name in dev mode to avoid CDN version mismatch +const bundleName = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV + ? 'plugin-dev' + : `plugin-${packageJson.version}`; const scriptDomain = (() => { diff --git a/webpack.config.js b/webpack.config.js index 4409246..83222f2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,7 +8,10 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl const packageJson = require("./package.json"); const analyseBundle = process.env.ANALYSE === 'true'; -const bundleName = `plugin-${packageJson.version}`; +const isPluginDev = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV === 'true'; + +// Use stable name in dev mode to avoid CDN version mismatch +const bundleName = isPluginDev ? 'plugin-dev' : `plugin-${packageJson.version}`; if (!bundleName) { throw new Error('Bundle name/version is not set'); From d95412030b3499b3e4e28a32af163b9a20b12419 Mon Sep 17 00:00:00 2001 From: Edgy Date: Sat, 7 Feb 2026 02:00:48 +0800 Subject: [PATCH 2/4] add build-widget:dev script for convenience --- DEVELOPER_NOTES.md | 19 +++++++++++++------ package.json | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/DEVELOPER_NOTES.md b/DEVELOPER_NOTES.md index cadbb6f..28a1a40 100644 --- a/DEVELOPER_NOTES.md +++ b/DEVELOPER_NOTES.md @@ -10,20 +10,27 @@ pnpm dev ## Building ```bash -# Production build (versioned: plugin-1.0.x.js) -pnpm build-widget - # Dev build (stable name: plugin-dev.js) - for local testing -NEXT_PUBLIC_IS_PLUGIN_DEV=true pnpm build-widget +pnpm build-widget:dev + +# Production build (versioned: plugin-1.0.x.js) - for publishing +pnpm build-widget ``` ## Dev Mode Bundle Loading -When `NEXT_PUBLIC_IS_PLUGIN_DEV=true` is set (in `.env` or environment): +When using `pnpm build-widget:dev`: - Webpack outputs to `plugin-dev.js` instead of `plugin-{version}.js` -- The loader uses the local build instead of fetching from CDN +- The homepage loads the local build instead of fetching from CDN - You can bump versions freely without breaking the homepage +**Typical dev workflow:** +```bash +pnpm build-widget:dev # Build once with stable name +pnpm dev # Start dev server - homepage works! +# Make changes, bump version, rebuild - still works +``` + This solves the "version mismatch" issue where bumping package.json version would cause the homepage to try loading files that don't exist on CDN yet. diff --git a/package.json b/package.json index 19597ad..064ad20 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "lint": "next lint", "format:fix": "prettier --write src", "build-widget": "NODE_ENV=production MODE=widget webpack", + "build-widget:dev": "NODE_ENV=production MODE=widget NEXT_PUBLIC_IS_PLUGIN_DEV=true webpack", "analyse": "NODE_ENV=production MODE=widget ANALYSE=true webpack" }, "files": [ From 1b1646c613a6e62185d9d7b02e93f5cbf5bb7702 Mon Sep 17 00:00:00 2001 From: Edgy Date: Sat, 7 Feb 2026 02:05:55 +0800 Subject: [PATCH 3/4] auto-detect Vercel preview and build widget for previews - Check VERCEL_ENV=preview in webpack and NEXT_PUBLIC_VERCEL_ENV in library.tsx - Add vercel.json to run build-widget:dev before Next.js build - Vercel previews now automatically load new code without manual env var setup --- DEVELOPER_NOTES.md | 4 ++++ src/library.tsx | 10 ++++++---- vercel.json | 5 +++++ webpack.config.js | 7 +++++-- 4 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 vercel.json diff --git a/DEVELOPER_NOTES.md b/DEVELOPER_NOTES.md index 28a1a40..f1175ad 100644 --- a/DEVELOPER_NOTES.md +++ b/DEVELOPER_NOTES.md @@ -34,6 +34,10 @@ pnpm dev # Start dev server - homepage works! This solves the "version mismatch" issue where bumping package.json version would cause the homepage to try loading files that don't exist on CDN yet. +**Vercel previews:** Automatically detected via `VERCEL_ENV=preview`. +The `vercel.json` runs `build-widget:dev` before Next.js build, so PR previews +load the new code from the preview URL instead of CDN. + There's a few point of entry for Plugin, and each has specific reasons: - https://github.com/jup-ag/plugin/blob/main/src/index.tsx (RenderJupiter) diff --git a/src/library.tsx b/src/library.tsx index da368d6..a9061a6 100644 --- a/src/library.tsx +++ b/src/library.tsx @@ -15,10 +15,12 @@ import { ShadowDomContainer } from './components/ShadowDomContainer'; const containerId = 'jupiter-plugin-instance'; const packageJson = require('../package.json'); -// Use stable name in dev mode to avoid CDN version mismatch -const bundleName = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV - ? 'plugin-dev' - : `plugin-${packageJson.version}`; +// Use stable bundle name in dev mode OR Vercel preview to avoid CDN version mismatch +const isPluginDev = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV === 'true'; +const isVercelPreview = process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview'; +const useDevBundle = isPluginDev || isVercelPreview; + +const bundleName = useDevBundle ? 'plugin-dev' : `plugin-${packageJson.version}`; const scriptDomain = (() => { diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..cee9edc --- /dev/null +++ b/vercel.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "buildCommand": "pnpm build-widget:dev && pnpm build", + "framework": "nextjs" +} diff --git a/webpack.config.js b/webpack.config.js index 83222f2..b9aec0b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,10 +8,13 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl const packageJson = require("./package.json"); const analyseBundle = process.env.ANALYSE === 'true'; + +// Use stable bundle name in dev mode OR Vercel preview to avoid CDN version mismatch const isPluginDev = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV === 'true'; +const isVercelPreview = process.env.VERCEL_ENV === 'preview'; +const useDevBundle = isPluginDev || isVercelPreview; -// Use stable name in dev mode to avoid CDN version mismatch -const bundleName = isPluginDev ? 'plugin-dev' : `plugin-${packageJson.version}`; +const bundleName = useDevBundle ? 'plugin-dev' : `plugin-${packageJson.version}`; if (!bundleName) { throw new Error('Bundle name/version is not set'); From d9fe2a287d27a5dcff19051c5e3d83948b277ff4 Mon Sep 17 00:00:00 2001 From: Edgy Date: Sat, 7 Feb 2026 02:10:07 +0800 Subject: [PATCH 4/4] simplify: keep versioned bundles, switch domain instead Instead of changing bundle names, we switch where we load from: - Dev/Preview: load from local /public (relative path) - Production: load from CDN This way: - Bundles are always versioned (plugin-1.0.14.js) - Local dev loads /public/plugin-1.0.14.js - Vercel preview loads /public/plugin-1.0.14.js - Production loads https://plugin.jup.ag/plugin-1.0.14.js --- DEVELOPER_NOTES.md | 34 +++++++++++++++------------------- package.json | 1 - src/library.tsx | 24 ++++++------------------ vercel.json | 2 +- webpack.config.js | 8 ++------ 5 files changed, 24 insertions(+), 45 deletions(-) diff --git a/DEVELOPER_NOTES.md b/DEVELOPER_NOTES.md index f1175ad..a94ae00 100644 --- a/DEVELOPER_NOTES.md +++ b/DEVELOPER_NOTES.md @@ -10,33 +10,29 @@ pnpm dev ## Building ```bash -# Dev build (stable name: plugin-dev.js) - for local testing -pnpm build-widget:dev - -# Production build (versioned: plugin-1.0.x.js) - for publishing -pnpm build-widget +pnpm build-widget # Build versioned bundle (plugin-1.0.x.js) to /public/ ``` -## Dev Mode Bundle Loading +## Local Development -When using `pnpm build-widget:dev`: -- Webpack outputs to `plugin-dev.js` instead of `plugin-{version}.js` -- The homepage loads the local build instead of fetching from CDN -- You can bump versions freely without breaking the homepage +The `.env` file has `NEXT_PUBLIC_IS_PLUGIN_DEV=true` which tells the app to +load bundles from local `/public/` instead of CDN. -**Typical dev workflow:** +**Workflow:** ```bash -pnpm build-widget:dev # Build once with stable name -pnpm dev # Start dev server - homepage works! -# Make changes, bump version, rebuild - still works +pnpm build-widget # Build once (creates /public/plugin-1.0.x.js) +pnpm dev # Homepage loads from localhost, not CDN +# Bump version, rebuild, still works - loads new version from /public/ ``` -This solves the "version mismatch" issue where bumping package.json version -would cause the homepage to try loading files that don't exist on CDN yet. +## Vercel Previews + +Automatically handled: +- `vercel.json` runs `build-widget` before Next.js build +- `NEXT_PUBLIC_VERCEL_ENV=preview` is set automatically by Vercel +- App detects preview mode and loads from preview URL instead of CDN -**Vercel previews:** Automatically detected via `VERCEL_ENV=preview`. -The `vercel.json` runs `build-widget:dev` before Next.js build, so PR previews -load the new code from the preview URL instead of CDN. +**Result:** PR previews always test the new code, no CDN needed. There's a few point of entry for Plugin, and each has specific reasons: diff --git a/package.json b/package.json index 064ad20..19597ad 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "lint": "next lint", "format:fix": "prettier --write src", "build-widget": "NODE_ENV=production MODE=widget webpack", - "build-widget:dev": "NODE_ENV=production MODE=widget NEXT_PUBLIC_IS_PLUGIN_DEV=true webpack", "analyse": "NODE_ENV=production MODE=widget ANALYSE=true webpack" }, "files": [ diff --git a/src/library.tsx b/src/library.tsx index a9061a6..413df18 100644 --- a/src/library.tsx +++ b/src/library.tsx @@ -14,27 +14,15 @@ import { ShadowDomContainer } from './components/ShadowDomContainer'; const containerId = 'jupiter-plugin-instance'; const packageJson = require('../package.json'); +const bundleName = `plugin-${packageJson.version}`; -// Use stable bundle name in dev mode OR Vercel preview to avoid CDN version mismatch -const isPluginDev = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV === 'true'; +// In dev/preview: load from local /public (empty string = relative path) +// In production: load from CDN +const isLocalDev = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV === 'true'; const isVercelPreview = process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview'; -const useDevBundle = isPluginDev || isVercelPreview; +const useLocalBundle = isLocalDev || isVercelPreview; -const bundleName = useDevBundle ? 'plugin-dev' : `plugin-${packageJson.version}`; - -const scriptDomain = - (() => { - if (!process.env.NEXT_PUBLIC_IS_PLUGIN_DEV) { - return null - } - if (typeof window === 'undefined' || typeof document === 'undefined') return ''; - - const url = (document.currentScript as HTMLScriptElement)?.src; - if (url) { - return new URL(url).origin; - } - return null; - })() || 'https://plugin.jup.ag'; +const scriptDomain = useLocalBundle ? '' : 'https://plugin.jup.ag'; async function loadRemote(id: string, href: string, type: 'text/javascript' | 'stylesheet') { return new Promise((res, rej) => { diff --git a/vercel.json b/vercel.json index cee9edc..eb6391a 100644 --- a/vercel.json +++ b/vercel.json @@ -1,5 +1,5 @@ { "$schema": "https://openapi.vercel.sh/vercel.json", - "buildCommand": "pnpm build-widget:dev && pnpm build", + "buildCommand": "pnpm build-widget && pnpm build", "framework": "nextjs" } diff --git a/webpack.config.js b/webpack.config.js index b9aec0b..e1af843 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -9,12 +9,8 @@ const packageJson = require("./package.json"); const analyseBundle = process.env.ANALYSE === 'true'; -// Use stable bundle name in dev mode OR Vercel preview to avoid CDN version mismatch -const isPluginDev = process.env.NEXT_PUBLIC_IS_PLUGIN_DEV === 'true'; -const isVercelPreview = process.env.VERCEL_ENV === 'preview'; -const useDevBundle = isPluginDev || isVercelPreview; - -const bundleName = useDevBundle ? 'plugin-dev' : `plugin-${packageJson.version}`; +// Always use versioned bundle name +const bundleName = `plugin-${packageJson.version}`; if (!bundleName) { throw new Error('Bundle name/version is not set');