Skip to content

Commit 25973fd

Browse files
antfubotantfu
andauthored
feat(inspector): rebuild on devframe (#5276)
Co-authored-by: Anthony Fu <github@antfu.me>
1 parent 6cc1d75 commit 25973fd

66 files changed

Lines changed: 1979 additions & 364 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ export default defineConfig({
318318
light: 'vitesse-light',
319319
dark: 'vitesse-dark',
320320
},
321+
// Preload the grammars the twoslash transformers depend on, so a cold
322+
// build can't race on a lazily-loaded language ("Language `html` not
323+
// found") — otherwise intermittent in the Netlify deploy build.
324+
languages: ['vue', 'html'],
321325
codeTransformers: [
322326
transformerTwoslash({
323327
processHoverInfo: info => info.replace(/_unocss_core\./g, ''),

docs/tools/inspector.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,32 @@ description: The inspector UI for UnoCSS (@unocss/inspector).
88
The inspector UI for UnoCSS: `@unocss/inspector`.
99
Ships with `unocss` and `@unocss/vite`.
1010

11-
## Usage
11+
The inspector allows you to inspect the generated CSS rules and the applied classes for each file. It also provides a REPL to test your utilities based on your current configuration.
12+
13+
Built on top of [devframe](https://devfra.me/), the inspector can be hosted in several ways.
14+
15+
## Vite DevTools (recommended)
16+
17+
When [Vite DevTools](https://devtools.vite.dev/) (`@vitejs/devtools`) is installed, the inspector is mounted automatically as a **UnoCSS dock** inside it — no auth prompt, live updates included.
18+
19+
`vite build` with DevTools' static build also bakes a pre-computed snapshot of the inspector data into the export, so the analysis is viewable without a dev server.
20+
21+
## Standalone URL
1222

1323
Visit <a href="http://localhost:5173/__unocss" target="_blank" rel="noreferrer">localhost:5173/\_\_unocss</a> in your Vite dev server to see the inspector.
1424

15-
The inspector allows you to inspect the generated CSS rules and the applied classes for each file. It also provided a REPL to test your utilities based on your current configuration.
25+
On first use, enter the one-time 6-digit code printed in your dev server terminal to unlock it (the token is remembered per browser). When Vite DevTools is active, this URL redirects into the DevTools UI instead.
26+
27+
::: info
28+
The standalone URL is a deprecated surface — the Vite DevTools dock is the recommended way to use the inspector going forward.
29+
:::
30+
31+
## Other hosts
32+
33+
`@unocss/inspector/devframe` exports the inspector as a portable [devframe definition](https://devfra.me/), mountable by any devframe host:
34+
35+
- `createInspectorDevframe(ctx)` — bind the inspector to an existing UnoCSS plugin context.
36+
- `createStandaloneInspectorDevframe(options)` — build a standalone context by scanning project files, for hosts without a bundler-integrated UnoCSS context (e.g. a Next.js app using `@unocss/postcss` via [`@devframes/next`](https://devfra.me/frameworks/next)).
1637

1738
<img src="https://user-images.githubusercontent.com/11247099/140885990-1827f5ce-f12a-4ed4-9d63-e5145a65fb4a.png" loading="lazy" alt="UnoCSS Inspector" />
1839
<img src="https://user-images.githubusercontent.com/11247099/140886020-7014f412-f020-4aed-a169-d025cc1bbcd3.png" loading="lazy" alt="UnoCSS Inspector REPL" />

examples/inspector-next/.gitignore

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# env files (can opt-in for committing if needed)
34+
.env*
35+
36+
# vercel
37+
.vercel
38+
39+
# typescript
40+
*.tsbuildinfo
41+
next-env.d.ts
42+
pnpm-lock.yaml

examples/inspector-next/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# UnoCSS Inspector — Next.js
2+
3+
Next.js app using UnoCSS through `@unocss/postcss`, hosting the inspector
4+
with [`@devframes/next`](https://devfra.me/frameworks/next) — no Vite
5+
involved.
6+
7+
The catch-all route at `app/%5F_unocss/[[...path]]/route.ts` builds a
8+
standalone UnoCSS context (scanning `app/**` once at startup via
9+
`createStandaloneInspectorDevframe`) and serves the inspector SPA + RPC
10+
side-car through `createDevframeNextHandler`.
11+
12+
```sh
13+
pnpm install
14+
pnpm dev
15+
```
16+
17+
Open [http://localhost:3000/\_\_unocss/](http://localhost:3000/__unocss/) and
18+
enter the one-time code printed in the Next dev terminal to unlock the
19+
inspector.
20+
21+
Note: the standalone context scans the project once at startup — restart the
22+
dev server (or re-save the route file) to re-scan after adding new utilities.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import process from 'node:process'
2+
import { createDevframeNextHandler } from '@devframes/next/single'
3+
import { createStandaloneInspectorDevframe } from '@unocss/inspector/devframe'
4+
import config from '@/uno.config'
5+
6+
export const runtime = 'nodejs'
7+
export const dynamic = 'force-dynamic'
8+
9+
// Build a standalone UnoCSS context by scanning the project files once at
10+
// startup, then host the inspector devframe from this catch-all route.
11+
// The RPC WebSocket runs on a side-car port advertised through
12+
// `/__unocss/__connection.json`, gated by devframe's one-time-code auth
13+
// (the code is printed in the Next dev terminal).
14+
const handlerPromise = createStandaloneInspectorDevframe({
15+
root: process.cwd(),
16+
// Pass the config inline (`configFile: false` skips the file loader,
17+
// which doesn't play well with the Next bundler)
18+
config: { ...config, configFile: false },
19+
patterns: ['app/**/*.{ts,tsx,html}'],
20+
// (cast: pnpm may instantiate devframe twice across the linked monorepo)
21+
}).then(({ definition }) => createDevframeNextHandler(definition as any))
22+
23+
export async function GET(request: Request) {
24+
return (await handlerPromise).fetch(request)
25+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@unocss all;
2+
3+
body {
4+
font-family: Arial, Helvetica, sans-serif;
5+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { Metadata } from 'next'
2+
import './globals.css'
3+
4+
export const metadata: Metadata = {
5+
title: 'UnoCSS Inspector — Next.js',
6+
description: 'UnoCSS inspector hosted by a Next.js app through devframe',
7+
}
8+
9+
export default function RootLayout({
10+
children,
11+
}: Readonly<{
12+
children: React.ReactNode
13+
}>) {
14+
return (
15+
<html lang="en">
16+
<body>{children}</body>
17+
</html>
18+
)
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export default function Home() {
2+
return (
3+
<div className="h-screen flex flex-col items-center justify-center gap-4 bg-gray-100 dark:bg-gray-900">
4+
<h1 className="text-2xl font-bold text-sky-600">UnoCSS + Next.js</h1>
5+
<p className="op-60 max-w-100 text-center">
6+
UnoCSS runs through
7+
{' '}
8+
<code>@unocss/postcss</code>
9+
{' '}
10+
and the inspector is hosted by the Next app at
11+
{' '}
12+
<a className="text-sky-600 underline" href="/__unocss/">/__unocss/</a>
13+
. Enter the one-time code printed in the Next dev terminal to unlock it.
14+
</p>
15+
<button type="button" className="btn">A button</button>
16+
<div className="m-4 p-2 text-sm text-red-500 hover:op-50">Some utilities to inspect</div>
17+
</div>
18+
)
19+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { NextConfig } from 'next'
2+
import { withDevframe } from '@devframes/next/single'
3+
4+
const nextConfig: NextConfig = {
5+
// Keep the devframe host out of the bundle — its optional MCP adapter
6+
// imports peer packages that are lazily loaded at runtime only
7+
serverExternalPackages: ['devframe', '@devframes/next', '@unocss/inspector'],
8+
}
9+
10+
// Sets `skipTrailingSlashRedirect` so the inspector SPA's relative assets
11+
// resolve under /__unocss/
12+
export default withDevframe({ ...nextConfig })
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "inspector-next",
3+
"private": true,
4+
"scripts": {
5+
"dev": "next dev",
6+
"build": "next build",
7+
"start": "next start"
8+
},
9+
"dependencies": {
10+
"next": "16.1.2",
11+
"react": "19.2.3",
12+
"react-dom": "19.2.3"
13+
},
14+
"devDependencies": {
15+
"@devframes/next": "^0.9.11",
16+
"@types/node": "^25.9.5",
17+
"@types/react": "^19.2.18",
18+
"@types/react-dom": "^19.2.4",
19+
"@unocss/core": "link:../../packages-engine/core",
20+
"@unocss/inspector": "link:../../packages-integrations/inspector",
21+
"@unocss/postcss": "link:../../packages-integrations/postcss",
22+
"@unocss/preset-wind3": "link:../../packages-presets/preset-wind3",
23+
"typescript": "^6.0.3",
24+
"unocss": "link:../../packages-presets/unocss"
25+
}
26+
}

0 commit comments

Comments
 (0)
Sponsor
SponsoredKunjungi sekarang
Promo