diff --git a/AGENTS.md b/AGENTS.md index 64fe663..d050f4e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,7 @@ PLEASE STRICTLY FOLLOW THE BEST PRACTICES FOR SKILL: https://platform.claude.com - Focus on agents capabilities and practical usage patterns. - Ignore user-facing guides, introductions, get-started, install guides, etc. - Ignore content that LLM agents already confident about in their training data. +- Make the skill as concise as possible, avoid creating too many references. ## Skill Source Types diff --git a/skills/vite/GENERATION.md b/skills/vite/GENERATION.md index 8beb9f9..a4b1c4a 100644 --- a/skills/vite/GENERATION.md +++ b/skills/vite/GENERATION.md @@ -1,5 +1,5 @@ # Generation Info - **Source:** `sources/vite` -- **Git SHA:** `b40292ce6a7dbbbbac9c6dae5f126b7f44c3e1b7` -- **Generated:** 2026-01-28 +- **Git SHA:** `c47015eba4f0de255218c35769628d87152216ca` +- **Generated:** 2026-01-31 diff --git a/skills/vite/SKILL.md b/skills/vite/SKILL.md index c24cb05..0a00766 100644 --- a/skills/vite/SKILL.md +++ b/skills/vite/SKILL.md @@ -1,50 +1,72 @@ --- name: vite -description: Vite next-generation frontend build tool with fast HMR and optimized builds. Use when configuring Vite, adding plugins, working with dev server, or building for production. +description: Vite build tool configuration, plugin API, SSR, and Vite 8 Rolldown migration. Use when working with Vite projects, vite.config.ts, Vite plugins, or building libraries/SSR apps with Vite. metadata: author: Anthony Fu - version: "2026.1.28" - source: Generated from https://github.com/vitejs/vite, scripts located at https://github.com/antfu/skills + version: "2026.1.31" + source: Generated from https://github.com/vitejs/vite, scripts at https://github.com/antfu/skills --- -Vite is a modern build tool for frontend development featuring instant server start with native ES modules, lightning-fast HMR, and optimized production builds using Rolldown/Rollup. It supports TypeScript, JSX, CSS pre-processors out of the box and has a rich plugin ecosystem. +# Vite -> The skill is based on Vite 6.x, generated at 2026-01-28. +> Based on Vite 8 beta (Rolldown-powered). Vite 8 uses Rolldown bundler and Oxc transformer. + +Vite is a next-generation frontend build tool with fast dev server (native ESM + HMR) and optimized production builds. + +## Preferences + +- Use TypeScript: prefer `vite.config.ts` +- Always use ESM, avoid CommonJS ## Core | Topic | Description | Reference | |-------|-------------|-----------| -| Configuration | Config file setup, defineConfig, conditional and async configs | [core-config](references/core-config.md) | -| CLI Commands | Dev server, build, preview commands and options | [core-cli](references/core-cli.md) | -| Core Features | TypeScript, JSX, CSS, HTML processing, JSON handling | [core-features](references/core-features.md) | -| Using Plugins | Adding, configuring, and ordering plugins | [core-plugins](references/core-plugins.md) | +| Configuration | `vite.config.ts`, `defineConfig`, conditional configs, `loadEnv` | [core-config](references/core-config.md) | +| Features | `import.meta.glob`, asset queries (`?raw`, `?url`), `import.meta.env`, HMR API | [core-features](references/core-features.md) | +| Plugin API | Vite-specific hooks, virtual modules, plugin ordering | [core-plugin-api](references/core-plugin-api.md) | -## Features +## Build & SSR | Topic | Description | Reference | |-------|-------------|-----------| -| CSS Handling | CSS modules, pre-processors, PostCSS, Lightning CSS | [features-css](references/features-css.md) | -| Static Assets | Asset imports, public directory, URL handling | [features-assets](references/features-assets.md) | -| Glob Import | import.meta.glob, dynamic imports, batch loading | [features-glob-import](references/features-glob-import.md) | -| Environment Variables | .env files, modes, import.meta.env constants | [features-env](references/features-env.md) | -| HMR API | Hot Module Replacement client API | [features-hmr](references/features-hmr.md) | -| Web Workers | Worker imports and configuration | [features-workers](references/features-workers.md) | -| Dependency Pre-Bundling | optimizeDeps, caching, monorepo setup | [features-dep-bundling](references/features-dep-bundling.md) | - -## Build - -| Topic | Description | Reference | -|-------|-------------|-----------| -| Production Build | Build options, browser targets, multi-page apps | [build-production](references/build-production.md) | -| Library Mode | Building libraries with proper package exports | [build-library](references/build-library.md) | -| SSR | Server-side rendering setup and configuration | [build-ssr](references/build-ssr.md) | +| Build & SSR | Library mode, SSR middleware mode, `ssrLoadModule`, JavaScript API | [build-and-ssr](references/build-and-ssr.md) | ## Advanced | Topic | Description | Reference | |-------|-------------|-----------| -| JavaScript API | createServer, build, preview programmatic APIs | [advanced-api](references/advanced-api.md) | -| Plugin API | Creating Vite plugins, hooks, virtual modules | [advanced-plugin-api](references/advanced-plugin-api.md) | -| Performance | Optimization tips for dev server and builds | [advanced-performance](references/advanced-performance.md) | -| Backend Integration | Integrating Vite with traditional backends | [advanced-backend](references/advanced-backend.md) | +| Environment API | Vite 6+ multi-environment support, custom runtimes | [environment-api](references/environment-api.md) | +| Rolldown Migration | Vite 8 changes: Rolldown bundler, Oxc transformer, config migration | [rolldown-migration](references/rolldown-migration.md) | + +## Quick Reference + +### CLI Commands + +```bash +vite # Start dev server +vite build # Production build +vite preview # Preview production build +vite build --ssr # SSR build +``` + +### Common Config + +```ts +import { defineConfig } from 'vite' + +export default defineConfig({ + plugins: [], + resolve: { alias: { '@': '/src' } }, + server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, + build: { target: 'esnext', outDir: 'dist' }, +}) +``` + +### Official Plugins + +- `@vitejs/plugin-vue` - Vue 3 SFC support +- `@vitejs/plugin-vue-jsx` - Vue 3 JSX +- `@vitejs/plugin-react` - React with Oxc/Babel +- `@vitejs/plugin-react-swc` - React with SWC +- `@vitejs/plugin-legacy` - Legacy browser support diff --git a/skills/vite/references/advanced-api.md b/skills/vite/references/advanced-api.md deleted file mode 100644 index 5b2787b..0000000 --- a/skills/vite/references/advanced-api.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -name: advanced-api -description: Vite's JavaScript API for programmatic usage ---- - -# JavaScript API - -Vite's APIs are fully typed. Use TypeScript or enable JS type checking for intellisense. - -## `createServer` - -Create a development server programmatically: - -```ts -import { createServer } from 'vite' - -const server = await createServer({ - configFile: false, - root: __dirname, - server: { - port: 1337 - } -}) - -await server.listen() -server.printUrls() -server.bindCLIShortcuts({ print: true }) -``` - -### ViteDevServer Interface - -```ts -interface ViteDevServer { - config: ResolvedConfig - middlewares: Connect.Server // Connect app for custom middleware - httpServer: http.Server | null // Node HTTP server - watcher: FSWatcher // Chokidar watcher - ws: WebSocketServer // WebSocket for HMR - moduleGraph: ModuleGraph // Module import relationships - - // Transform without HTTP - transformRequest(url: string): Promise - - // Apply HTML transforms - transformIndexHtml(url: string, html: string): Promise - - // Load module for SSR - ssrLoadModule(url: string): Promise> - - // Fix SSR error stack traces - ssrFixStacktrace(e: Error): void - - // Control - listen(port?: number): Promise - restart(): Promise - close(): Promise -} -``` - -## `build` - -Build for production: - -```ts -import { build } from 'vite' - -await build({ - root: './project', - base: '/foo/', - build: { - rolldownOptions: { - // ... - } - } -}) -``` - -## `preview` - -Preview production build locally: - -```ts -import { preview } from 'vite' - -const previewServer = await preview({ - preview: { - port: 8080, - open: true - } -}) - -previewServer.printUrls() -``` - -## `resolveConfig` - -Resolve config without starting server: - -```ts -import { resolveConfig } from 'vite' - -const config = await resolveConfig( - { root: './project' }, - 'serve', // 'serve' | 'build' - 'development' // default mode -) -``` - -## `mergeConfig` - -Deep merge two configs: - -```ts -import { mergeConfig } from 'vite' - -const merged = mergeConfig(baseConfig, overrideConfig) -``` - -Merge callback config: - -```ts -import { defineConfig, mergeConfig } from 'vite' - -export default defineConfig((env) => - mergeConfig(configAsCallback(env), configAsObject) -) -``` - -## `loadEnv` - -Load .env files: - -```ts -import { loadEnv } from 'vite' - -// Load VITE_* vars -const env = loadEnv('development', process.cwd()) - -// Load all vars (empty prefix) -const allEnv = loadEnv('development', process.cwd(), '') -``` - -## `searchForWorkspaceRoot` - -Find monorepo workspace root: - -```ts -import { searchForWorkspaceRoot } from 'vite' - -const workspaceRoot = searchForWorkspaceRoot(process.cwd()) -``` - -## `normalizePath` - -Normalize paths for cross-platform: - -```ts -import { normalizePath } from 'vite' - -normalizePath('foo\\bar') // 'foo/bar' -``` - -## `transformWithOxc` - -Transform JS/TS with Oxc Transformer: - -```ts -import { transformWithOxc } from 'vite' - -const result = await transformWithOxc( - code, - 'file.ts', - { target: 'es2020' } -) -``` - -## `preprocessCSS` - -Pre-process CSS files: - -```ts -import { preprocessCSS, resolveConfig } from 'vite' - -const config = await resolveConfig({}, 'serve') -const result = await preprocessCSS(code, 'styles.scss', config) -// result.code - plain CSS -// result.modules - CSS modules mapping -``` - -## `loadConfigFromFile` - -Load config file manually: - -```ts -import { loadConfigFromFile } from 'vite' - -const result = await loadConfigFromFile( - { command: 'serve', mode: 'development' }, - 'vite.config.ts' -) -// result.config, result.path, result.dependencies -``` - -## InlineConfig - -Extends UserConfig with: - -```ts -interface InlineConfig extends UserConfig { - configFile?: string | false // Config file path or false to skip - mode?: string -} -``` - - diff --git a/skills/vite/references/advanced-backend.md b/skills/vite/references/advanced-backend.md deleted file mode 100644 index 1bca0f3..0000000 --- a/skills/vite/references/advanced-backend.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -name: advanced-backend -description: Integrating Vite with traditional backend frameworks ---- - -# Backend Integration - -Integrate Vite with traditional backends (Rails, Laravel, etc.) for asset serving. - -## Configuration - -```ts -// vite.config.ts -export default defineConfig({ - server: { - cors: { - origin: 'http://my-backend.example.com' - } - }, - build: { - manifest: true, // Generate .vite/manifest.json - rolldownOptions: { - input: '/path/to/main.js' // Override HTML entry - } - } -}) -``` - -Import polyfill in entry: - -```ts -// main.js -import 'vite/modulepreload-polyfill' -``` - -## Development - -Inject Vite client and entry in your backend template: - -```html - - - -``` - -### React Setup - -Add before other scripts: - -```html - -``` - -### Asset Proxying - -Either: -1. Proxy static asset requests to Vite -2. Set `server.origin`: - -```ts -export default defineConfig({ - server: { - origin: 'http://localhost:5173' - } -}) -``` - -## Production - -Build generates `.vite/manifest.json`: - -```json -{ - "views/foo.js": { - "file": "assets/foo-BRBmoGS9.js", - "src": "views/foo.js", - "isEntry": true, - "imports": ["_shared-B7PI925R.js"], - "css": ["assets/foo-5UjPuW-k.css"] - }, - "_shared-B7PI925R.js": { - "file": "assets/shared-B7PI925R.js", - "css": ["assets/shared-ChJ_j-JJ.css"] - } -} -``` - -## Rendering Tags - -For entry `views/foo.js`, render in this order: - -```html - - - - - - - - - - - -``` - -## Manifest Structure - -```ts -interface ManifestChunk { - src?: string // Input file name - file: string // Output file name - css?: string[] // CSS files (JS chunks only) - assets?: string[] // Non-CSS assets (JS chunks only) - isEntry?: boolean // Is entry point - isDynamicEntry?: boolean // Is dynamic import - imports?: string[] // Static imports (manifest keys) - dynamicImports?: string[] // Dynamic imports (manifest keys) -} -``` - -## Processing Imports - -Recursively collect all imported chunks: - -```ts -function getImportedChunks(manifest, name) { - const seen = new Set() - const chunks = [] - - function collect(chunk) { - for (const file of chunk.imports ?? []) { - if (seen.has(file)) continue - seen.add(file) - - const importee = manifest[file] - collect(importee) - chunks.push(importee) - } - } - - collect(manifest[name]) - return chunks -} -``` - -## Existing Integrations - -Check [Awesome Vite](https://github.com/vitejs/awesome-vite#integrations-with-backends) for: -- Laravel (laravel-vite) -- Rails -- Django -- Flask -- And more - - diff --git a/skills/vite/references/advanced-performance.md b/skills/vite/references/advanced-performance.md deleted file mode 100644 index 8dea328..0000000 --- a/skills/vite/references/advanced-performance.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -name: advanced-performance -description: Performance optimization tips for Vite dev server and builds ---- - -# Performance Optimization - -## Browser Setup - -- Use dev-only browser profile without extensions -- Disable "Disable Cache" in DevTools when using Vite -- Extensions can interfere with requests and slow startup - -## Audit Plugin Performance - -1. **Lazy load large dependencies** in plugins -2. **Avoid long operations** in `buildStart`, `config`, `configResolved` -3. **Optimize transform hooks** - check `id` extension before processing - -Debug transform times: - -```bash -vite --debug plugin-transform -``` - -Use [vite-plugin-inspect](https://github.com/antfu/vite-plugin-inspect) to inspect transforms. - -## Profiling - -```bash -vite --profile -# Visit site, press 'p + enter' to record .cpuprofile -# Open in https://www.speedscope.app -``` - -## Reduce Resolve Operations - -Be explicit with extensions to avoid filesystem checks: - -```ts -// Slow: checks .mjs, .js, .mts, .ts, .jsx, .tsx, .json -import Component from './Component' - -// Fast: direct hit -import Component from './Component.tsx' -``` - -Enable TypeScript path resolution for explicit imports: - -```json -{ - "compilerOptions": { - "moduleResolution": "bundler", - "allowImportingTsExtensions": true - } -} -``` - -## Avoid Barrel Files - -Barrel files (`index.js` re-exporting everything) cause all files to load: - -```ts -// Slow: loads all utils -import { slash } from './utils' - -// Fast: loads only slash.js -import { slash } from './utils/slash.js' -``` - -## Warm Up Frequently Used Files - -Pre-transform files that are always loaded: - -```ts -export default defineConfig({ - server: { - warmup: { - clientFiles: [ - './src/components/BigComponent.vue', - './src/utils/big-utils.js' - ], - ssrFiles: ['./src/server/modules/*.js'] - } - } -}) -``` - -Find files to warm up: - -```bash -vite --debug transform -``` - -## Use Native/Less Tooling - -**Do less work:** -- CSS instead of Sass/Less (PostCSS has nesting) -- Don't transform SVGs to components - import as strings/URLs -- Skip Babel in `@vitejs/plugin-react` if not needed - -**Use native tools:** -- Try Lightning CSS for faster CSS processing - -```ts -export default defineConfig({ - css: { - transformer: 'lightningcss' - } -}) -``` - -## Server Options - -### Open Browser Automatically - -Triggers warmup of entry point: - -```ts -export default defineConfig({ - server: { - open: true - } -}) -``` - -### Limit File Watching - -```ts -export default defineConfig({ - server: { - watch: { - ignored: ['**/large-folder/**'] - } - } -}) -``` - -## Build Performance - -### Disable Reporting - -Skip gzip size calculation for large projects: - -```ts -export default defineConfig({ - build: { - reportCompressedSize: false - } -}) -``` - -### Sourcemaps - -Disable if not needed: - -```ts -export default defineConfig({ - build: { - sourcemap: false - } -}) -``` - - diff --git a/skills/vite/references/advanced-plugin-api.md b/skills/vite/references/advanced-plugin-api.md deleted file mode 100644 index c9a30a4..0000000 --- a/skills/vite/references/advanced-plugin-api.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -name: advanced-plugin-api -description: Creating Vite plugins, hooks, virtual modules, and client-server communication ---- - -# Plugin API - -Vite plugins extend Rolldown's plugin interface with Vite-specific hooks. - -## Basic Plugin Structure - -```ts -export default function myPlugin(options = {}) { - return { - name: 'vite-plugin-my-plugin', - - // Hooks... - } -} -``` - -## Naming Conventions - -- Vite-only plugins: `vite-plugin-*` -- Rollup-compatible: `rollup-plugin-*` -- Framework-specific: `vite-plugin-vue-*`, `vite-plugin-react-*` - -## Universal Hooks (from Rolldown) - -Called on server start: -- `options` - Modify Rolldown options -- `buildStart` - Build starting - -Called per module request: -- `resolveId` - Resolve import paths -- `load` - Load module content -- `transform` - Transform module code - -Called on server close: -- `buildEnd` -- `closeBundle` - -## Vite-Specific Hooks - -### `config` - -Modify config before resolution: - -```ts -{ - name: 'modify-config', - config(config, { command, mode }) { - if (command === 'build') { - return { - resolve: { - alias: { foo: 'bar' } - } - } - } - } -} -``` - -### `configResolved` - -Access final resolved config: - -```ts -{ - name: 'read-config', - configResolved(config) { - this.config = config - } -} -``` - -### `configureServer` - -Add dev server middleware: - -```ts -{ - name: 'configure-server', - configureServer(server) { - // Before Vite's middlewares - server.middlewares.use((req, res, next) => { - // Handle request - next() - }) - - // Return function to run after Vite's middlewares - return () => { - server.middlewares.use((req, res, next) => { - // Post middleware - }) - } - } -} -``` - -### `transformIndexHtml` - -Transform HTML files: - -```ts -{ - name: 'html-transform', - transformIndexHtml(html) { - return html.replace(/(.*?)<\/title>/, '<title>New Title') - } -} -``` - -Inject tags: - -```ts -{ - name: 'html-inject', - transformIndexHtml() { - return { - tags: [ - { - tag: 'script', - attrs: { src: '/inject.js' }, - injectTo: 'body' // 'head' | 'body' | 'head-prepend' | 'body-prepend' - } - ] - } - } -} -``` - -### `handleHotUpdate` - -Custom HMR handling: - -```ts -{ - name: 'custom-hmr', - handleHotUpdate({ file, server, modules }) { - if (file.endsWith('.custom')) { - server.ws.send({ - type: 'custom', - event: 'custom-update', - data: { file } - }) - return [] // Prevent default HMR - } - } -} -``` - -## Virtual Modules - -Provide build-time information to source code: - -```ts -export default function myPlugin() { - const virtualModuleId = 'virtual:my-module' - const resolvedId = '\0' + virtualModuleId - - return { - name: 'virtual-module', - - resolveId(id) { - if (id === virtualModuleId) { - return resolvedId - } - }, - - load(id) { - if (id === resolvedId) { - return `export const msg = "from virtual module"` - } - } - } -} -``` - -Usage: - -```ts -import { msg } from 'virtual:my-module' -``` - -## Client-Server Communication - -### Server to Client - -```ts -{ - configureServer(server) { - server.ws.on('connection', () => { - server.ws.send('my:greetings', { msg: 'hello' }) - }) - } -} -``` - -Client receives: - -```ts -if (import.meta.hot) { - import.meta.hot.on('my:greetings', (data) => { - console.log(data.msg) - }) -} -``` - -### Client to Server - -```ts -// Client -if (import.meta.hot) { - import.meta.hot.send('my:from-client', { msg: 'Hey!' }) -} - -// Server (in plugin) -{ - configureServer(server) { - server.ws.on('my:from-client', (data, client) => { - console.log(data.msg) - client.send('my:reply', { msg: 'Got it!' }) - }) - } -} -``` - -## Transform with Filtering - -```ts -{ - name: 'transform-js', - transform: { - filter: { - id: /\.js$/ // Only .js files - }, - handler(code, id) { - return transformCode(code) - } - } -} -``` - -## Path Normalization - -Use POSIX separators for cross-platform compatibility: - -```ts -import { normalizePath } from 'vite' - -normalizePath('foo\\bar') // 'foo/bar' -``` - - diff --git a/skills/vite/references/build-and-ssr.md b/skills/vite/references/build-and-ssr.md new file mode 100644 index 0000000..757a2c7 --- /dev/null +++ b/skills/vite/references/build-and-ssr.md @@ -0,0 +1,238 @@ +--- +name: vite-build-ssr +description: Vite library mode and SSR configuration +--- + +# Build and SSR + +## Library Mode + +Build a library for distribution: + +```ts +// vite.config.ts +import { resolve } from 'node:path' +import { defineConfig } from 'vite' + +export default defineConfig({ + build: { + lib: { + entry: resolve(import.meta.dirname, 'lib/main.ts'), + name: 'MyLib', + fileName: 'my-lib', + }, + rolldownOptions: { + external: ['vue', 'react'], + output: { + globals: { + vue: 'Vue', + react: 'React', + }, + }, + }, + }, +}) +``` + +### Multiple Entries + +```ts +build: { + lib: { + entry: { + 'my-lib': resolve(import.meta.dirname, 'lib/main.ts'), + secondary: resolve(import.meta.dirname, 'lib/secondary.ts'), + }, + name: 'MyLib', + }, +} +``` + +### Output Formats + +- Single entry: `es` and `umd` +- Multiple entries: `es` and `cjs` + +### Package.json Setup + +```json +{ + "name": "my-lib", + "type": "module", + "files": ["dist"], + "main": "./dist/my-lib.umd.cjs", + "module": "./dist/my-lib.js", + "exports": { + ".": { + "import": "./dist/my-lib.js", + "require": "./dist/my-lib.umd.cjs" + }, + "./style.css": "./dist/my-lib.css" + } +} +``` + +## Multi-Page App + +```ts +export default defineConfig({ + build: { + rolldownOptions: { + input: { + main: resolve(import.meta.dirname, 'index.html'), + nested: resolve(import.meta.dirname, 'nested/index.html'), + }, + }, + }, +}) +``` + +## SSR Development + +### Middleware Mode + +Use Vite as middleware in a custom server: + +```ts +import express from 'express' +import { createServer as createViteServer } from 'vite' + +const app = express() + +const vite = await createViteServer({ + server: { middlewareMode: true }, + appType: 'custom', +}) + +app.use(vite.middlewares) + +app.use('*all', async (req, res, next) => { + const url = req.originalUrl + + // 1. Read and transform index.html + let template = await fs.readFile('index.html', 'utf-8') + template = await vite.transformIndexHtml(url, template) + + // 2. Load server entry + const { render } = await vite.ssrLoadModule('/src/entry-server.ts') + + // 3. Render app + const appHtml = await render(url) + + // 4. Inject into template + const html = template.replace('', appHtml) + + res.status(200).set({ 'Content-Type': 'text/html' }).end(html) +}) + +app.listen(5173) +``` + +### SSR Build + +```json +{ + "scripts": { + "build:client": "vite build --outDir dist/client", + "build:server": "vite build --outDir dist/server --ssr src/entry-server.ts" + } +} +``` + +The `--ssr` flag: +- Externalizes dependencies by default +- Outputs for Node.js consumption + +### SSR Manifest + +Generate asset mapping for preload hints: + +```bash +vite build --outDir dist/client --ssrManifest +``` + +Creates `dist/client/.vite/ssr-manifest.json` mapping module IDs to chunks. + +### SSR Externals + +Control which deps get bundled vs externalized: + +```ts +export default defineConfig({ + ssr: { + noExternal: ['some-package'], // Bundle this dep + external: ['another-package'], // Externalize this dep + }, +}) +``` + +### Conditional Logic + +```ts +if (import.meta.env.SSR) { + // Server-only code (tree-shaken from client) +} +``` + +## JavaScript API + +### createServer + +```ts +import { createServer } from 'vite' + +const server = await createServer({ + configFile: false, + root: import.meta.dirname, + server: { port: 1337 }, +}) + +await server.listen() +server.printUrls() +``` + +### build + +```ts +import { build } from 'vite' + +await build({ + root: './project', + build: { outDir: 'dist' }, +}) +``` + +### preview + +```ts +import { preview } from 'vite' + +const previewServer = await preview({ + preview: { port: 8080, open: true }, +}) +previewServer.printUrls() +``` + +### resolveConfig + +```ts +import { resolveConfig } from 'vite' + +const config = await resolveConfig({}, 'build') +``` + +### loadEnv + +```ts +import { loadEnv } from 'vite' + +const env = loadEnv('development', process.cwd(), '') +// Loads all env vars (empty prefix = no filtering) +``` + + diff --git a/skills/vite/references/build-library.md b/skills/vite/references/build-library.md deleted file mode 100644 index e259c56..0000000 --- a/skills/vite/references/build-library.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -name: build-library -description: Building libraries with Vite including proper package.json exports ---- - -# Library Mode - -Build browser-oriented libraries for distribution. - -## Basic Configuration - -```ts -import { resolve } from 'path' -import { defineConfig } from 'vite' - -export default defineConfig({ - build: { - lib: { - entry: resolve(__dirname, 'lib/main.js'), - name: 'MyLib', // Global variable name for UMD - fileName: 'my-lib' // Output filename (without extension) - }, - rolldownOptions: { - external: ['vue'], // Don't bundle these - output: { - globals: { - vue: 'Vue' // Global var for externals in UMD - } - } - } - } -}) -``` - -## Multiple Entry Points - -```ts -export default defineConfig({ - build: { - lib: { - entry: { - 'my-lib': resolve(__dirname, 'lib/main.js'), - 'secondary': resolve(__dirname, 'lib/secondary.js') - }, - name: 'MyLib' - } - } -}) -``` - -## Output Formats - -Single entry defaults: `['es', 'umd']` -Multiple entries defaults: `['es', 'cjs']` - -```ts -export default defineConfig({ - build: { - lib: { - entry: resolve(__dirname, 'lib/main.js'), - formats: ['es', 'cjs', 'umd', 'iife'] - } - } -}) -``` - -## Custom File Names - -```ts -export default defineConfig({ - build: { - lib: { - entry: resolve(__dirname, 'lib/main.js'), - fileName: (format, entryName) => `${entryName}.${format}.js`, - cssFileName: 'styles' // For bundled CSS - } - } -}) -``` - -## Package.json Configuration - -### Single Entry - -```json -{ - "name": "my-lib", - "type": "module", - "files": ["dist"], - "main": "./dist/my-lib.umd.cjs", - "module": "./dist/my-lib.js", - "exports": { - ".": { - "import": "./dist/my-lib.js", - "require": "./dist/my-lib.umd.cjs" - } - } -} -``` - -### Multiple Entries - -```json -{ - "name": "my-lib", - "type": "module", - "files": ["dist"], - "main": "./dist/my-lib.cjs", - "module": "./dist/my-lib.js", - "exports": { - ".": { - "import": "./dist/my-lib.js", - "require": "./dist/my-lib.cjs" - }, - "./secondary": { - "import": "./dist/secondary.js", - "require": "./dist/secondary.cjs" - } - } -} -``` - -### With CSS - -```json -{ - "exports": { - ".": { - "import": "./dist/my-lib.js", - "require": "./dist/my-lib.umd.cjs" - }, - "./style.css": "./dist/my-lib.css" - } -} -``` - -## Library Entry File - -```ts -// lib/main.js -import Foo from './Foo.vue' -import Bar from './Bar.vue' - -export { Foo, Bar } -``` - -## Environment Variables - -In library mode: -- `import.meta.env.*` is statically replaced -- `process.env.*` is NOT replaced (consumers can change it) - -To replace `process.env`: - -```ts -export default defineConfig({ - define: { - 'process.env.NODE_ENV': '"production"' - } -}) -``` - -## Notes - -- `assetsInlineLimit` is ignored - assets always inlined -- `cssCodeSplit` defaults to `false` -- For non-browser libraries, consider using [tsdown](https://tsdown.dev/) or Rolldown directly - - diff --git a/skills/vite/references/build-production.md b/skills/vite/references/build-production.md deleted file mode 100644 index f4152f5..0000000 --- a/skills/vite/references/build-production.md +++ /dev/null @@ -1,220 +0,0 @@ ---- -name: build-production -description: Building for production including targets, multi-page apps, and optimizations ---- - -# Building for Production - -## Basic Build - -```bash -vite build -``` - -Uses `/index.html` as entry point, outputs to `dist/`. - -## Browser Compatibility - -Default target: Baseline Widely Available browsers (Chrome 111+, Edge 111+, Firefox 114+, Safari 16.4+). - -```ts -export default defineConfig({ - build: { - target: 'es2020', // Or specific browsers - // target: ['chrome64', 'firefox78', 'safari12'] - } -}) -``` - -For legacy browsers: - -```bash -npm add -D @vitejs/plugin-legacy -``` - -```ts -import legacy from '@vitejs/plugin-legacy' - -export default defineConfig({ - plugins: [ - legacy({ - targets: ['defaults', 'not IE 11'] - }) - ] -}) -``` - -## Output Configuration - -```ts -export default defineConfig({ - build: { - outDir: 'dist', // Output directory - assetsDir: 'assets', // Assets subdirectory - emptyOutDir: true, // Clear outDir before build - sourcemap: true, // Generate sourcemaps - // sourcemap: 'inline' | 'hidden' - } -}) -``` - -## Public Base Path - -For deploying under a subpath: - -```ts -export default defineConfig({ - base: '/my-app/' -}) -``` - -Relative base (works anywhere): - -```ts -export default defineConfig({ - base: './' -}) -``` - -Access in code: - -```ts -const base = import.meta.env.BASE_URL -``` - -## Multi-Page App - -```ts -import { resolve } from 'path' - -export default defineConfig({ - build: { - rolldownOptions: { - input: { - main: resolve(__dirname, 'index.html'), - nested: resolve(__dirname, 'nested/index.html') - } - } - } -}) -``` - -## Minification - -```ts -export default defineConfig({ - build: { - minify: 'oxc', // Default, fastest - // minify: 'terser', // More options, slower - // minify: false, // Disable - - terserOptions: { // If using terser - compress: { - drop_console: true - } - } - } -}) -``` - -## Chunk Strategy - -```ts -export default defineConfig({ - build: { - rolldownOptions: { - output: { - codeSplitting: { - // Manual chunks configuration - } - } - }, - chunkSizeWarningLimit: 500 // KB - } -}) -``` - -## CSS Options - -```ts -export default defineConfig({ - build: { - cssCodeSplit: true, // CSS per async chunk - cssMinify: 'lightningcss', // or 'esbuild' - cssTarget: 'chrome61' // Different from JS target - } -}) -``` - -## Asset Handling - -```ts -export default defineConfig({ - build: { - assetsInlineLimit: 4096, // Inline assets < 4KB as base64 - copyPublicDir: true // Copy public/ to outDir - } -}) -``` - -## Manifest - -Generate manifest for backend integration: - -```ts -export default defineConfig({ - build: { - manifest: true // .vite/manifest.json - } -}) -``` - -## Watch Mode - -Rebuild on file changes: - -```bash -vite build --watch -``` - -```ts -export default defineConfig({ - build: { - watch: {} // Enable programmatically - } -}) -``` - -## Load Error Handling - -Handle dynamic import failures (e.g., after deployment): - -```ts -window.addEventListener('vite:preloadError', (event) => { - window.location.reload() -}) -``` - -## Build Optimizations (Automatic) - -- **CSS code splitting** - CSS per async chunk -- **Preload directives** - `` -- **Async chunk optimization** - Parallel fetching of dependencies - -## License Generation - -Generate license file for dependencies: - -```ts -export default defineConfig({ - build: { - license: true // .vite/license.md - } -}) -``` - - diff --git a/skills/vite/references/build-ssr.md b/skills/vite/references/build-ssr.md deleted file mode 100644 index b847946..0000000 --- a/skills/vite/references/build-ssr.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -name: build-ssr -description: Server-side rendering setup and configuration with Vite ---- - -# Server-Side Rendering (SSR) - -Low-level API for framework authors. For applications, use higher-level tools from [Awesome Vite SSR](https://github.com/vitejs/awesome-vite#ssr). - -## Project Structure - -``` -├── index.html -├── server.js # Express/Node server -└── src/ - ├── main.js # Universal app code - ├── entry-client.js # Mounts app to DOM - └── entry-server.js # Renders app with SSR API -``` - -## index.html - -```html - - - -
- - - -``` - -## Development Server - -```ts -// server.js -import express from 'express' -import { createServer as createViteServer } from 'vite' - -async function createServer() { - const app = express() - - const vite = await createViteServer({ - server: { middlewareMode: true }, - appType: 'custom' - }) - - app.use(vite.middlewares) - - app.use('*all', async (req, res, next) => { - const url = req.originalUrl - - try { - // 1. Read index.html - let template = fs.readFileSync( - path.resolve(__dirname, 'index.html'), - 'utf-8' - ) - - // 2. Apply Vite transforms - template = await vite.transformIndexHtml(url, template) - - // 3. Load server entry - const { render } = await vite.ssrLoadModule('/src/entry-server.js') - - // 4. Render app HTML - const appHtml = await render(url) - - // 5. Inject into template - const html = template.replace('', appHtml) - - res.status(200).set({ 'Content-Type': 'text/html' }).end(html) - } catch (e) { - vite.ssrFixStacktrace(e) - next(e) - } - }) - - app.listen(5173) -} - -createServer() -``` - -## Conditional Logic - -```ts -if (import.meta.env.SSR) { - // Server-only code (tree-shaken on client) -} -``` - -## Production Build - -```json -{ - "scripts": { - "build:client": "vite build --outDir dist/client", - "build:server": "vite build --outDir dist/server --ssr src/entry-server.js" - } -} -``` - -### Production Server - -```ts -// Differences from dev: -// 1. Use dist/client/index.html as template -// 2. Use import('./dist/server/entry-server.js') instead of ssrLoadModule -// 3. Serve static files from dist/client -``` - -## SSR Manifest - -For preload directives: - -```bash -vite build --outDir dist/client --ssrManifest -``` - -Generates `dist/client/.vite/ssr-manifest.json` with module-to-chunk mappings. - -## SSR Externals - -Dependencies are externalized by default. To transform with Vite: - -```ts -export default defineConfig({ - ssr: { - noExternal: ['package-that-needs-transform'], - external: ['package-to-externalize'] - } -}) -``` - -## SSR-specific Plugin Logic - -```ts -export function mySSRPlugin() { - return { - name: 'my-ssr', - transform(code, id, options) { - if (options?.ssr) { - // SSR-specific transform - } - } - } -} -``` - -## SSR Target - -```ts -export default defineConfig({ - ssr: { - target: 'node', // Default - // target: 'webworker' // For edge runtimes - } -}) -``` - -## SSR Bundle - -Bundle all dependencies (for workers): - -```ts -export default defineConfig({ - ssr: { - noExternal: true // Bundle everything - } -}) -``` - -## Resolve Conditions - -```ts -export default defineConfig({ - ssr: { - resolve: { - conditions: ['node'], - externalConditions: ['node'] - } - } -}) -``` - -## Pre-Rendering / SSG - -Pre-render routes with known data into static HTML at build time. - - diff --git a/skills/vite/references/core-cli.md b/skills/vite/references/core-cli.md deleted file mode 100644 index fb2b762..0000000 --- a/skills/vite/references/core-cli.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -name: core-cli -description: Vite CLI commands for development, building, and previewing ---- - -# Vite CLI - -## Dev Server - -Start the development server: - -```bash -vite [root] -vite dev [root] # alias -vite serve [root] # alias -``` - -### Dev Server Options - -| Option | Description | -|--------|-------------| -| `--host [host]` | Specify hostname (use `0.0.0.0` for LAN access) | -| `--port ` | Specify port (default: 5173) | -| `--open [path]` | Open browser on startup | -| `--cors` | Enable CORS | -| `--strictPort` | Exit if port is in use | -| `--force` | Force optimizer to re-bundle dependencies | -| `-c, --config ` | Use specified config file | -| `--base ` | Public base path | -| `-m, --mode ` | Set env mode | -| `-l, --logLevel ` | info \| warn \| error \| silent | -| `--clearScreen` | Allow/disable clear screen when logging | - -## Build - -Build for production: - -```bash -vite build [root] -``` - -### Build Options - -| Option | Description | -|--------|-------------| -| `--target ` | Transpile target (default: `"modules"`) | -| `--outDir ` | Output directory (default: `dist`) | -| `--assetsDir ` | Assets directory under outDir (default: `"assets"`) | -| `--assetsInlineLimit ` | Inline threshold in bytes (default: 4096) | -| `--ssr [entry]` | Build for SSR | -| `--sourcemap [output]` | Generate source maps (`boolean \| "inline" \| "hidden"`) | -| `--minify [minifier]` | Minifier (`boolean \| "oxc" \| "terser" \| "esbuild"`) | -| `--manifest [name]` | Generate build manifest JSON | -| `--ssrManifest [name]` | Generate SSR manifest JSON | -| `--emptyOutDir` | Force empty outDir | -| `-w, --watch` | Watch mode for rebuilding | - -## Preview - -Locally preview the production build: - -```bash -vite preview [root] -``` - -### Preview Options - -| Option | Description | -|--------|-------------| -| `--host [host]` | Specify hostname | -| `--port ` | Specify port | -| `--strictPort` | Exit if port is in use | -| `--open [path]` | Open browser on startup | -| `--outDir ` | Output directory (default: `dist`) | - -## Package Scripts - -Typical `package.json` scripts: - -```json -{ - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - } -} -``` - -## Running Vite - -```bash -# With npm -npx vite - -# With pnpm -pnpm vite - -# With yarn -yarn vite - -# With bun -bunx vite -``` - -## Scaffolding New Project - -```bash -# Interactive prompts -npm create vite@latest - -# With project name and template -npm create vite@latest my-app -- --template vue-ts - -# Available templates: vanilla, vanilla-ts, vue, vue-ts, react, react-ts, -# react-swc, react-swc-ts, preact, preact-ts, lit, lit-ts, svelte, svelte-ts, -# solid, solid-ts, qwik, qwik-ts -``` - -## Debugging - -```bash -# Debug plugin transforms -vite --debug plugin-transform - -# Debug with profiling -vite --profile -# Then press 'p + enter' to record .cpuprofile - -# Filter debug logs -vite --debug -f plugin-transform -``` - - diff --git a/skills/vite/references/core-config.md b/skills/vite/references/core-config.md index bbe6fee..039ba52 100644 --- a/skills/vite/references/core-config.md +++ b/skills/vite/references/core-config.md @@ -1,13 +1,11 @@ --- -name: core-config -description: Vite configuration file setup, defineConfig helper, conditional and async configs +name: vite-config +description: Vite configuration patterns using vite.config.ts --- # Vite Configuration -Vite automatically resolves a config file named `vite.config.*` in the project root. - -## Basic Configuration +## Basic Setup ```ts // vite.config.ts @@ -18,159 +16,147 @@ export default defineConfig({ }) ``` -Use `defineConfig` for TypeScript intellisense. Alternatively, use JSDoc annotations: - -```js -/** @type {import('vite').UserConfig} */ -export default { - // config options -} -``` +Vite auto-resolves `vite.config.ts` from project root. Supports ES modules syntax regardless of `package.json` type. ## Conditional Config -Export a function to conditionally determine options based on command, mode, or build type: +Export a function to access command and mode: ```ts -import { defineConfig } from 'vite' - export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => { if (command === 'serve') { - // dev specific config - return { - define: { - __DEV__: true - } - } + return { /* dev config */ } } else { - // build specific config - return { - define: { - __DEV__: false - } - } + return { /* build config */ } } }) ``` -- `command` is `'serve'` during dev (`vite`, `vite dev`, `vite serve`) and `'build'` for production -- `mode` defaults to `'development'` for serve, `'production'` for build +- `command`: `'serve'` during dev, `'build'` for production +- `mode`: `'development'` or `'production'` (or custom via `--mode`) ## Async Config ```ts -import { defineConfig } from 'vite' - export default defineConfig(async ({ command, mode }) => { - const data = await fetchRemoteConfig() - return { - // config using fetched data - } -}) -``` - -## Key Configuration Options - -### Root and Base - -```ts -export default defineConfig({ - root: './src', // Project root directory (where index.html is) - base: '/my-app/', // Public base path for assets - publicDir: 'public', // Static assets directory - cacheDir: 'node_modules/.vite' // Cache directory -}) -``` - -### Resolve Aliases - -```ts -import { resolve } from 'path' - -export default defineConfig({ - resolve: { - alias: { - '@': resolve(__dirname, 'src'), - '~': resolve(__dirname, 'src/components') - }, - // File extensions to try for imports without extension - extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'] - } -}) -``` - -### Define Global Constants - -```ts -export default defineConfig({ - define: { - __APP_VERSION__: JSON.stringify('1.0.0'), - __API_URL__: JSON.stringify('https://api.example.com') - } -}) -``` - -Values must be JSON-serializable or a single identifier. Add TypeScript declarations: - -```ts -// vite-env.d.ts -declare const __APP_VERSION__: string -declare const __API_URL__: string -``` - -### JSON Handling - -```ts -export default defineConfig({ - json: { - namedExports: true, // Support named imports from JSON - stringify: 'auto' // Stringify large JSON for performance - } + const data = await fetchSomething() + return { /* config */ } }) ``` ## Using Environment Variables in Config -Variables from `.env` files are NOT automatically available in config. Use `loadEnv`: +`.env` files are loaded **after** config resolution. Use `loadEnv` to access them in config: ```ts import { defineConfig, loadEnv } from 'vite' export default defineConfig(({ mode }) => { - // Load env vars from .env files + // Load env files from cwd, include all vars (empty prefix) const env = loadEnv(mode, process.cwd(), '') return { define: { - __APP_ENV__: JSON.stringify(env.APP_ENV) + __APP_ENV__: JSON.stringify(env.APP_ENV), }, server: { - port: env.APP_PORT ? Number(env.APP_PORT) : 5173 - } + port: env.APP_PORT ? Number(env.APP_PORT) : 5173, + }, } }) ``` -## Specifying Config File +## Key Config Options -```bash -vite --config my-config.ts +### resolve.alias + +```ts +export default defineConfig({ + resolve: { + alias: { + '@': '/src', + '~': '/src', + }, + }, +}) ``` -## Config Loading Methods +### define (Global Constants) -```bash -# Default: bundle with Rolldown (may have issues in monorepos) -vite - -# Use module runner (no temp file, transforms on the fly) -vite --configLoader runner - -# Use native runtime (requires Node.js with TypeScript support) -vite --configLoader native +```ts +export default defineConfig({ + define: { + __APP_VERSION__: JSON.stringify('1.0.0'), + __API_URL__: 'window.__backend_api_url', + }, +}) ``` - diff --git a/skills/vite/references/core-features.md b/skills/vite/references/core-features.md index 8a3d79b..1403ac9 100644 --- a/skills/vite/references/core-features.md +++ b/skills/vite/references/core-features.md @@ -1,170 +1,205 @@ --- -name: core-features -description: Core Vite features including TypeScript, JSX, CSS, and HTML processing +name: vite-features +description: Vite-specific import patterns and runtime features --- -# Core Features +# Vite Features -## TypeScript +## Glob Import -Vite supports `.ts` files out of the box with transpilation via Oxc Transformer (20-30x faster than tsc). - -### Important: Transpile Only - -Vite does NOT perform type checking. Run type checking separately: - -```bash -# Production build -tsc --noEmit && vite build - -# During development (separate process) -tsc --noEmit --watch - -# Or use vite-plugin-checker for browser error reporting -``` - -### TypeScript Configuration - -Required `tsconfig.json` settings: - -```json -{ - "compilerOptions": { - "isolatedModules": true, - "useDefineForClassFields": true, - "skipLibCheck": true - } -} -``` - -### Client Types - -Add Vite's client types for `import.meta.env` and asset imports: - -```json -{ - "compilerOptions": { - "types": ["vite/client"] - } -} -``` - -This provides types for: -- Asset imports (`.svg`, `.png`, etc.) -- `import.meta.env` constants -- `import.meta.hot` HMR API - -### Custom Type Overrides - -Override default asset import types: +Import multiple modules matching a pattern: ```ts -// vite-env-override.d.ts -declare module '*.svg' { - const content: React.FC> - export default content +const modules = import.meta.glob('./dir/*.ts') +// { './dir/foo.ts': () => import('./dir/foo.ts'), ... } + +for (const path in modules) { + modules[path]().then((mod) => { + console.log(path, mod) + }) } ``` -### Path Aliases with tsconfig - -Enable tsconfig paths resolution: +### Eager Loading ```ts -// vite.config.ts -export default defineConfig({ - resolve: { - tsconfigPaths: true - } +const modules = import.meta.glob('./dir/*.ts', { eager: true }) +// Modules loaded immediately, no dynamic import +``` + +### Named Imports + +```ts +const modules = import.meta.glob('./dir/*.ts', { import: 'setup' }) +// Only imports the 'setup' export from each module + +const defaults = import.meta.glob('./dir/*.ts', { import: 'default', eager: true }) +``` + +### Multiple Patterns + +```ts +const modules = import.meta.glob(['./dir/*.ts', './another/*.ts']) +``` + +### Negative Patterns + +```ts +const modules = import.meta.glob(['./dir/*.ts', '!**/ignored.ts']) +``` + +### Custom Queries + +```ts +const svgRaw = import.meta.glob('./icons/*.svg', { query: '?raw', import: 'default' }) +const svgUrls = import.meta.glob('./icons/*.svg', { query: '?url', import: 'default' }) +``` + +## Asset Import Queries + +### URL Import + +```ts +import imgUrl from './img.png' +// Returns resolved URL: '/src/img.png' (dev) or '/assets/img.2d8efhg.png' (build) +``` + +### Explicit URL + +```ts +import workletUrl from './worklet.js?url' +``` + +### Raw String + +```ts +import shaderCode from './shader.glsl?raw' +``` + +### Inline/No-Inline + +```ts +import inlined from './small.png?inline' // Force base64 inline +import notInlined from './large.png?no-inline' // Force separate file +``` + +### Web Workers + +```ts +import Worker from './worker.ts?worker' +const worker = new Worker() + +// Or inline: +import InlineWorker from './worker.ts?worker&inline' +``` + +Preferred pattern using constructor: + +```ts +const worker = new Worker(new URL('./worker.ts', import.meta.url), { + type: 'module', }) ``` -## JSX +## Environment Variables -`.jsx` and `.tsx` files are supported out of the box. Custom JSX configuration: +### Built-in Constants ```ts -export default defineConfig({ - oxc: { - jsx: { - runtime: 'classic', // or 'automatic' - pragma: 'h', - pragmaFrag: 'Fragment' - }, - // Auto-inject JSX helpers - jsxInject: `import React from 'react'` - } -}) +import.meta.env.MODE // 'development' | 'production' | custom +import.meta.env.BASE_URL // Base URL from config +import.meta.env.PROD // true in production +import.meta.env.DEV // true in development +import.meta.env.SSR // true when running in server ``` -## HTML +### Custom Variables -`index.html` is the entry point, not tucked away in `public/`. Vite processes it as part of the module graph. +Only `VITE_` prefixed vars exposed to client: -### Supported Elements +``` +# .env +VITE_API_URL=https://api.example.com +DB_PASSWORD=secret # NOT exposed to client +``` -Vite processes these HTML element attributes: +```ts +console.log(import.meta.env.VITE_API_URL) // works +console.log(import.meta.env.DB_PASSWORD) // undefined +``` -- ` +

