@vizejs/vite-plugin 0.331.0 → 0.333.0

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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as VizeVueVersion, c as VizeInspectorLintPlanRequest, d as LoadConfigOptions, f as ResolvedVizeConfig, i as VizeOptions, l as VizeInspectorOptions, m as VizeConfig, n as MacroArtifact, o as VizeVueFeatures, p as UserConfigExport, r as VizeCompatibilityOptions, s as VizeInspectorLintPlanProvider, t as CompiledModule, u as ConfigEnv } from "./types-DR5IFFd7.mjs";
1
+ import { a as VizeVueVersion, c as VizeInspectorLintPlanRequest, d as LoadConfigOptions, f as ResolvedVizeConfig, i as VizeOptions, l as VizeInspectorOptions, m as VizeConfig, n as MacroArtifact, o as VizeVueFeatures, p as UserConfigExport, r as VizeCompatibilityOptions, s as VizeInspectorLintPlanProvider, t as CompiledModule, u as ConfigEnv } from "./types-T_Fu8G5I.mjs";
2
2
  import { Plugin } from "vite";
3
3
 
4
4
  //#region src/virtual.d.ts
package/dist/index.mjs CHANGED
@@ -341,9 +341,20 @@ function toNativeCssAliasRule(rule) {
341
341
  }
342
342
  //#endregion
343
343
  //#region src/utils/filter.ts
