Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ export default antfu({
'plans',
'e2e/fixtures/**/dist',
'e2e/fixtures/**/.vite-devtools',
// The production playground is a standalone workspace (its own
// `pnpm-workspace.yaml`) that mirrors a real user install, so it uses plain
// dependency specifiers rather than the repo catalog and stays out of the
// repo-wide ESLint run.
// The production playgrounds are standalone workspaces (their own
// `pnpm-workspace.yaml`) that mirror a real user install, so they use
// plain dependency specifiers rather than the repo catalog and stay out
// of the repo-wide ESLint run.
'playgrounds/production',
'playgrounds/production-nuxt',
// `packages/oxc` is DevTools for the Oxc toolchain and dogfoods its own
// oxlint/oxfmt on itself, whose formatting (e.g. `arrowParens: "avoid"`)
// conflicts with this shared antfu config, so it is linted by its own
Expand Down
7 changes: 7 additions & 0 deletions playgrounds/production-nuxt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
dist
.output
.nuxt
.tarballs
pnpm-lock.yaml
*.local
71 changes: 71 additions & 0 deletions playgrounds/production-nuxt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Production Nuxt Playground

A **standalone pnpm workspace** running a **Nuxt 5** app with **Nuxt DevTools
4**, whose internal Vite DevTools dependency is overridden to the **local
built dist** — so you can test how Vite DevTools behaves when it's running as
Nuxt DevTools' own engine, rather than mounted directly as a Vite plugin.

The playground at `playgrounds/production` installs `@vitejs/devtools`
straight into a plain Vite app. This one exercises the other real-world
integration path: Nuxt DevTools v4 (`@nuxt/devtools@^4.0.0-alpha.9`) depends
directly on `@vitejs/devtools` and `@vitejs/devtools-kit`, so a Nuxt app with
`devtools: { enabled: true }` gets Vite DevTools for free, through Nuxt
DevTools.

Nuxt 5 isn't published to the `nuxt` package's stable dist-tags yet, so
`package.json` pulls it from Nuxt's [nightly release
channel](https://nuxt.com/docs/guide/going-further/nightly-release-channel)
via the `npm:nuxt-nightly@5x` alias — the same channel Nuxt itself documents
for trying the next major early. Nuxt DevTools 4 (`@nuxt/devtools@^4.0.0-alpha.9`)
is already on its regular dist-tags as a pre-release, so it's installed
directly with no alias needed.

## How it works

`scripts/pack-local.mjs` builds the monorepo and packs the six published
Vite DevTools packages into `.tarballs/`, exactly like `playgrounds/production`
(it shares the same `scripts/pack-devtools-tarballs.mjs` implementation).
Every run wipes and repacks under stable, version-agnostic names, then
installs with `--force`, so the install always reflects the tarballs that
were just packed, never a stale previous build.

`pnpm-workspace.yaml` overrides `@vitejs/devtools`, `@vitejs/devtools-kit`,
and every sibling package to those tarballs. Because `@nuxt/devtools` pulls
those same two packages in as regular (non-`workspace:`) npm dependencies,
the override reaches into Nuxt DevTools' own dependency tree and forces it to
run on the exact Vite DevTools build under test here — not whatever version
`@nuxt/devtools` has pinned on npm. Everything else (`nuxt`, `vue`,
`@nuxt/devtools` itself, ...) resolves from the public registry, just like a
real install.

Its own `pnpm-workspace.yaml` keeps it isolated from the monorepo above, so a
`pnpm install` here builds an independent dependency tree with its own lockfile.

## Usage

From this directory:

```sh
# Build the monorepo, pack the packages, and install them
pnpm run setup

# Start the Nuxt dev server (Nuxt DevTools panel)
pnpm dev

# Or produce a production build
pnpm build
```

To re-pack after changing package source without rebuilding untouched packages,
`pnpm run setup` re-runs the turbo build (cached), repacks, and reinstalls. If
you already have fresh `dist` output and only want to re-pack + reinstall:

```sh
pnpm run setup:no-build
```

## Layout

- `scripts/pack-local.mjs` — build + pack the published packages into `.tarballs/`, then install
- `nuxt.config.ts` — a plain user config with `devtools: { enabled: true }`
- `app/app.vue` — a minimal Nuxt app so the panels have real build/module data
37 changes: 37 additions & 0 deletions playgrounds/production-nuxt/app/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup lang="ts">
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
<main>
<h1>Vite DevTools — Production Nuxt Playground</h1>
<p>
This app installs Nuxt with Nuxt DevTools from npm, inside a standalone
pnpm workspace, with Nuxt DevTools' internal <code>@vitejs/devtools</code>
and <code>@vitejs/devtools-kit</code> dependencies overridden to the
local built dist — testing Vite DevTools the way it actually ships,
running as Nuxt DevTools' own engine.
</p>
<button type="button" @click="count++">
count is {{ count }}
</button>
</main>
</template>

<style scoped>
main {
max-width: 42rem;
margin: 4rem auto;
padding: 0 1rem;
font-family: system-ui, sans-serif;
line-height: 1.6;
}
button {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
border: 1px solid currentColor;
cursor: pointer;
}
</style>
12 changes: 12 additions & 0 deletions playgrounds/production-nuxt/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineNuxtConfig } from 'nuxt/config'

// This config is intentionally written the way a real user would write it:
// enabling Nuxt DevTools is the only integration point needed. Nuxt DevTools
// v4 (`@nuxt/devtools`, overridden here to resolve its internal Vite DevTools
// dependency from the local built dist — see `pnpm-workspace.yaml`) embeds
// Vite DevTools as its own engine, so there's no separate `@vitejs/devtools`
// Vite plugin to add by hand.
export default defineNuxtConfig({
compatibilityDate: '2024-11-01',
devtools: { enabled: true },
})
21 changes: 21 additions & 0 deletions playgrounds/production-nuxt/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "playground-production-nuxt",
"type": "module",
"version": "0.4.11",
"private": true,
"description": "Standalone workspace that installs a Nuxt 5 app with Nuxt DevTools 4 from npm, overriding its internal Vite DevTools dependency to the local built dist, to test the real Nuxt-DevTools-embeds-Vite-DevTools install path.",
"scripts": {
"setup": "node scripts/pack-local.mjs",
"setup:no-build": "node scripts/pack-local.mjs --no-build",
"dev": "nuxt dev --host 0.0.0.0",
"build": "nuxt build",
"preview": "nuxt preview"
},
"dependencies": {
"nuxt": "npm:nuxt-nightly@5x",
"vue": "^3.5.39"
},
"devDependencies": {
"@nuxt/devtools": "^4.0.0-alpha.9"
}
}
29 changes: 29 additions & 0 deletions playgrounds/production-nuxt/pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Standalone workspace root.
#
# This file exists so pnpm treats `playgrounds/production-nuxt` as its own,
# self-contained project instead of a member of the monorepo above it.
#
# Nuxt DevTools v4 (`@nuxt/devtools@^4.0.0-alpha.9`) embeds Vite DevTools: it
# depends directly on `@vitejs/devtools` and `@vitejs/devtools-kit` as its own
# engine. These overrides redirect that internal dependency — and every other
# Vite DevTools package — to the local built dist tarballs produced by
# `scripts/pack-local.mjs`, so Nuxt DevTools always runs on the exact Vite
# DevTools build under test here rather than whatever version `@nuxt/devtools`
# has pinned on npm. Everything else (nuxt, vue, ...) resolves from the public
# registry — exactly what a real user gets.
packages: []