Running in %MODE%

+ ``` -### Multi-Page Apps +## CSS Modules -Access any HTML file by its path: - -- `/index.html` → `http://localhost:5173/` -- `/about.html` → `http://localhost:5173/about.html` -- `/blog/index.html` → `http://localhost:5173/blog/index.html` - -## JSON - -Direct import with named exports support: +Any `.module.css` file treated as CSS module: ```ts -// Import entire object -import json from './data.json' - -// Named imports (tree-shakeable) -import { field } from './data.json' +import styles from './component.module.css' +element.className = styles.button ``` -## Framework Support - -Official framework plugins: - -| Framework | Plugin | -|-----------|--------| -| Vue 3 | `@vitejs/plugin-vue` | -| Vue 3 JSX | `@vitejs/plugin-vue-jsx` | -| React | `@vitejs/plugin-react` | -| React (SWC) | `@vitejs/plugin-react-swc` | -| React Server Components | `@vitejs/plugin-rsc` | -| Legacy browsers | `@vitejs/plugin-legacy` | - -## Content Security Policy - -Configure nonce for CSP: +With camelCase conversion: ```ts -export default defineConfig({ - html: { - cspNonce: 'PLACEHOLDER' // Replace per-request - } -}) +// .my-class -> myClass (if css.modules.localsConvention configured) +import { myClass } from './component.module.css' ``` - diff --git a/skills/vite/references/core-plugin-api.md b/skills/vite/references/core-plugin-api.md new file mode 100644 index 0000000..c115851 --- /dev/null +++ b/skills/vite/references/core-plugin-api.md @@ -0,0 +1,235 @@ +--- +name: vite-plugin-api +description: Vite plugin authoring with Vite-specific hooks +--- + +# Vite Plugin API + +Vite plugins extend Rolldown's plugin interface with Vite-specific hooks. + +## Basic Structure + +```ts +function myPlugin(): Plugin { + return { + name: 'my-plugin', + // hooks... + } +} +``` + +## Vite-Specific Hooks + +### config + +Modify config before resolution: + +```ts +const plugin = () => ({ + name: 'add-alias', + config: () => ({ + resolve: { + alias: { foo: 'bar' }, + }, + }), +}) +``` + +### configResolved + +Access final resolved config: + +```ts +const plugin = () => { + let config: ResolvedConfig + return { + name: 'read-config', + configResolved(resolvedConfig) { + config = resolvedConfig + }, + transform(code, id) { + if (config.command === 'serve') { /* dev */ } + }, + } +} +``` + +### configureServer + +Add custom middleware to dev server: + +```ts +const plugin = () => ({ + name: 'custom-middleware', + configureServer(server) { + server.middlewares.use((req, res, next) => { + // handle request + next() + }) + }, +}) +``` + +Return function to run **after** internal middlewares: + +```ts +configureServer(server) { + return () => { + server.middlewares.use((req, res, next) => { + // runs after Vite's middlewares + }) + } +} +``` + +### transformIndexHtml + +Transform HTML entry files: + +```ts +const plugin = () => ({ + name: 'html-transform', + transformIndexHtml(html) { + return html.replace(/(.*?)<\/title>/, '<title>New Title') + }, +}) +``` + +Inject tags: + +```ts +transformIndexHtml() { + return [ + { tag: 'script', attrs: { src: '/inject.js' }, injectTo: 'body' }, + ] +} +``` + +### handleHotUpdate + +Custom HMR handling: + +```ts +handleHotUpdate({ server, modules, timestamp }) { + server.ws.send({ type: 'custom', event: 'special-update', data: {} }) + return [] // empty = skip default HMR +} +``` + +## Virtual Modules + +Serve virtual content without files on disk: + +```ts +const plugin = () => { + const virtualModuleId = 'virtual:my-module' + const resolvedId = '\0' + virtualModuleId + + return { + name: 'virtual-module', + resolveId(id) { + if (id === virtualModuleId) return resolvedId + }, + load(id) { + if (id === resolvedId) { + return `export const msg = "from virtual module"` + } + }, + } +} +``` + +Usage: + +```ts +import { msg } from 'virtual:my-module' +``` + +Convention: prefix user-facing path with `virtual:`, prefix resolved id with `\0`. + +## Plugin Ordering + +Use `enforce` to control execution order: + +```ts +{ + name: 'pre-plugin', + enforce: 'pre', // runs before core plugins +} + +{ + name: 'post-plugin', + enforce: 'post', // runs after build plugins +} +``` + +Order: Alias → `enforce: 'pre'` → Core → User (no enforce) → Build → `enforce: 'post'` → Post-build + +## Conditional Application + +```ts +{ + name: 'build-only', + apply: 'build', // or 'serve' +} + +// Function form: +{ + apply(config, { command }) { + return command === 'build' && !config.build.ssr + } +} +``` + +## Universal Hooks (from Rolldown) + +These work in both dev and build: + +- `resolveId(id, importer)` - Resolve import paths +- `load(id)` - Load module content +- `transform(code, id)` - Transform module code + +```ts +transform(code, id) { + if (id.endsWith('.custom')) { + return { code: compile(code), map: null } + } +} +``` + +## Client-Server Communication + +Server to client: + +```ts +configureServer(server) { + server.ws.send('my:event', { msg: 'hello' }) +} +``` + +Client side: + +```ts +if (import.meta.hot) { + import.meta.hot.on('my:event', (data) => { + console.log(data.msg) + }) +} +``` + +Client to server: + +```ts +// Client +import.meta.hot.send('my:from-client', { msg: 'Hey!' }) + +// Server +server.ws.on('my:from-client', (data, client) => { + client.send('my:ack', { msg: 'Got it!' }) +}) +``` + + diff --git a/skills/vite/references/core-plugins.md b/skills/vite/references/core-plugins.md deleted file mode 100644 index 6fde148..0000000 --- a/skills/vite/references/core-plugins.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -name: core-plugins -description: Adding, configuring, and ordering Vite plugins ---- - -# Using Plugins - -Vite extends Rolldown's plugin interface with extra Vite-specific options. - -## Adding Plugins - -Install and add to config: - -```bash -npm add -D @vitejs/plugin-vue -``` - -```ts -// vite.config.ts -import vue from '@vitejs/plugin-vue' -import { defineConfig } from 'vite' - -export default defineConfig({ - plugins: [vue()] -}) -``` - -## Plugin Arrays - -Plugins can return arrays (for complex features): - -```ts -// Framework plugin returning multiple plugins -export default function framework(config) { - return [ - frameworkRefresh(config), - frameworkDevtools(config) - ] -} -``` - -## Conditional Plugins - -Falsy values are ignored: - -```ts -export default defineConfig({ - plugins: [ - vue(), - process.env.ANALYZE && visualizer() // Only if ANALYZE is set - ] -}) -``` - -## Enforcing Plugin Order - -Control when plugin runs relative to Vite core: - -```ts -export default defineConfig({ - plugins: [ - { - ...somePlugin(), - enforce: 'pre' // Before Vite core plugins - }, - { - ...anotherPlugin(), - enforce: 'post' // After Vite build plugins - } - ] -}) -``` - -**Order:** -1. Alias -2. Plugins with `enforce: 'pre'` -3. Vite core plugins -4. Plugins without enforce -5. Vite build plugins -6. Plugins with `enforce: 'post'` -7. Vite post-build plugins (minify, manifest) - -## Conditional Application - -Apply only during serve or build: - -```ts -export default defineConfig({ - plugins: [ - { - ...typescript2(), - apply: 'build' // Only during build - }, - { - ...devOnlyPlugin(), - apply: 'serve' // Only during dev - } - ] -}) -``` - -Function form for more control: - -```ts -{ - ...myPlugin(), - apply(config, { command }) { - // Apply only on build but not for SSR - return command === 'build' && !config.build.ssr - } -} -``` - -## Finding Plugins - -1. Check [Vite Features Guide](https://vite.dev/guide/features.html) - many use cases are built-in -2. Official plugins in [Vite Plugins](https://vite.dev/plugins/) -3. Community plugins in [awesome-vite](https://github.com/vitejs/awesome-vite#plugins) -4. Search npm for `vite-plugin-*` or `rollup-plugin-*` - -## Official Plugins - -| Plugin | Purpose | -|--------|---------| -| `@vitejs/plugin-vue` | Vue 3 SFC support | -| `@vitejs/plugin-vue-jsx` | Vue 3 JSX support | -| `@vitejs/plugin-react` | React with Babel/Oxc | -| `@vitejs/plugin-react-swc` | React with SWC | -| `@vitejs/plugin-rsc` | React Server Components | -| `@vitejs/plugin-legacy` | Legacy browser support | - -## Rollup/Rolldown Plugin Compatibility - -Many Rollup plugins work directly with Vite if they: -- Don't use `moduleParsed` hook -- Don't rely on Rolldown-specific options -- Don't have strong coupling between bundle and output phases - -For build-only Rollup plugins: - -```ts -export default defineConfig({ - build: { - rolldownOptions: { - plugins: [rollupPluginForBuildOnly()] - } - } -}) -``` - - diff --git a/skills/vite/references/environment-api.md b/skills/vite/references/environment-api.md new file mode 100644 index 0000000..006ff7f --- /dev/null +++ b/skills/vite/references/environment-api.md @@ -0,0 +1,108 @@ +--- +name: vite-environment-api +description: Vite 6+ Environment API for multiple runtime environments +--- + +# Environment API (Vite 6+) + +The Environment API formalizes multiple runtime environments beyond the traditional client/SSR split. + +## Concept + +Before Vite 6: Two implicit environments (`client` and `ssr`). + +Vite 6+: Configure as many environments as needed (browser, node server, edge server, etc.). + +## Basic Configuration + +For SPA/MPA, nothing changes—options apply to the implicit `client` environment: + +```ts +export default defineConfig({ + build: { sourcemap: false }, + optimizeDeps: { include: ['lib'] }, +}) +``` + +## Multiple Environments + +```ts +export default defineConfig({ + build: { sourcemap: false }, // Inherited by all environments + optimizeDeps: { include: ['lib'] }, // Client only + environments: { + // SSR environment + server: {}, + // Edge runtime environment + edge: { + resolve: { noExternal: true }, + }, + }, +}) +``` + +Environments inherit top-level config. Some options (like `optimizeDeps`) only apply to `client` by default. + +## Environment Options + +```ts +interface EnvironmentOptions { + define?: Record + resolve?: EnvironmentResolveOptions + optimizeDeps: DepOptimizationOptions + consumer?: 'client' | 'server' + dev: DevOptions + build: BuildOptions +} +``` + +## Custom Environment Instances + +Runtime providers can define custom environments: + +```ts +import { customEnvironment } from 'vite-environment-provider' + +export default defineConfig({ + environments: { + ssr: customEnvironment({ + build: { outDir: '/dist/ssr' }, + }), + }, +}) +``` + +Example: Cloudflare's Vite plugin runs code in `workerd` runtime during development. + +## Backward Compatibility + +- `server.moduleGraph` returns mixed client/SSR view +- `ssrLoadModule` still works +- Existing SSR apps work unchanged + +## When to Use + +- **End users**: Usually don't need to configure—frameworks handle it +- **Plugin authors**: Use for environment-aware transformations +- **Framework authors**: Create custom environments for their runtime needs + +## Plugin Environment Access + +Plugins can access environment in hooks: + +```ts +{ + name: 'env-aware', + transform(code, id, options) { + if (options?.ssr) { + // SSR-specific transform + } + }, +} +``` + + diff --git a/skills/vite/references/features-assets.md b/skills/vite/references/features-assets.md deleted file mode 100644 index 584407a..0000000 --- a/skills/vite/references/features-assets.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -name: features-assets -description: Static asset handling in Vite including imports, public directory, and URL handling ---- - -# Static Asset Handling - -## Importing Assets as URL - -```ts -import imgUrl from './img.png' -document.getElementById('hero-img').src = imgUrl -// Dev: /src/img.png -// Build: /assets/img.2d8efhg.png -``` - -Common image, media, and font types are detected automatically. - -## Import Queries - -### Explicit URL Import - -```ts -import workletURL from './worklet.js?url' -CSS.paintWorklet.addModule(workletURL) -``` - -### Import as String (Raw) - -```ts -import shaderString from './shader.glsl?raw' -``` - -### Control Inlining - -```ts -import imgUrl1 from './img.svg?no-inline' // Never inline -import imgUrl2 from './img.png?inline' // Always inline as base64 -``` - -## Asset Inlining - -Assets smaller than `assetsInlineLimit` (default 4KB) are inlined as base64: - -```ts -export default defineConfig({ - build: { - assetsInlineLimit: 4096, // 4KB - // Or use callback for fine control - assetsInlineLimit: (filePath) => { - return !filePath.endsWith('.svg') - } - } -}) -``` - -## The `public` Directory - -Files in `public/` are: -- Served at root path `/` during dev -- Copied as-is to `dist/` root during build -- Not processed or hashed - -``` -public/ - favicon.ico → /favicon.ico - robots.txt → /robots.txt -``` - -Reference with absolute paths in source: - -```html - -``` - -Configure directory: - -```ts -export default defineConfig({ - publicDir: 'static' // or false to disable -}) -``` - -## Extending Asset Types - -```ts -export default defineConfig({ - assetsInclude: ['**/*.gltf', '**/*.hdr'] -}) -``` - -## Dynamic URLs with import.meta.url - -```ts -// Works natively in modern browsers -const imgUrl = new URL('./img.png', import.meta.url).href - -// Dynamic pattern (limited) -function getImageUrl(name) { - return new URL(`./dir/${name}.png`, import.meta.url).href -} -``` - -**Limitations:** -- URL string must be static for build analysis -- Does not work with SSR (different semantics in Node.js vs browser) - -## TypeScript Support - -Add `vite/client` to types for asset import recognition: - -```json -{ - "compilerOptions": { - "types": ["vite/client"] - } -} -``` - -## URL Handling in CSS - -```css -.hero { - background: url('./img.png'); /* Processed and rebased */ -} -``` - -For dynamically constructed SVG URLs: - -```ts -import imgUrl from './img.svg' -element.style.background = `url("${imgUrl}")` // Note double quotes -``` - - diff --git a/skills/vite/references/features-css.md b/skills/vite/references/features-css.md deleted file mode 100644 index 705950c..0000000 --- a/skills/vite/references/features-css.md +++ /dev/null @@ -1,215 +0,0 @@ ---- -name: features-css -description: CSS handling in Vite including modules, pre-processors, PostCSS, and Lightning CSS ---- - -# CSS Handling - -Vite provides rich CSS support with HMR, `@import` inlining, and automatic URL rebasing. - -## Basic CSS Import - -```ts -import './styles.css' // Injected into page with HMR support -``` - -## CSS Modules - -Files ending with `.module.css` are treated as CSS modules: - -```css -/* example.module.css */ -.red { - color: red; -} -``` - -```ts -import classes from './example.module.css' -element.className = classes.red -``` - -### Named Imports with camelCase - -```ts -// vite.config.ts -export default defineConfig({ - css: { - modules: { - localsConvention: 'camelCaseOnly' - } - } -}) -``` - -```ts -// .apply-color -> applyColor -import { applyColor } from './example.module.css' -``` - -## CSS Pre-processors - -Install the pre-processor, no Vite plugin needed: - -```bash -# Sass (sass-embedded recommended for performance) -npm add -D sass-embedded - -# Less -npm add -D less - -# Stylus -npm add -D stylus -``` - -Use by file extension: - -```ts -import './styles.scss' -import './styles.less' -import './styles.styl' -``` - -### Pre-processor Options - -```ts -export default defineConfig({ - css: { - preprocessorOptions: { - scss: { - additionalData: `$injectedColor: orange;`, - importers: [/* ... */] - }, - less: { - math: 'parens-division' - } - }, - preprocessorMaxWorkers: true // Use multiple threads - } -}) -``` - -### Combined with CSS Modules - -```ts -import styles from './component.module.scss' -``` - -## PostCSS - -Automatically applied if `postcss.config.js` exists: - -```js -// postcss.config.js -export default { - plugins: [ - require('postcss-nesting'), - require('autoprefixer') - ] -} -``` - -Or configure inline: - -```ts -export default defineConfig({ - css: { - postcss: { - plugins: [ - postcssNesting(), - autoprefixer() - ] - } - } -}) -``` - -## Lightning CSS - -Experimental faster CSS processing: - -```bash -npm add -D lightningcss -``` - -```ts -export default defineConfig({ - css: { - transformer: 'lightningcss', - lightningcss: { - targets: { - chrome: 111 - }, - cssModules: { - // Lightning CSS modules config - } - } - } -}) -``` - -Use Lightning CSS for minification only: - -```ts -export default defineConfig({ - build: { - cssMinify: 'lightningcss' - } -}) -``` - -## Disable CSS Injection - -Import CSS as string without injecting: - -```ts -import styles from './styles.css?inline' // Returns CSS string, not injected -``` - -## Source Maps - -Enable CSS source maps in development: - -```ts -export default defineConfig({ - css: { - devSourcemap: true - } -}) -``` - -## CSS Code Splitting - -By default, CSS is extracted per async chunk. Disable to get single CSS file: - -```ts -export default defineConfig({ - build: { - cssCodeSplit: false // Single CSS file for entire app - } -}) -``` - -## CSS Target - -Set different browser target for CSS: - -```ts -export default defineConfig({ - build: { - cssTarget: 'chrome61' // For Android WeChat WebView - } -}) -``` - -## @import and URL Handling - -- `@import` statements are inlined automatically -- Vite aliases work in `@import` -- `url()` references are rebased for correctness -- Works across Sass/Less files in different directories - - diff --git a/skills/vite/references/features-dep-bundling.md b/skills/vite/references/features-dep-bundling.md deleted file mode 100644 index fe830ab..0000000 --- a/skills/vite/references/features-dep-bundling.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -name: features-dep-bundling -description: Dependency pre-bundling configuration and caching ---- - -# Dependency Pre-Bundling - -Vite pre-bundles dependencies on first run for faster dev server startup. - -## Why Pre-Bundling - -1. **CommonJS/UMD to ESM** - Convert non-ESM dependencies -2. **Performance** - Bundle many internal modules into single file (e.g., lodash-es has 600+ modules) - -```ts -// Works thanks to smart import analysis -import React, { useState } from 'react' -``` - -## Automatic Discovery - -Vite crawls source code to find bare imports and pre-bundles them with Rolldown. - -New dependencies discovered after server start trigger re-bundling. - -## Including Dependencies - -Force pre-bundling for dependencies not auto-discovered: - -```ts -export default defineConfig({ - optimizeDeps: { - include: [ - 'some-package', - 'another-package/nested' // Deep imports - ] - } -}) -``` - -**When to include:** -- Dynamically imported (via plugin transform) -- Large dependencies with many internal modules -- CommonJS dependencies - -## Excluding Dependencies - -Skip pre-bundling for small ESM-only dependencies: - -```ts -export default defineConfig({ - optimizeDeps: { - exclude: ['small-esm-dep'] - } -}) -``` - -## Monorepo Linked Dependencies - -Linked packages are treated as source code by default. If not ESM: - -```ts -export default defineConfig({ - optimizeDeps: { - include: ['linked-dep'] - } -}) -``` - -Restart with `--force` after making changes to linked deps. - -## Custom Rolldown Options - -```ts -export default defineConfig({ - optimizeDeps: { - rolldownOptions: { - plugins: [/* Rolldown plugins */], - // Other Rolldown options - } - } -}) -``` - -## Caching - -### File System Cache - -Located in `node_modules/.vite`. Re-runs when: - -- Package lockfile changes (`package-lock.json`, `pnpm-lock.yaml`, etc.) -- Patches folder modified -- `vite.config.js` changes -- `NODE_ENV` changes - -Force re-bundle: - -```bash -vite --force -# Or delete node_modules/.vite -``` - -### Browser Cache - -Pre-bundled deps are cached with `max-age=31536000,immutable`. - -To debug dependencies with local edits: - -1. Disable cache in browser DevTools Network tab -2. Restart Vite with `--force` -3. Reload page - -## Entries - -Specify custom entry points for discovery: - -```ts -export default defineConfig({ - optimizeDeps: { - entries: [ - 'src/main.ts', - 'src/other-entry.ts' - ] - } -}) -``` - -By default, all HTML files are used as entries. - -## esbuildOptions (Deprecated) - -Use `rolldownOptions` instead: - -```ts -export default defineConfig({ - optimizeDeps: { - // Deprecated - esbuildOptions: {}, - // Use instead - rolldownOptions: {} - } -}) -``` - - diff --git a/skills/vite/references/features-env.md b/skills/vite/references/features-env.md deleted file mode 100644 index 32320f7..0000000 --- a/skills/vite/references/features-env.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -name: features-env -description: Environment variables, .env files, and modes in Vite ---- - -# Environment Variables and Modes - -## Built-in Constants - -Available via `import.meta.env`: - -| Constant | Description | -|----------|-------------| -| `import.meta.env.MODE` | App mode (`'development'` or `'production'`) | -| `import.meta.env.BASE_URL` | Base URL from `base` config | -| `import.meta.env.PROD` | `true` in production | -| `import.meta.env.DEV` | `true` in development | -| `import.meta.env.SSR` | `true` in server-side rendering | - -```ts -if (import.meta.env.DEV) { - console.log('Development mode') - // Tree-shaken in production -} -``` - -## Custom Environment Variables - -Only variables prefixed with `VITE_` are exposed to client code: - -```bash -# .env -VITE_API_URL=https://api.example.com -DB_PASSWORD=secret # NOT exposed to client -``` - -```ts -console.log(import.meta.env.VITE_API_URL) // "https://api.example.com" -console.log(import.meta.env.DB_PASSWORD) // undefined -``` - -### Custom Prefix - -```ts -export default defineConfig({ - envPrefix: ['VITE_', 'APP_'] // Expose VITE_* and APP_* -}) -``` - -## .env Files - -Load order (later has higher priority): - -``` -.env # Always loaded -.env.local # Always loaded, gitignored -.env.[mode] # Only in specified mode -.env.[mode].local # Only in specified mode, gitignored -``` - -### Variable Expansion - -```bash -# .env -KEY=123 -EXPANDED=test$KEY # test123 -ESCAPED=test\$foo # test$foo (escaped) -``` - -## Modes - -```bash -# Development mode (default for dev) -vite - -# Production mode (default for build) -vite build - -# Custom mode -vite build --mode staging -``` - -Create mode-specific env file: - -```bash -# .env.staging -VITE_APP_TITLE=My App (staging) -NODE_ENV=production # Still production build -``` - -### NODE_ENV vs Mode - -| Command | NODE_ENV | Mode | -|---------|----------|------| -| `vite build` | `production` | `production` | -| `vite build --mode development` | `production` | `development` | -| `NODE_ENV=development vite build` | `development` | `production` | - -## TypeScript IntelliSense - -Create type declarations for custom env variables: - -```ts -// vite-env.d.ts -interface ImportMetaEnv { - readonly VITE_APP_TITLE: string - readonly VITE_API_URL: string -} - -interface ImportMeta { - readonly env: ImportMetaEnv -} -``` - -For strict typing (disallow unknown keys): - -```ts -interface ViteTypeOptions { - strictImportMetaEnv: unknown -} -``` - -## HTML Replacement - -Use `%VARIABLE%` syntax in HTML: - -```html -%VITE_APP_TITLE% -

