@10up/wp-vite-plugins 1.0.0-alpha.2 → 1.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,14 +7,34 @@ A focused set of Vite plugins that handle what WordPress projects actually need:
7
7
  ## Install
8
8
 
9
9
  ```sh
10
- npm install --save-dev @10up/wp-vite-plugins
10
+ npm install --save-dev @10up/wp-vite-plugins@alpha
11
11
  ```
12
12
 
13
- Requires Node ≥ 20.11 and Vite ^8 (Rolldown-powered).
13
+ 1.0 is in alpha, published under the `alpha` dist-tag. Requires Node `^22.18.0 || ^24.11.0 || >=26` and Vite 8 (Rolldown-powered).
14
+
15
+ ### Coming from `10up-toolkit`?
16
+
17
+ [Migrating from `10up-toolkit`](./docs/migrating-from-toolkit.md) walks a wp-scaffold project over to Vite+ and these plugins, and the [migration field notes](./docs/migration-field-notes.md) collect what real migrations ran into.
14
18
 
15
19
  ### Vite+ / Rolldown compatibility
16
20
 
17
- The plugins use only Rolldown-implemented plugin APIs, so they work unchanged with [Vite+](https://viteplus.dev) — `vp dev`, `vp build`, and `vp build --mode modules` read the same `vite.config.ts` and produce identical output to plain `vite` commands. The test suite runs under `vp test` (Vitest) as well.
21
+ The plugins use only Rolldown-implemented plugin APIs, so they work unchanged with [Vite+](https://viteplus.dev) — `vp dev` and `vp build` read the same `vite.config.ts` as plain `vite` commands and produce identical output. The test suite runs under `vp test` (Vitest) as well.
22
+
23
+ In a Vite+ project, pin `vite` to the Vite+ core with an npm override, as `vp migrate` does. Without it, npm installs a second, plain Vite next to Vite+, and `vp` refuses to run against it. The `vite` peer range is `^8.0.0 || ^1.0.0`: Vite 8, or `@voidzero-dev/vite-plus-core` 1.x under the `vite` alias (Vite never had a stable 1.x). Without the second half, npm marks the override invalid and refuses to upgrade a lockfile to a newer Vite+:
24
+
25
+ ```json
26
+ {
27
+ "devDependencies": {
28
+ "@10up/wp-vite-plugins": "^1.0.0-alpha.4",
29
+ "vite-plus": "^1.6.0"
30
+ },
31
+ "overrides": {
32
+ "vite": "npm:@voidzero-dev/vite-plus-core@^1.6.0"
33
+ }
34
+ }
35
+ ```
36
+
37
+ This repository builds, lints, formats and tests itself with Vite+ (`vp pack`, `vp check`, `vp test`).
18
38
 
19
39
  ## Quick start
20
40
 
@@ -40,19 +60,20 @@ That single call wires up:
40
60
  - **`wpBlocks`** — discovers every `block.json`, turns `file:` references into Rollup entries, copies `block.json` + sibling PHP into `dist/`, and emits `blocks-manifest.php` (WP 6.7+).
41
61
  - **`wpBlockStyles`** — emits each stylesheet under `blocksStylesDir` as its own CSS entry for selective PHP enqueueing.
42
62
  - **`wpCopyAssets`** — copies images / fonts / SVG from `copyAssetsDir` to `dist/`.
43
- - **`wpAdminPages`** — builds `@wordpress/boot` admin pages from `adminPagesDir` in the module pass (`content` / `route` entries, `loader.js` anchor, per-page `content.css`), and optionally generates the whole `@wordpress/build`-style PHP registration layer.
44
- - **`wpExternals`** — rewrites `@wordpress/*` imports against `window.wp.*` (or preserves them as ESM in module mode) and emits `<entry>.asset.php` dependency sidecars.
45
- - **`wpScriptDedupe`** _(auto, script mode)_ — gives every script-mode entry a private copy of the modules it imports, so no entry has to `import` a shared chunk (a classic script can't).
46
- - **`wpScriptIife`** _(auto)_ — wraps script-mode entries in an IIFE so they enqueue cleanly as classic `<script>` tags, defines `import.meta` away, and fails the build on output that isn't valid as a classic script.
63
+ - **`wpCss`** _(when `css` is set)_ — compiles CSS with Lightning CSS and gives every stylesheet the project's custom media, custom selectors and mixins without an `@import`. Relative `url()`s work in the build and on the dev server.
64
+ - **`wpAdminPages`** — builds `@wordpress/boot` admin pages from `adminPagesDir` as Script Modules (`content` / `route` entries, `loader.js` anchor, per-page `content.css`), and optionally generates the whole `@wordpress/build`-style PHP registration layer.
65
+ - **`wpExternals`** — rewrites `@wordpress/*` imports against `window.wp.*` (or preserves them as ESM for Script Modules) and emits `<entry>.asset.php` dependency sidecars.
66
+ - **`wpScriptDedupe`** _(auto, classic scripts)_ — gives every classic-script entry a private copy of the modules it imports, so no entry has to `import` a shared chunk (a classic script can't).
67
+ - **`wpScriptIife`** _(auto, classic scripts)_ — wraps classic-script entries in an IIFE so they enqueue cleanly as classic `<script>` tags, defines `import.meta` away, and fails the build on output that isn't valid as a classic script.
47
68
  - **`wpCleanCssChunks`** _(auto)_ — deletes the empty JS shims Vite leaves next to CSS-only entries.
69
+ - **`wpCssAssetInfo`** _(auto)_ — emits an `.asset.php` sidecar for CSS-only entries, which `wpExternals` can't write for them (there's no JS chunk to walk).
70
+ - **`wpEnvironments`** _(auto)_ — builds classic scripts and Script Modules as two Vite build environments into one `dist/`; see [below](#classic-scripts-and-script-modules).
71
+ - **`wpCssEntryGuard`** _(auto)_ — keeps CSS-only entries whose output is byte-identical (two empty stylesheets, say) from collapsing into one emitted file, which would 404 the other.
48
72
 
49
73
  ## Wrapper options
50
74
 
51
75
  ```ts
52
76
  wp({
53
- // Build mode for all sub-plugins. Default: 'script'.
54
- buildType: 'script', // or 'module'
55
-
56
77
  // Top-level shortcuts — pass a directory to enable the plugin.
57
78
  blocksDir: './includes/blocks',
58
79
  blocksStylesDir: './assets/css/blocks',
@@ -65,48 +86,71 @@ wp({
65
86
  copyAssets: { pattern: '**/*.{png,svg}' },
66
87
  adminPages: { php: {} }, // `php` turns on PHP generation; see docs/wp-admin-pages.md
67
88
  externals: {
68
- scriptModuleNamespaces: ['ignite-*'],
89
+ scriptModuleNamespaces: ['acme-*'],
69
90
  additionalExternals: { myLib: { global: 'MyLib', handle: 'my-lib' } },
91
+ moduleEntryMatchers: ['/assets/js/modules/'], // your own Script Module entries
70
92
  },
71
93
 
72
94
  // Helper opt-outs.
73
- scriptDedupe: false, // disable wpScriptDedupe (script mode only)
74
- iife: false, // disable wpScriptIife (script mode only)
95
+ scriptDedupe: false, // disable wpScriptDedupe (classic scripts only)
96
+ iife: false, // disable wpScriptIife (classic scripts only)
75
97
  cleanCssChunks: false, // disable wpCleanCssChunks (always on by default)
76
98
  });
77
99
  ```
78
100
 
79
101
  `externals` is always included unless you pass `externals: false`. The other four are included only when their directory option is provided (top-level or nested). See [docs/wp.md](./docs/wp.md) for the full inclusion and option-merging rules.
80
102
 
81
- ## Dual-pass builds (script + module)
103
+ ## Classic scripts and Script Modules
104
+
105
+ One `vp build` builds both. `wp()` declares two [Vite build environments](https://vite.dev/guide/api-environment) — `client` for classic scripts (`window.wp.*`, IIFEs) and `modules` for Script Modules (ESM, bare `@wordpress/*` specifiers for WordPress's import map) — and builds them into one `dist/`:
106
+
107
+ ```jsonc
108
+ {
109
+ "scripts": {
110
+ "build": "vp build", // both environments; dist/ emptied once
111
+ "watch": "vp build --watch", // each environment rebuilds on its own
112
+ "dev": "vp dev" // one dev server serves both; see below
113
+ }
114
+ }
115
+ ```
82
116
 
83
- For projects that ship both classic scripts and Script Modules, dispatch on Vite's `mode`:
117
+ Block assets go where their `block.json` field says (`viewScriptModule` → `modules`), admin pages are always Script Modules, and your own `build.rollupOptions.input` entries are classic scripts unless their path matches `externals.moduleEntryMatchers`:
84
118
 
85
119
  ```ts
86
- export default defineConfig(({ mode }) => ({
87
- plugins: [
88
- wp({
89
- buildType: mode === 'modules' ? 'module' : 'script',
90
- blocksDir: './includes/blocks',
91
- }),
92
- ],
93
- }));
120
+ wp({ externals: { moduleEntryMatchers: ['/assets/js/modules/'] } })
94
121
  ```
95
122
 
96
- Run the two passes separately: `vite build` (default script mode) and `vite build --mode modules`. The module pass is safe to run unconditionally — when no block declares a `scriptModule` / `viewScriptModule` (and no other module entries are configured), `wpBlocks` turns it into a no-op build instead of letting Rollup error on empty input.
123
+ A project with no Script Modules skips the `modules` environment. Because the build is one cache-aware command, `vp run --cache build` replays `dist/` when nothing changed. → [Details](./docs/wp.md#classic-scripts-and-script-modules)
97
124
 
98
- Or let the bundled CLI drive both passes, one command per task — it cleans `dist/` exactly once and keeps the passes from deleting each other's output:
125
+ ## Dev server
99
126
 
100
- ```jsonc
101
- {
102
- "scripts": {
103
- "build": "wp-vite build", // script pass, then module pass; fails fast
104
- "watch": "wp-vite watch" // both passes watched in a single process
105
- }
127
+ `vp dev` starts a real Vite dev server for a WordPress install — instant transforms, native ESM in the browser, HMR — and writes the one file PHP needs to know about it:
128
+
129
+ ```sh
130
+ vp dev
131
+ ```
132
+
133
+ ```
134
+ dist/.wp-vite-dev.json { "origin": "http://localhost:5173", "base": "/", "plugins": [] }
135
+ ```
136
+
137
+ Present means hot; absent means serve the built files. Alongside it, [`wpDevServer`](./docs/wp-dev-server.md) writes dev `.asset.php` sidecars for every entry a build writes one for — blocks, block styles, admin pages and your own `rollupOptions.input` entries — with the same keys a build writes plus `'source'`, mapping each asset back to the file the server serves. It also writes the `block.json` / `blocks-manifest.php` tree `register_block_type()` reads off disk, and keeps all of it in step as blocks are added and removed mid-session.
138
+
139
+ Wiring it into WordPress is one line, next to your other `dist/` requires:
140
+
141
+ ```php
142
+ if ( file_exists( __DIR__ . '/dist/dev-server.php' ) ) {
143
+ require_once __DIR__ . '/dist/dev-server.php';
106
144
  }
107
145
  ```
108
146
 
109
- → [Full documentation](./docs/cli.md)
147
+ `dev-server.php` is generated by every build (and by the dev server on start). Cold, it costs one `file_exists()`. Hot, it repoints every classic script (`script_loader_src` + a `type="module"` stamp), every Script Module (`script_module_loader_src`, WP 6.5+) and every stylesheet enqueued out of `dist/` at the running server, and enqueues Vite's HMR client. **No other PHP changes** — your registration code doesn't know the difference.
148
+
149
+ One server handles both kinds of entry: a classic entry gets the `window.wp.*` rewrite, a Script Module entry keeps its bare `@wordpress/*` specifiers for WordPress's runtime import map. The plugin is included by `wp()` by default, is `apply: 'serve'`, and costs a build nothing.
150
+
151
+ `@vitejs/plugin-react` gets React Fast Refresh for free — no extra config. When the hot file reports the plugin, `dev-server.php` attaches its preamble to the Vite client handle, ahead of every component module.
152
+
153
+ → [Full documentation](./docs/wp-dev-server.md)
110
154
 
111
155
  ## Using plugins individually
112
156
 
@@ -115,6 +159,7 @@ The wrapper is just sugar. Every plugin is exported on its own for finer control
115
159
  ```ts
116
160
  import { defineConfig } from 'vite';
117
161
  import {
162
+ wpEnvironments,
118
163
  wpBlocks,
119
164
  wpBlockStyles,
120
165
  wpCopyAssets,
@@ -127,15 +172,21 @@ import {
127
172
 
128
173
  export default defineConfig({
129
174
  plugins: [
130
- wpBlocks({ blocksDir: './includes/blocks', buildType: 'script' }),
175
+ // The `client` + `modules` build environments. Without it only `client`
176
+ // exists, and Script Module entries never build.
177
+ wpEnvironments(),
178
+ wpBlocks({ blocksDir: './includes/blocks' }),
131
179
  wpBlockStyles({ blocksStylesDir: './assets/css/blocks' }),
132
180
  wpCopyAssets({ copyAssetsDir: './assets' }),
133
- // Module pass only — a no-op with buildType: 'script'. Composed by hand,
134
- // it needs a matching `wpBuildAssetMatchers` entry on wpExternals.
135
- wpAdminPages({ adminPagesDir: './assets/js/admin-pages', buildType: 'module' }),
136
- wpExternals({ buildType: 'script' }),
137
- // Script mode only, and in this order: dedupe partitions the graph, the
138
- // IIFE wrapper vets the result.
181
+ // Composed by hand, it needs a matching `wpBuildAssetMatchers` entry on
182
+ // wpExternals.
183
+ wpAdminPages({ adminPagesDir: './assets/js/admin-pages' }),
184
+ ...wpExternals({ wpBuildAssetMatchers: ['/assets/js/admin-pages/'] }),
185
+ // Classic scripts only (each applies to `client` alone), in this order:
186
+ // dedupe partitions the graph, the IIFE wrapper vets the result. Composed by hand, wpScriptIife gets no
187
+ // `globals` map, so Rolldown's runtime `require()` of an external has
188
+ // nothing to resolve against — pass wpExternals' `globalsSink` through
189
+ // both if any dependency reaches an external from CommonJS.
139
190
  wpScriptDedupe(),
140
191
  wpScriptIife(),
141
192
  wpCleanCssChunks(),
@@ -147,13 +198,19 @@ export default defineConfig({
147
198
 
148
199
  Two runnable consumer projects live under [`examples/`](./examples/README.md), each with a WordPress Playground blueprint for end-to-end verification:
149
200
 
150
- - [`examples/minimal-block-plugin`](./examples/minimal-block-plugin) — one plugin, one block, single-pass build.
151
- - [`examples/scaffold-monorepo`](./examples/scaffold-monorepo) — a full [10up/wp-scaffold](https://github.com/10up/wp-scaffold)-style monorepo (classic theme, block theme, mu-plugin) building through npm workspaces, including a dual-pass Script Module build.
201
+ - [`examples/minimal-block-plugin`](./examples/minimal-block-plugin) — one plugin, one block.
202
+ - [`examples/scaffold-monorepo`](./examples/scaffold-monorepo) — a full [10up/wp-scaffold](https://github.com/10up/wp-scaffold)-style monorepo (classic theme, block theme, mu-plugin) building through npm workspaces, including Interactivity API Script Modules and `@wordpress/boot` admin pages.
152
203
 
153
204
  ## Plugins
154
205
 
155
206
  The sections below are the quick reference. Each plugin also has an in-depth page under [`docs/`](./docs/README.md) covering internals, output formats, and caveats.
156
207
 
208
+ ### `wpDevServer(options)`
209
+
210
+ → [Full documentation](./docs/wp-dev-server.md)
211
+
212
+ Serve-only (`apply: 'serve'`), included by `wp()` by default. Writes `dist/.wp-vite-dev.json` on `listening` and deletes it on exit; writes dev `.asset.php` sidecars and the blocks metadata tree; keeps Script Module entries' bare specifiers intact for WordPress's import map; refreshes everything on watcher events. Its build-side twin `wpDevServerPhp` emits `dist/dev-server.php`, the PHP bridge, into every build. Disable both with `wp({ devServer: false })`.
213
+
157
214
  ### `wpBlocks(options)`
158
215
 
159
216
  → [Full documentation](./docs/wp-blocks.md)
@@ -170,7 +227,6 @@ Scans `blocksDir` for `block.json` files. For each one:
170
227
  | Option | Type | Default | Notes |
171
228
  | --- | --- | --- | --- |
172
229
  | `blocksDir` | `string` | (required) | Root directory containing `block.json` files. |
173
- | `buildType` | `'script' \| 'module'` | `'script'` | Which `block.json` fields to discover as entries. |
174
230
  | `emitManifest` | `boolean` | `true` | Emit `blocks-manifest.php`. |
175
231
  | `skip` | `string[]` | `[]` | Block directory names (relative to `blocksDir`) to skip entirely. |
176
232
 
@@ -193,25 +249,27 @@ The sidecar comes in two shapes, chosen per entry, because WordPress core and bo
193
249
 
194
250
  For every entry, `version` now hashes the chunk code *and* its extracted CSS, and dependencies are unioned across the entry chunk and every chunk it imports, so shared chunks don't lose deps. See the [sidecar reference](./docs/wp-externals.md#the-assetphp-sidecar) and its [breaking-change note](./docs/wp-externals.md#breaking-change-pre-10).
195
251
 
196
- For non-`@wordpress/*` packages, a hardcoded vendor map covers `react`, `react-dom`, `jquery`, `lodash`, `moment`. Pass `additionalExternals` to extend or replace that map.
252
+ For non-`@wordpress/*` packages, a hardcoded vendor map covers `react`, `react-dom`, `jquery`, `lodash`, `lodash-es`, `moment`. Pass `additionalExternals` to extend or replace that map.
197
253
 
198
254
  **Options**
199
255
 
200
256
  | Option | Type | Default | Notes |
201
257
  | --- | --- | --- | --- |
202
258
  | `projectRoot` | `string` | `process.cwd()` | Resolution root for `@wordpress/*` package metadata. |
203
- | `buildType` | `'script' \| 'module'` | `'script'` | Controls import rewriting strategy. |
204
259
  | `externalNamespaces` | `Record<string, ExternalNamespace>` | `{}` | Add classic-script externals for namespaces like `@woo/*`. |
205
260
  | `additionalExternals` | `Record<string, { global, handle }>` | (vendor map) | Override the non-scoped vendor externals. |
206
- | `moduleEntryMatchers` | `string[]` | `[]` | File path substrings that should be treated as module-mode regardless of `buildType`. |
261
+ | `moduleEntryMatchers` | `string[]` | `[]` | Path substrings of Script Module entries: built in `modules` (via `wp()`), served in module mode by the dev server. |
207
262
  | `wpBuildAssetMatchers` | `string[]` | `[]` | Entry source-path substrings whose `.asset.php` uses the `@wordpress/build` shape. |
208
263
  | `scriptModuleNamespaces` | `string[]` | `[]` | Plugin-local Script Module namespaces (exact or `prefix-*` glob). |
264
+ | `globalsSink` | `Map<string, string>` | — | Out-param, filled with specifier → window global so `wpScriptIife` can shim `require()` for CJS deps. Wired automatically by `wp()`. |
265
+ | `bundle` | `string[]` | `[]` | Bare package names to bundle instead of externalizing, on top of the default (`@wordpress/icons`). |
266
+ | `uninstalledWordPressPackages` | `'bundle' \| 'external'` | `'bundle'` | `'external'` assumes WordPress provides a `@wordpress/*` package that isn't installed. |
209
267
 
210
268
  ### `wpAdminPages(options)`
211
269
 
212
270
  → [Full documentation](./docs/wp-admin-pages.md)
213
271
 
214
- Builds [`@wordpress/boot`](https://github.com/WordPress/gutenberg/tree/trunk/packages/boot)-powered admin pages (WP 6.9+ Script Module admin screens) as part of the **module pass**, replacing a separate esbuild pipeline. Every immediate subdirectory of `adminPagesDir` with a `content` entry is a page:
272
+ Builds [`@wordpress/boot`](https://github.com/WordPress/gutenberg/tree/trunk/packages/boot)-powered admin pages (WordPress 7.0+, or the Gutenberg plugin) as Script Modules, in the same `vp build`, replacing a separate esbuild pipeline. Every immediate subdirectory of `adminPagesDir` with a `content` entry is a page:
215
273
 
216
274
  ```
217
275
  dist/modules/<page>/
@@ -226,16 +284,15 @@ dist/modules/<page>/
226
284
 
227
285
  Entries containing JSX must use `.jsx` / `.tsx` — Vite doesn't parse JSX out of `.js`.
228
286
 
229
- Pass `php: {}` and the plugin also generates the `@wordpress/build`-style PHP layer next to the modules — `build.php`, `constants.php`, `pages.php`, `pages/<slug>/page{,-wp-admin}.php`, `routes.php`, `routes/registry.php` — so a consuming plugin needs no hand-written PHP beyond `require_once __DIR__ . '/dist/build.php';`. Per-page `page.json` covers titles, menu registration, init modules, modes and REST preload. See [the reference](./docs/wp-admin-pages.md#generated-php); `AbstractBootAdminPage` stays a supported alternative.
287
+ Pass `php: {}` and the plugin also emits the `@wordpress/build`-style PHP layer next to the modules — `build.php` (the pages as data) and the `wp-boot/` classes it loads (from [`10up/wp-boot`](../wp-boot)) — so a consuming plugin needs no hand-written PHP beyond `require_once __DIR__ . '/dist/build.php';`. Per-page `page.json` covers titles, menu registration, init modules, modes and REST preload. See [the reference](./docs/wp-admin-pages.md#generated-php); `AbstractBootAdminPage` stays a supported alternative.
230
288
 
231
289
  **Options**
232
290
 
233
291
  | Option | Type | Default | Notes |
234
292
  | --- | --- | --- | --- |
235
293
  | `adminPagesDir` | `string` | (required) | Directory whose immediate subdirectories are pages. |
236
- | `buildType` | `'script' \| 'module'` | `'script'` | No-op in script mode; pages are Script Modules. |
237
294
  | `php` | `WpAdminPagesPhpOptions` | (off) | Presence enables PHP generation (`prefix`, `handlePrefix`, `baseUrl`, `textdomain`). |
238
- | `projectRoot` | `string` | Vite's `root` | `package.json` supplying the generated version / prefix defaults. |
295
+ | `projectRoot` | `string` | Vite's `root` | Root whose `package.json` supplies the generated PHP's prefix defaults. |
239
296
 
240
297
  Via `wp({ adminPagesDir })` the pages directory is also fed to `wpExternals`' `wpBuildAssetMatchers` so page sidecars get the `@wordpress/build` shape; set that option yourself when composing the plugins by hand.
241
298
 
@@ -250,6 +307,7 @@ Every stylesheet under `blocksStylesDir` becomes a dedicated CSS entry under `di
250
307
  | Option | Type | Default | Notes |
251
308
  | --- | --- | --- | --- |
252
309
  | `blocksStylesDir` | `string` | (required) | Directory of per-block stylesheets. |
310
+ | `outputPrefix` | `string` | `'autoenqueue'` | Directory under `dist/` the stylesheets land in. `'blocks/autoenqueue'` keeps a `10up-toolkit` project's paths. |
253
311
 
254
312
  ### `wpCopyAssets(options)`
255
313
 
@@ -263,19 +321,37 @@ Copies static assets (images, fonts, SVG) from `copyAssetsDir` to `dist/`, prese
263
321
  | --- | --- | --- | --- |
264
322
  | `copyAssetsDir` | `string` | (required) | Source directory. |
265
323
  | `pattern` | `string` | `**/*.{jpg,jpeg,png,gif,webp,avif,ico,svg,eot,ttf,woff,woff2,otf}` | Glob, relative to `copyAssetsDir`. |
266
- | `buildType` | `'script' \| 'module'` | `'script'` | Only runs in script mode (to avoid double-emission on dual-pass builds). |
324
+
325
+ ### `wpCss(options?)`
326
+
327
+ → [Full documentation](./docs/wp-css.md)
328
+
329
+ Compiles every stylesheet with Lightning CSS, in place of the PostCSS stack `10up-toolkit` ran. The `@custom-media`, `@custom-selector` and `@define-mixin` definitions in the `globals` files reach every stylesheet without an `@import`, and local `@import`s are inlined. Relative `url()`s are kept relative to the built file, and on the dev server they point at the copied file's source. Use it through `wp({ css })`, which also passes `copyAssetsDir`.
330
+
331
+ **Options**
332
+
333
+ | Option | Type | Default | Notes |
334
+ | --- | --- | --- | --- |
335
+ | `globals` | `string[]` | `[]` | Globs of the globals files, relative to the Vite root. |
336
+ | `mixins` | `MixinMap \| () => MixinMap` | none | Mixins defined in JS: name → declarations. |
337
+ | `browserslist` | `string \| string[]` | the project's config | The compile targets. |
338
+ | `assetsDir` | `string` | `wp()`'s `copyAssetsDir` | Source of the files copied into `dist/`, for dev-server urls. |
267
339
 
268
340
  ### `wpScriptDedupe()`
269
341
 
270
342
  → [Full documentation](./docs/wp-script-dedupe.md)
271
343
 
272
- Duplicates every statically shared module into each script-mode entry (webpack's behavior), so Rolldown never leaves an entry importing a shared chunk — invalid in a classic `<script>`. Also inlines Rolldown's CJS interop runtime and wpExternals' CJS global shims, which are injected too late to partition. Script mode + `vite build` only. No options.
344
+ Duplicates every statically shared module into each classic-script entry (webpack's behavior), so Rolldown never leaves an entry importing a shared chunk — invalid in a classic `<script>`. Also inlines Rolldown's CJS interop runtime and wpExternals' CJS global shims, which are injected too late to partition. `client` environment + build only. No options.
273
345
 
274
- ### `wpScriptIife()`
346
+ ### `wpScriptIife(options?)`
275
347
 
276
348
  → [Full documentation](./docs/wp-script-iife.md)
277
349
 
278
- Wraps each script-mode entry chunk in an IIFE in `writeBundle`. Avoids global-scope leaks when WP enqueues bundles as classic `<script>` tags. Injects the `import.meta.url` / `import.meta.resolve` `define` script mode needs, and fails the build if a chunk still holds a live `import`/`export` statement or an `import.meta` reference. No options.
350
+ Wraps each classic-script entry chunk in an IIFE in `writeBundle`. Avoids global-scope leaks when WP enqueues bundles as classic `<script>` tags. Injects the `import.meta.url` / `import.meta.resolve` `define` classic scripts need, and fails the build — before any chunk is wrapped — if a chunk still holds a live `import`/`export` statement or an `import.meta` reference.
351
+
352
+ | Option | Type | Default | Notes |
353
+ | --- | --- | --- | --- |
354
+ | `globals` | `Map<string, string>` | `new Map()` | Specifier → window global, used to shim `require()` for CJS deps Rolldown resolves at runtime. Wired automatically by `wp()`. |
279
355
 
280
356
  ### `wpCleanCssChunks()`
281
357