overrides:
'@vitejs/devtools': 'file:.tarballs/vitejs-devtools.tgz'
'@vitejs/devtools-kit': 'file:.tarballs/vitejs-devtools-kit.tgz'
'@vitejs/devtools-rolldown': 'file:.tarballs/vitejs-devtools-rolldown.tgz'
'@vitejs/devtools-vite': 'file:.tarballs/vitejs-devtools-vite.tgz'
'@vitejs/devtools-vitest': 'file:.tarballs/vitejs-devtools-vitest.tgz'
'@vitejs/devtools-oxc': 'file:.tarballs/vitejs-devtools-oxc.tgz'

verifyDepsBeforeRun: false
allowBuilds:
esbuild: true
rolldown: true
unrs-resolver: true
minimumReleaseAge: 0
36 changes: 36 additions & 0 deletions playgrounds/production-nuxt/scripts/pack-local.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// @ts-check
/**
* Build the Vite DevTools packages, pack them into local tarballs, and
* install this playground from them — the same artifacts that would be
* published to npm. Nuxt DevTools v4 (`@nuxt/devtools`) depends directly on
* `@vitejs/devtools` and `@vitejs/devtools-kit`; `pnpm-workspace.yaml`
* overrides those (and every other Vite DevTools package) to these tarballs,
* so Nuxt DevTools runs on the build under test here.
*
* Every run wipes `.tarballs/` and repacks from scratch, then reinstalls with
* `--force` so pnpm never mistakes a freshly rebuilt tarball (same stable
* filename, new content) for the previous stale install.
*
* Usage:
* node scripts/pack-local.mjs # build the monorepo, pack, install
* node scripts/pack-local.mjs --no-build # skip the build, just (re)pack + install
*/
import { dirname, join, resolve } from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { packDevToolsTarballs, run } from '../../../scripts/pack-devtools-tarballs.mjs'