344
+ /**
345
+ * Defaults the filter falls back to, and what the `vite:vue` shim reports
346
+ * through `api.include` / `api.exclude` when neither is configured (#3227).
347
+ *
348
+ * `DEFAULT_INCLUDE_PATTERN` is `@vitejs/plugin-vue`'s own default.
349
+ * `DEFAULT_EXCLUDE_PATTERN` has no upstream counterpart — plugin-vue leaves
350
+ * `exclude` undefined — so the shim reports the pattern Vize actually filters
351
+ * on rather than an upstream-shaped `undefined` it does not honor.
352
+ */
353
+ const DEFAULT_INCLUDE_PATTERN = /\.vue$/;
354
+ const DEFAULT_EXCLUDE_PATTERN = /node_modules/;
344
355
  function createFilter(include, exclude) {
345
- const includePatterns = include ? Array.isArray(include) ? include : [include] : [/\.vue$/];
346
- const excludePatterns = exclude ? Array.isArray(exclude) ? exclude : [exclude] : [/node_modules/];
356
+ const includePatterns = include ? Array.isArray(include) ? include : [include] : [DEFAULT_INCLUDE_PATTERN];
357
+ const excludePatterns = exclude ? Array.isArray(exclude) ? exclude : [exclude] : [DEFAULT_EXCLUDE_PATTERN];
347
358
  return (id) => {
348
359
  const matchInclude = includePatterns.some((pattern) => matchesFilterPattern(pattern, id));
349
360
  const matchExclude = excludePatterns.some((pattern) => matchesFilterPattern(pattern, id));
@@ -2425,6 +2436,114 @@ function shouldLoadCompiledVueSfcPath(state, realPath, hasNuxtComponentQuery = f
2425
2436
  return true;
2426
2437
  }
2427
2438
  //#endregion
2439
+ //#region src/plugin/ssr-modules.ts
2440
+ /**
2441
+ * Point a compiled SSR module at the `vue/server-renderer` subpath.
2442
+ *
2443
+ * The compiler emits `@vue/server-renderer`, which is not a dependency every
2444
+ * app declares; the subpath re-export always resolves alongside `vue` itself.
2445
+ */
2446
+ function normalizeVueServerRendererImport(code) {
2447
+ return code.replace(/\bfrom\s+(['"])@vue\/server-renderer\1/g, "from \"vue/server-renderer\"");
2448
+ }
2449
+ /**
2450
+ * Marks a module whose registration has already been appended.
2451
+ *
2452
+ * Idempotency cannot key on the helper identifiers: an SFC is free to declare
2453
+ * `__vize_useSSRContext` itself, and skipping registration for it would cost it
2454
+ * its initial stylesheet.
2455
+ */
2456
+ const REGISTRATION_MARKER = "/* @vize-ssr-modules-registered */";
2457
+ /**
2458
+ * Matches the `_sfc_main` component declaration the emitted module carries.
2459
+ *
2460
+ * A bare `\b_sfc_main\b` also matches the identifier inside a string literal or
2461
+ * a comment, and wrapping a component that was never declared is a
2462
+ * `ReferenceError` at render time.
2463
+ */
2464
+ const SFC_MAIN_DECLARATION = /\b(?:const|let|var)\s+_sfc_main\s*=/;
2465
+ /**
2466
+ * Register an SFC in `ssrContext.modules` during SSR, the way
2467
+ * `@vitejs/plugin-vue` does.
2468
+ *
2469
+ * After rendering, `vue-bundle-renderer` intersects `ssrContext.modules` with
2470
+ * the client manifest to decide which stylesheets belong in the document head.
2471
+ * A component that never registers itself contributes no `<link>`, so the
2472
+ * server-rendered markup arrives unstyled and only gains its styles once the
2473
+ * route chunk loads on the client — a flash of unstyled content that never
2474
+ * recovers when JavaScript is disabled (#3868).
2475
+ *
2476
+ * The key must be the module's path relative to the Vite root with POSIX
2477
+ * separators, because that is what the client manifest is keyed on.
2478
+ */
2479
+ function ssrModuleRegistrationCode(filePath, root, helpers = {}) {
2480
+ const moduleId = JSON.stringify(toManifestModuleId(filePath, root));
2481
+ const useSSRContext = helpers.useSSRContext ?? "__vize_useSSRContext";
2482
+ const sfcSetup = helpers.sfcSetup ?? "__vize_sfc_setup";
2483
+ return {
2484
+ prologue: `${REGISTRATION_MARKER}\nimport { useSSRContext as ${useSSRContext} } from "vue";`,
2485
+ epilogue: [
2486
+ `const ${sfcSetup} = _sfc_main.setup;`,
2487
+ `_sfc_main.setup = (props, ctx) => {`,
2488
+ ` const ssrContext = ${useSSRContext}();`,
2489
+ ` (ssrContext.modules || (ssrContext.modules = new Set())).add(${moduleId});`,
2490
+ ` return ${sfcSetup} ? ${sfcSetup}(props, ctx) : undefined;`,
2491
+ `};`
2492
+ ].join("\n")
2493
+ };
2494
+ }
2495
+ /**
2496
+ * The client-manifest key for `filePath`: relative to `root`, POSIX separators.
2497
+ *
2498
+ * A path outside the root keeps its absolute form rather than becoming a `../`
2499
+ * chain, matching how Vite keys modules it cannot root-relativize. Only a real
2500
+ * parent-directory step counts as outside: a filename that merely begins with
2501
+ * `..` still lives in the root and is keyed relative to it.
2502
+ */
2503
+ function toManifestModuleId(filePath, root) {
2504
+ const relative = path.relative(root, filePath).replace(/\\/g, "/");
2505
+ if (!relative || relative === ".." || relative.startsWith("../") || path.isAbsolute(relative)) return filePath.replace(/\\/g, "/");
2506
+ return relative;
2507
+ }
2508
+ /**
2509
+ * Wrap an emitted module with the registration.
2510
+ *
2511
+ * The wrapper is appended, so it closes over whatever `setup` the emitter's own
2512
+ * rewrites left in place, but its `import` is *prepended*. A trailing `import`
2513
+ * is legal ESM, yet it makes the module's last import statement its last line,
2514
+ * and Nuxt's auto-import injection then inserts nothing — a component relying on
2515
+ * an auto-imported composable loses that binding and throws `ReferenceError` at
2516
+ * render time (#3868). Leading the module with the import keeps the import
2517
+ * section where every downstream transform expects to find it.
2518
+ *
2519
+ * `useSSRContext()` throws outside a render, so this is a no-op unless `isSsr`.
2520
+ * Modules without an `_sfc_main` declaration — a render-function-only output, or
2521
+ * a boundary placeholder — have no component object to wrap and are returned
2522
+ * untouched.
2523
+ */
2524
+ function appendSsrModuleRegistration(code, filePath, root, isSsr) {
2525
+ if (!isSsr || !SFC_MAIN_DECLARATION.test(code)) return code;
2526
+ if (code.includes(REGISTRATION_MARKER)) return code;
2527
+ const { prologue, epilogue } = ssrModuleRegistrationCode(filePath, root, {
2528
+ useSSRContext: freeIdentifier("__vize_useSSRContext", code),
2529
+ sfcSetup: freeIdentifier("__vize_sfc_setup", code)
2530
+ });
2531
+ return `${prologue}\n${code}\n${epilogue}`;
2532
+ }
2533
+ /**
2534
+ * `base`, or `base` plus the smallest numeric suffix the module does not use.
2535
+ *
2536
+ * Re-declaring an identifier the SFC already bound is a `SyntaxError`, which
2537
+ * would take down the whole module rather than just its stylesheet.
2538
+ */
2539
+ function freeIdentifier(base, code) {
2540
+ if (!new RegExp(`\\b${base}\\b`).test(code)) return base;
2541
+ for (let suffix = 2;; suffix++) {
2542
+ const candidate = `${base}${suffix}`;
2543
+ if (!new RegExp(`\\b${candidate}\\b`).test(code)) return candidate;
2544
+ }
2545
+ }
2546
+ //#endregion
2428
2547
  //#region src/plugin/vite-transform.ts
2429
2548
  function createVirtualTypeScriptTransformer(viteApi) {
2430
2549
  return async (code, id) => {
@@ -2515,9 +2634,6 @@ function getBoundaryPlaceholderCode(realPath, ssr) {
2515
2634
  if (!ssr && boundaryKind === "server") return SERVER_PLACEHOLDER_CODE;
2516
2635
  return null;
2517
2636
  }
2518
- function normalizeVueServerRendererImport(code) {
2519
- return code.replace(/\bfrom\s+(['"])@vue\/server-renderer\1/g, "from \"vue/server-renderer\"");
2520
- }
2521
2637
  function findMacroArtifactModule(state, realPath, ssr, kind) {
2522
2638
  const cache = getEnvironmentCache(state, ssr);
2523
2639
  const extractCss = shouldExtractCssForRequest(state, ssr);
@@ -2578,6 +2694,7 @@ function loadCompiledSfcModule(state, realPath, isSsr, currentBase, loadOptions)
2578
2694
  rewritten.edit(rewriteDynamicTemplateImports(rewritten.code, state.dynamicImportAliasRules));
2579
2695
  rewritten.edit(rewriteStaticAssetUrls(rewritten.code, state.dynamicImportAliasRules));
2580
2696
  rewritten.edit(rewriteImportMetaGlobBase(rewritten.code, realPath, state.root));
2697
+ rewritten.edit(appendSsrModuleRegistration(rewritten.code, realPath, state.root, isSsr));
2581
2698
  return {
2582
2699
  code: rewritten.code,
2583
2700
  map: rewritten.map
@@ -2938,7 +3055,16 @@ async function handleHotUpdateEnvironmentHook(state, environment, options) {
2938
3055
  }
2939
3056
  //#endregion
2940
3057
  //#region src/plugin/compat.ts
2941
- function createVueCompatPlugin(state) {
3058
+ /**
3059
+ * The `vite:vue` shim a host framework probes for a Vue plugin.
3060
+ *
3061
+ * `api.include` / `api.exclude` report the patterns behind `state.filter`, and
3062
+ * assigning them rewrites the plugin's own options — the only window where that
3063
+ * is meaningful is before `configResolved` builds the filter, so a later write
3064
+ * throws rather than silently doing nothing (#3227). Upstream guards the same
3065
+ * way, keyed on its `options` hook instead.
3066
+ */
3067
+ function createVueCompatPlugin(state, options) {
2942
3068
  let compilerSfc = null;
2943
3069
  const loadCompilerSfc = () => {
2944
3070
  if (!compilerSfc) try {
@@ -2951,16 +3077,36 @@ function createVueCompatPlugin(state) {
2951
3077
  }
2952
3078
  return compilerSfc;
2953
3079
  };
3080
+ const configured = () => state.initialized ? state.mergedOptions : options;
3081
+ const assertUnresolved = (name) => {
3082
+ if (state.initialized) throw new Error(`${name} cannot be updated after the filter is resolved`);
3083
+ };
2954
3084
  return {
2955
3085
  name: "vite:vue",
2956
- api: { get options() {
2957
- return {
2958
- compiler: loadCompilerSfc(),
2959
- isProduction: state.isProduction ?? false,
2960
- root: state.root ?? process.cwd(),
2961
- template: {}
2962
- };
2963
- } }
3086
+ api: {
3087
+ get options() {
3088
+ return {
3089
+ compiler: loadCompilerSfc(),
3090
+ isProduction: state.isProduction ?? false,
3091
+ root: state.root ?? process.cwd(),
3092
+ template: {}
3093
+ };
3094
+ },
3095
+ get include() {
3096
+ return configured().include ?? DEFAULT_INCLUDE_PATTERN;
3097
+ },
3098
+ set include(value) {
3099
+ assertUnresolved("include");
3100
+ options.include = value;
3101
+ },
3102
+ get exclude() {
3103
+ return configured().exclude ?? DEFAULT_EXCLUDE_PATTERN;
3104
+ },
3105
+ set exclude(value) {
3106
+ assertUnresolved("exclude");
3107
+ options.exclude = value;
3108
+ }
3109
+ }
2964
3110
  };
2965
3111
  }
2966
3112
  function normalizeVirtualStyleId(id) {
@@ -3584,11 +3730,18 @@ function parseDefine(value) {
3584
3730
  return value;
3585
3731
  }
3586
3732
  }
3587
- /** Resolve Vue runtime defines with plugin-vue's precedence and defaults. */
3588
- function resolveVueFeatureDefines(features, define, command) {
3733
+ /**
3734
+ * Resolve Vue runtime defines with plugin-vue's precedence and defaults.
3735
+ *
3736
+ * `__VUE_PROD_DEVTOOLS__` used to be `command === "serve"`, which left no way to
3737
+ * enable devtools for a production build (#3227). It now follows plugin-vue's
3738
+ * OR semantics, and defaults to `false` in dev as upstream does: a development
3739
+ * build enables devtools through Vue's own `__DEV__`, not through this flag.
3740
+ */
3741
+ function resolveVueFeatureDefines(features, define) {
3589
3742
  return {
3590
3743
  __VUE_OPTIONS_API__: features?.optionsAPI ?? parseDefine(define?.__VUE_OPTIONS_API__) ?? true,
3591
- __VUE_PROD_DEVTOOLS__: command === "serve",
3744
+ __VUE_PROD_DEVTOOLS__: (features?.prodDevtools || parseDefine(define?.__VUE_PROD_DEVTOOLS__)) ?? false,
3592
3745
  __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: (features?.prodHydrationMismatchDetails || parseDefine(define?.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__)) ?? false
3593
3746
  };
3594
3747
  }
@@ -3643,14 +3796,14 @@ function vize(options = {}) {
3643
3796
  logger: createLogger(options.debug ?? false)
3644
3797
  };
3645
3798
  return [
3646
- createVueCompatPlugin(state),
3799
+ createVueCompatPlugin(state, options),
3647
3800
  {
3648
3801
  name: "vite-plugin-vize",
3649
3802
  enforce: "pre",
3650
- config(userConfig, env) {
3803
+ config(userConfig) {
3651
3804
  patchCssModuleGenerateScopedName(userConfig);
3652
3805
  return {
3653
- define: resolveVueFeatureDefines(options.features, userConfig.define, env.command),
3806
+ define: resolveVueFeatureDefines(options.features, userConfig.define),
3654
3807
  optimizeDeps: { exclude: ["virtual:vize-styles"] }
3655
3808
  };
3656
3809
  },
@@ -1,4 +1,4 @@
1
- import { f as ResolvedVizeConfig } from "../types-DR5IFFd7.mjs";
1
+ import { f as ResolvedVizeConfig } from "../types-T_Fu8G5I.mjs";
2
2
  import { ResolvedConfig } from "vite";
3
3
 
4
4
  //#region src/internal/config-bridge.d.ts
@@ -730,6 +730,11 @@ interface VizeVueFeatures {
730
730
  * @default true
731
731
  */
732
732
  optionsAPI?: boolean;
733
+ /**
734
+ * Enable Vue devtools support in production bundles.
735
+ * @default false
736
+ */
737
+ prodDevtools?: boolean;
733
738
  /**
734
739
  * Enable detailed hydration mismatch errors in production bundles.
735
740
  * @default false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizejs/vite-plugin",
3
- "version": "0.331.0",
3
+ "version": "0.333.0",
4
4
  "description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
5
5
  "keywords": [
6
6
  "compiler",
@@ -45,10 +45,10 @@
45
45
  "access": "public"
46
46
  },
47
47
  "dependencies": {
48
- "@vizejs/native": "0.331.0",
48
+ "@vizejs/native": "0.333.0",
49
49
  "oxc-parser": "0.133.0",
50
50
  "tinyglobby": "0.2.16",
51
- "vize": "0.331.0"
51
+ "vize": "0.333.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "25.9.2",