Mode: %MODE%

-``` - -Non-existent variables are left as-is (not replaced with `undefined`). - -## Loading Env in Config - -Env vars are NOT available in `vite.config.ts` automatically: - -```ts -import { defineConfig, loadEnv } from 'vite' - -export default defineConfig(({ mode }) => { - const env = loadEnv(mode, process.cwd(), '') // '' loads all vars - - return { - define: { - __APP_ENV__: JSON.stringify(env.APP_ENV) - } - } -}) -``` - -## Security Notes - -- Add `*.local` to `.gitignore` -- `VITE_*` variables end up in client bundle - no secrets -- Never set `envPrefix` to `''` (exposes everything) - - diff --git a/skills/vite/references/features-glob-import.md b/skills/vite/references/features-glob-import.md deleted file mode 100644 index b24576a..0000000 --- a/skills/vite/references/features-glob-import.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -name: features-glob-import -description: Vite's import.meta.glob for batch importing modules and dynamic imports ---- - -# Glob Import - -## Basic Usage - -Import multiple modules using glob patterns: - -```ts -const modules = import.meta.glob('./dir/*.js') -// Transformed to: -// { -// './dir/foo.js': () => import('./dir/foo.js'), -// './dir/bar.js': () => import('./dir/bar.js'), -// } -``` - -Iterate and load: - -```ts -for (const path in modules) { - modules[path]().then((mod) => { - console.log(path, mod) - }) -} -``` - -## Eager Loading - -Load all modules immediately (no dynamic import): - -```ts -const modules = import.meta.glob('./dir/*.js', { eager: true }) -// Transformed to: -// import * as __glob_0 from './dir/foo.js' -// import * as __glob_1 from './dir/bar.js' -// const modules = { -// './dir/foo.js': __glob_0, -// './dir/bar.js': __glob_1, -// } -``` - -## Multiple Patterns - -```ts -const modules = import.meta.glob([ - './dir/*.js', - './another/*.js' -]) -``` - -## Negative Patterns - -Exclude files with `!` prefix: - -```ts -const modules = import.meta.glob([ - './dir/*.js', - '!**/bar.js' // Exclude bar.js -]) -``` - -## Named Imports - -Import specific exports for tree-shaking: - -```ts -const modules = import.meta.glob('./dir/*.js', { - import: 'setup' -}) -// './dir/foo.js': () => import('./dir/foo.js').then(m => m.setup) -``` - -Import default export: - -```ts -const modules = import.meta.glob('./dir/*.js', { - import: 'default', - eager: true -}) -``` - -## Custom Queries - -Import as raw strings or URLs: - -```ts -const moduleStrings = import.meta.glob('./dir/*.svg', { - query: '?raw', - import: 'default' -}) - -const moduleUrls = import.meta.glob('./dir/*.svg', { - query: '?url', - import: 'default' -}) -``` - -Custom queries for plugins: - -```ts -const modules = import.meta.glob('./dir/*.js', { - query: { foo: 'bar', bar: true } -}) -``` - -## Base Path - -Change the base path for imports: - -```ts -const modules = import.meta.glob('./**/*.js', { - base: './base' -}) -// Keys: './dir/foo.js' -// Imports: './base/dir/foo.js' -``` - -## Important Caveats - -1. **Vite-only feature** - Not a web standard -2. **Patterns must be literals** - Cannot use variables -3. **Relative or absolute** - Must start with `./`, `/`, or use an alias -4. **Glob matching** - Uses [tinyglobby](https://github.com/SuperchupuDev/tinyglobby) - -## Dynamic Import with Variables - -Limited dynamic import support: - -```ts -const module = await import(`./dir/${file}.js`) -``` - -**Rules:** -- Must start with `./` or `../` -- Must end with file extension -- Variable represents only one level (no `foo/bar`) -- Own directory needs filename pattern: `./prefix-${foo}.js` not `./${foo}.js` - -## Practical Example: Loading Route Components - -```ts -// Lazy load all page components -const pages = import.meta.glob('./pages/*.vue') - -const routes = Object.keys(pages).map((path) => { - const name = path.match(/\.\/pages\/(.*)\.vue$/)[1] - return { - path: `/${name.toLowerCase()}`, - component: pages[path] // Lazy loaded - } -}) -``` - - diff --git a/skills/vite/references/features-hmr.md b/skills/vite/references/features-hmr.md deleted file mode 100644 index a87b9d6..0000000 --- a/skills/vite/references/features-hmr.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -name: features-hmr -description: Vite's Hot Module Replacement (HMR) client API ---- - -# HMR API - -The HMR API is exposed via `import.meta.hot`. Primarily for framework and tooling authors. - -## Conditional Guard - -Always guard HMR code for tree-shaking in production: - -```ts -if (import.meta.hot) { - // HMR code -} -``` - -## TypeScript Support - -Add to `tsconfig.json`: - -```json -{ - "compilerOptions": { - "types": ["vite/client"] - } -} -``` - -## Self-Accepting Module - -Module handles its own updates: - -```ts -export const count = 1 - -if (import.meta.hot) { - import.meta.hot.accept((newModule) => { - if (newModule) { - console.log('updated: count is now', newModule.count) - } - }) -} -``` - -## Accept Dependency Updates - -React to changes in dependencies without self-reload: - -```ts -import { foo } from './foo.js' - -foo() - -if (import.meta.hot) { - // Single dependency - import.meta.hot.accept('./foo.js', (newFoo) => { - newFoo?.foo() - }) - - // Multiple dependencies - import.meta.hot.accept( - ['./foo.js', './bar.js'], - ([newFooModule, newBarModule]) => { - // Handle updates - } - ) -} -``` - -## Cleanup on Update - -Clean up side effects before module is replaced: - -```ts -function setupSideEffect() { - const interval = setInterval(() => {}, 1000) - return interval -} - -const interval = setupSideEffect() - -if (import.meta.hot) { - import.meta.hot.dispose((data) => { - clearInterval(interval) - }) -} -``` - -## Prune Callback - -Called when module is no longer imported: - -```ts -if (import.meta.hot) { - import.meta.hot.prune((data) => { - // Cleanup when module is removed from page - }) -} -``` - -## Persistent Data - -Pass data between module instances: - -```ts -if (import.meta.hot) { - // Mutate properties, don't reassign data itself - import.meta.hot.data.count = (import.meta.hot.data.count || 0) + 1 -} -``` - -## Invalidate - -Force propagation to importers: - -```ts -if (import.meta.hot) { - import.meta.hot.accept((module) => { - if (cannotHandleUpdate(module)) { - import.meta.hot.invalidate() // Propagate to importers - } - }) -} -``` - -## HMR Events - -Listen to built-in events: - -```ts -if (import.meta.hot) { - import.meta.hot.on('vite:beforeUpdate', (payload) => { - console.log('Update incoming') - }) - - import.meta.hot.on('vite:afterUpdate', (payload) => { - console.log('Update applied') - }) - - import.meta.hot.on('vite:beforeFullReload', () => { - console.log('Full reload') - }) - - import.meta.hot.on('vite:error', (error) => { - console.error('HMR error', error) - }) - - import.meta.hot.on('vite:ws:connect', () => { - console.log('WebSocket connected') - }) - - import.meta.hot.on('vite:ws:disconnect', () => { - console.log('WebSocket disconnected') - }) -} -``` - -## Custom Events - -Send events to server: - -```ts -// Client -if (import.meta.hot) { - import.meta.hot.send('my:event', { msg: 'Hello from client' }) -} -``` - -Receive from server: - -```ts -// Client -if (import.meta.hot) { - import.meta.hot.on('my:response', (data) => { - console.log(data.msg) - }) -} -``` - -## TypeScript for Custom Events - -```ts -// events.d.ts -import 'vite/types/customEvent.d.ts' - -declare module 'vite/types/customEvent.d.ts' { - interface CustomEventMap { - 'my:event': { msg: string } - 'my:response': { msg: string } - } -} -``` - - diff --git a/skills/vite/references/features-workers.md b/skills/vite/references/features-workers.md deleted file mode 100644 index 0bd5efb..0000000 --- a/skills/vite/references/features-workers.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -name: features-workers -description: Web Worker support in Vite ---- - -# Web Workers - -## Constructor Syntax (Recommended) - -Standard Web Worker creation: - -```ts -const worker = new Worker(new URL('./worker.js', import.meta.url)) -``` - -Module worker: - -```ts -const worker = new Worker(new URL('./worker.js', import.meta.url), { - type: 'module' -}) -``` - -Shared Worker: - -```ts -const sharedWorker = new SharedWorker( - new URL('./shared-worker.js', import.meta.url) -) -``` - -**Note:** The `new URL()` must be used directly inside `new Worker()` for detection. - -## Query Suffix Syntax - -Import with `?worker` suffix: - -```ts -import MyWorker from './worker?worker' - -const worker = new MyWorker() -``` - -Shared worker: - -```ts -import MySharedWorker from './worker?sharedworker' - -const worker = new MySharedWorker() -``` - -### Inline Worker - -Inline as base64 string (no separate chunk): - -```ts -import MyWorker from './worker?worker&inline' - -const worker = new MyWorker() -``` - -### Worker URL Only - -Get URL instead of constructor: - -```ts -import workerUrl from './worker?worker&url' -``` - -## Worker Script - -Workers can use ESM `import` statements: - -```ts -// worker.js -import { heavyComputation } from './utils' - -self.onmessage = (e) => { - const result = heavyComputation(e.data) - self.postMessage(result) -} -``` - -## Worker Options - -Configure worker bundling: - -```ts -// vite.config.ts -export default defineConfig({ - worker: { - format: 'es', // or 'iife' - plugins: () => [/* worker-specific plugins */], - rollupOptions: { - // Rollup options for worker bundle - } - } -}) -``` - -## WebAssembly in Workers - -```ts -// worker.js -import init from './module.wasm?init' - -init().then((instance) => { - instance.exports.compute() -}) -``` - - diff --git a/skills/vite/references/rolldown-migration.md b/skills/vite/references/rolldown-migration.md new file mode 100644 index 0000000..28d6d76 --- /dev/null +++ b/skills/vite/references/rolldown-migration.md @@ -0,0 +1,157 @@ +--- +name: vite-rolldown +description: Vite 8 Rolldown bundler and Oxc transformer migration +--- + +# Rolldown Migration (Vite 8) + +Vite 8 replaces esbuild+Rollup with Rolldown, a unified Rust-based bundler. + +## What Changed + +| Before (Vite 7) | After (Vite 8) | +|-----------------|----------------| +| esbuild (dev transform) | Oxc Transformer | +| esbuild (dep pre-bundling) | Rolldown | +| Rollup (production build) | Rolldown | +| `rollupOptions` | `rolldownOptions` | +| `esbuild` option | `oxc` option | + +## Performance Impact + +- 10-30x faster than Rollup for production builds +- Matches esbuild's dev performance +- Unified behavior between dev and build + +## Config Migration + +### rollupOptions → rolldownOptions + +```ts +// Before (Vite 7) +export default defineConfig({ + build: { + rollupOptions: { + external: ['vue'], + output: { globals: { vue: 'Vue' } }, + }, + }, +}) + +// After (Vite 8) +export default defineConfig({ + build: { + rolldownOptions: { + external: ['vue'], + output: { globals: { vue: 'Vue' } }, + }, + }, +}) +``` + +### esbuild → oxc + +```ts +// Before (Vite 7) +export default defineConfig({ + esbuild: { + jsxFactory: 'h', + jsxFragment: 'Fragment', + }, +}) + +// After (Vite 8) +export default defineConfig({ + oxc: { + jsx: { + runtime: 'classic', + pragma: 'h', + pragmaFrag: 'Fragment', + }, + }, +}) +``` + +### JSX Configuration + +```ts +export default defineConfig({ + oxc: { + jsx: { + runtime: 'automatic', // or 'classic' + importSource: 'react', // for automatic runtime + }, + jsxInject: `import React from 'react'`, // auto-inject + }, +}) +``` + +### Custom Transform Targets + +```ts +export default defineConfig({ + oxc: { + include: ['**/*.ts', '**/*.tsx'], + exclude: ['node_modules/**'], + }, +}) +``` + +## Plugin Compatibility + +Most Vite plugins work unchanged. Rolldown supports Rollup's plugin API. + +If a plugin only works during build: + +```ts +{ + ...rollupPlugin(), + enforce: 'post', + apply: 'build', +} +``` + +## New Capabilities + +Rolldown unlocks features not possible before: + +- Full bundle mode (experimental) +- Module-level persistent cache +- More flexible chunk splitting +- Module Federation support + +## Gradual Migration + +For large projects, migrate via `rolldown-vite` first: + +```bash +# Step 1: Test with rolldown-vite +pnpm add -D rolldown-vite + +# Replace vite import in config +import { defineConfig } from 'rolldown-vite' + +# Step 2: Once stable, upgrade to Vite 8 +pnpm add -D vite@8 +``` + +## Overriding Vite in Frameworks + +When framework depends on older Vite: + +```json +{ + "pnpm": { + "overrides": { + "vite": "8.0.0" + } + } +} +``` + +