const scriptDir = dirname(fileURLToPath(import.meta.url))
const playgroundDir = resolve(scriptDir, '..')
const repoRoot = resolve(playgroundDir, '../..')
const tarballDir = join(playgroundDir, '.tarballs')

const skipBuild = process.argv.includes('--no-build')

packDevToolsTarballs({ repoRoot, tarballDir, skipBuild })

// `--force` bypasses pnpm's content-addressable store cache, guaranteeing the
// install always reflects the tarballs that were just packed above.
run('pnpm install --no-frozen-lockfile --force', playgroundDir)

console.log('\nDone. Run `pnpm dev` to start the playground.')
3 changes: 3 additions & 0 deletions playgrounds/production-nuxt/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "./.nuxt/tsconfig.json"
}
29 changes: 13 additions & 16 deletions playgrounds/production/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ and the `dist` output.

## How it works

`scripts/pack-local.mjs` builds the monorepo and runs `pnpm pack` on the five
`scripts/pack-local.mjs` builds the monorepo and runs `pnpm pack` on the six
published packages (`@vitejs/devtools`, `-kit`, `-rolldown`, `-vite`,
`-vitest`). `pnpm pack` rewrites each package's `workspace:*` and `catalog:*`
protocols into concrete versions, producing the exact tarballs npm would serve.
The tarballs land in `.tarballs/` under stable names; `pnpm-workspace.yaml`
points `@vitejs/devtools` and every inter-package dependency at them through
`overrides`. Everything else (devframe, `@devframes/*`, vite, vue) resolves
from the public registry — just like a real install.
`-vitest`, `-oxc`). `pnpm pack` rewrites each package's `workspace:*` and
`catalog:*` protocols into concrete versions, producing the exact tarballs npm
would serve. Every run wipes `.tarballs/` and repacks from scratch under
stable, version-agnostic names, then installs the playground with `--force` —
so the install always reflects the tarballs that were just packed, never a
stale previous build. `pnpm-workspace.yaml` points `@vitejs/devtools` and
every inter-package dependency at those tarballs through `overrides`.
Everything else (devframe, `@devframes/*`, vite, vue) resolves from the public
registry — just like a real install.

Its own `pnpm-workspace.yaml` keeps it isolated from the monorepo above, so a
`pnpm install` here builds an independent dependency tree with its own lockfile.
Expand All @@ -40,21 +43,15 @@ pnpm build
```

To re-pack after changing package source without rebuilding untouched packages,
`pnpm run setup` re-runs the turbo build (cached) and re-packs. If you already
have fresh `dist` output and only want to re-pack + reinstall:
`pnpm run setup` re-runs the turbo build (cached), repacks, and reinstalls. If
you already have fresh `dist` output and only want to re-pack + reinstall:

```sh
pnpm run setup:no-build
```

If pnpm doesn't pick up freshly re-packed tarballs, force it:

```sh
pnpm install --no-frozen-lockfile --force
```

## Layout

- `scripts/pack-local.mjs` — build + pack the published packages into `.tarballs/`
- `scripts/pack-local.mjs` — build + pack the published packages into `.tarballs/`, then install
- `vite.config.ts` — a plain user config importing `DevTools` from `@vitejs/devtools`
- `src/` — a minimal Vue app so the panels have real build/module data
5 changes: 2 additions & 3 deletions playgrounds/production/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
"private": true,
"description": "Standalone workspace that installs Vite DevTools from the local built dist, to test the real user install experience.",
"scripts": {
"setup": "node scripts/pack-local.mjs && pnpm install --no-frozen-lockfile",
"setup:no-build": "node scripts/pack-local.mjs --no-build && pnpm install --no-frozen-lockfile",
"pack:local": "node scripts/pack-local.mjs",
"setup": "node scripts/pack-local.mjs",
"setup:no-build": "node scripts/pack-local.mjs --no-build",
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview --host"
Expand Down
76 changes: 17 additions & 59 deletions playgrounds/production/scripts/pack-local.mjs
Original file line number Diff line number Diff line change
@@ -1,78 +1,36 @@
// @ts-check
/**
* Build the Vite DevTools packages and pack them into local tarballs that this
* standalone playground installs — the same artifacts that would be published
* to npm, so the playground exercises the real user install path.
* Build the Vite DevTools packages, pack them into local tarballs, and
* install this playground from them — the same artifacts that would be
* published to npm, so the playground exercises the real user install path.
*
* Every run wipes `.tarballs/` and repacks from scratch, then reinstalls with
* `--force` so pnpm never mistakes a freshly rebuilt tarball (same stable
* filename, new content) for the previous stale install.
*
* Usage:
* node scripts/pack-local.mjs # build the monorepo, then pack
* node scripts/pack-local.mjs --no-build # skip the build, just (re)pack dist
* node scripts/pack-local.mjs # build the monorepo, pack, install
* node scripts/pack-local.mjs --no-build # skip the build, just (re)pack + install
*
* `pnpm pack` resolves each package's `workspace:*` and `catalog:*` protocols
* into concrete versions, so the tarballs are exactly what end users receive.
* The playground's package.json then points `@vitejs/devtools` and every
* inter-package dependency at these tarballs via `pnpm.overrides`.
* The playground's package.json / pnpm-workspace.yaml point `@vitejs/devtools`
* and every inter-package dependency at these tarballs via `pnpm.overrides`.
*/
import { execSync } from 'node:child_process'
import { mkdirSync, readdirSync, renameSync, rmSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { packDevToolsTarballs, run } from '../../../scripts/pack-devtools-tarballs.mjs'

const scriptDir = dirname(fileURLToPath(import.meta.url))
const playgroundDir = resolve(scriptDir, '..')
const repoRoot = resolve(playgroundDir, '../..')
const tarballDir = join(playgroundDir, '.tarballs')

/**
* The set of packages published to npm as part of Vite DevTools.
* `@vitejs/devtools-ui` is private (bundled into the others at build time) and
* `@vitejs/devtools-oxc` is a separate opt-in package, so neither is packed.
*
* @type {Array<{ name: string, dir: string, out: string }>}
*/
const PACKAGES = [
{ name: '@vitejs/devtools', dir: 'packages/core', out: 'vitejs-devtools.tgz' },
{ name: '@vitejs/devtools-kit', dir: 'packages/kit', out: 'vitejs-devtools-kit.tgz' },
{ name: '@vitejs/devtools-rolldown', dir: 'packages/rolldown', out: 'vitejs-devtools-rolldown.tgz' },
{ name: '@vitejs/devtools-vite', dir: 'packages/vite', out: 'vitejs-devtools-vite.tgz' },
{ name: '@vitejs/devtools-vitest', dir: 'packages/vitest', out: 'vitejs-devtools-vitest.tgz' },
{ name: '@vitejs/devtools-oxc', dir: 'packages/oxc', out: 'vitejs-devtools-oxc.tgz' },
]

const skipBuild = process.argv.includes('--no-build')

/** @param {string} cmd @param {string} cwd */
function run(cmd, cwd) {
console.log(`\n$ ${cmd}\n (cwd: ${cwd})`)
execSync(cmd, { cwd, stdio: 'inherit' })
}

if (!skipBuild) {
run('pnpm build', repoRoot)
}

rmSync(tarballDir, { recursive: true, force: true })
mkdirSync(tarballDir, { recursive: true })

// Pack each package. `--ignore-scripts` skips the `prepack` rebuild since the
// monorepo build above already produced fresh dist output.
for (const { name, dir } of PACKAGES) {
console.log(`\nPacking ${name}...`)
run(`pnpm pack --config.ignore-scripts=true --pack-destination "${tarballDir}"`, join(repoRoot, dir))
}
packDevToolsTarballs({ repoRoot, tarballDir, skipBuild })

// pnpm writes `<name>-<version>.tgz`; rename to the stable, version-agnostic
// names the playground's package.json / overrides reference.
const produced = readdirSync(tarballDir)
for (const { name, out } of PACKAGES) {
const base = name.replace('@', '').replace('/', '-')
const pattern = new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}-\\d[^/]*\\.tgz$`)
const match = produced.find(f => pattern.test(f))
if (!match)
throw new Error(`Could not find packed tarball for ${name} (expected ${base}-<version>.tgz)`)
renameSync(join(tarballDir, match), join(tarballDir, out))
console.log(`✓ ${name} -> .tarballs/${out}`)
}
// `--force` bypasses pnpm's content-addressable store cache, guaranteeing the
// install always reflects the tarballs that were just packed above.
run('pnpm install --no-frozen-lockfile --force', playgroundDir)

console.log('\nDone. Now run: pnpm install --no-frozen-lockfile')
console.log('\nDone. Run `pnpm dev` to start the playground.')
Loading
Loading