Skip to content

feat: extend defineConfig to support lazy plugin loading via factory functions#1215

Open
fengmk2 wants to merge 1 commit intomainfrom
how-to-use-lazy-field
Open

feat: extend defineConfig to support lazy plugin loading via factory functions#1215
fengmk2 wants to merge 1 commit intomainfrom
how-to-use-lazy-field

Conversation

@fengmk2
Copy link
Copy Markdown
Member

@fengmk2 fengmk2 commented Mar 30, 2026

Summary

Extend defineConfig so the plugins field accepts factory functions in addition to the standard PluginOption[] array. The factory is only called for vite commands (dev, build, test, preview) and skipped for non-vite commands (lint, fmt, check, etc.), avoiding unnecessary plugin loading overhead.

Refs vitejs/vite#22085

Usage

import { defineConfig } from 'vite-plus'

// sync factory — plugin construction deferred
export default defineConfig({
  plugins: () => [fooPlugin()],
})

// async factory — both import and construction deferred
export default defineConfig({
  plugins: async () => {
    const { default: heavyPlugin } = await import('vite-plugin-heavy');
    return [heavyPlugin()];
  },
})

// plain array — still works as before
export default defineConfig({
  plugins: [fooPlugin()],
})

How it works

  • bin.ts sets VP_COMMAND env var from the CLI command argument
  • defineConfig checks if plugins is a function; if so, only calls it when VP_COMMAND is a vite command
  • For async factories, the returned Promise is wrapped in an array — Vite's asyncFlatten resolves it during plugin pipeline

Test plan

  • Unit tests pass: 31 tests covering factory patterns, PluginOption compatibility, and vitest plugin hooks
  • Snap tests pass: sync build, async build, and lint-skips-plugins
  • vp check passes (format + lint)

🤖 Generated with Claude Code


Note

Medium Risk
Changes how vite.config.ts plugins are resolved based on the running vp command, which could affect plugin execution order/availability across build/test/dev vs lint/fmt/check paths. Adds VP_COMMAND env injection in both JS and Rust CLI flows, so regressions would show up as incorrect plugin loading in synthesized commands (e.g. vp run).

Overview
Adds lazy plugin loading to vite-plus defineConfig by allowing plugins to be a sync/async factory function; the factory is executed only for Vite commands (dev/build/test/preview) and skipped for non-Vite commands to reduce config-load overhead.

The CLI now sets/injects VP_COMMAND (JS bin.ts, and Rust resolver for synthesized subcommands) so factory decisions remain correct even when commands are executed via vp run. Includes expanded unit coverage, new snapshot fixtures validating sync/async factories (including Vitest configureVitest) and that plugins are not loaded during vp lint, plus a small Windows snapshot-stabilization tweak and updated troubleshooting docs.

Reviewed by Cursor Bugbot for commit ca6266c. Configure here.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 30, 2026

Deploy Preview for viteplus-preview canceled.

Name Link
🔨 Latest commit ca6266c
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/69d7a03b34c2bd00080885f8

Copy link
Copy Markdown
Member Author

fengmk2 commented Mar 30, 2026


How to use the Graphite Merge Queue

Add the label auto-merge to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@fengmk2 fengmk2 self-assigned this Mar 30, 2026
@fengmk2 fengmk2 marked this pull request as ready for review March 30, 2026 12:32
@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from 5adc3fd to 49d17df Compare March 30, 2026 12:34
Copy link
Copy Markdown
Contributor

@leaysgur leaysgur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no objection to recommending this method as a current workaround. 👌🏻

(However, I cannot judge whether this is the best approach, as I do not know the background behind why this lazy was introduced.)

@cpojer
Copy link
Copy Markdown
Member

cpojer commented Mar 31, 2026

I'm really not a fan of the lazy attribute and I don't think we should recommend it. It would be better to make the plugins field either an array or a function that returns Promise<Array<…>>.

@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from 49d17df to b3cb2f5 Compare March 31, 2026 03:08
@fengmk2 fengmk2 changed the title docs: add lazy loading plugins documentation and tests docs: add config troubleshooting page with lazy loading guide Mar 31, 2026
@fengmk2
Copy link
Copy Markdown
Member Author

fengmk2 commented Mar 31, 2026

I'm really not a fan of the lazy attribute and I don't think we should recommend it. It would be better to make the plugins field either an array or a function that returns Promise<Array<…>>.

This needs to be resolved on the Vite side. I think Vite+ should not change the meaning of fields defined by Vite. @sapphi-red

@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from b3cb2f5 to 8936d0c Compare March 31, 2026 03:31
@fengmk2 fengmk2 changed the title docs: add config troubleshooting page with lazy loading guide docs: add config troubleshooting page with lazy plugin loading guide Mar 31, 2026
@fengmk2 fengmk2 marked this pull request as draft March 31, 2026 05:18
@cpojer
Copy link
Copy Markdown
Member

cpojer commented Mar 31, 2026

Upstream issue created here: vitejs/vite#22085

@fengmk2 fengmk2 closed this Apr 2, 2026
@fengmk2 fengmk2 reopened this Apr 3, 2026
@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from 8936d0c to 71d3659 Compare April 3, 2026 07:25
@fengmk2 fengmk2 changed the title docs: add config troubleshooting page with lazy plugin loading guide feat: add vitePlugins() helper for conditional plugin loading Apr 3, 2026
@fengmk2 fengmk2 marked this pull request as ready for review April 3, 2026 08:17
@fengmk2 fengmk2 added the test: e2e Auto run e2e tests label Apr 3, 2026
@cpojer
Copy link
Copy Markdown
Member

cpojer commented Apr 6, 2026

I don't really follow, why do we need to add a new function to wrap plugins instead of redefining the plugin type from plugins: Array<Plugin> to plugins: Array<Plugin> | () => Promise<Array<Plugin>>?

@TheAlexLichter
Copy link
Copy Markdown
Member

I don't really follow, why do we need to add a new function to wrap plugins instead of redefining the plugin type from plugins: Array<Plugin> to plugins: Array<Plugin> | () => Promise<Array<Plugin>>?

That only works if we'd "guarantee" there are no plugins that can influence the behavior of vp lint, vp fmt etc.

@cpojer
Copy link
Copy Markdown
Member

cpojer commented Apr 6, 2026

For now, that's the expectation, yes.

@TheAlexLichter
Copy link
Copy Markdown
Member

I think then we can also wrap the whole function (as long there is no type mismatch or we alter the allowed types of plugins).

@fengmk2 fengmk2 marked this pull request as draft April 7, 2026 15:40
@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from 7a6bc52 to 91d5fdf Compare April 7, 2026 16:17
@fengmk2 fengmk2 changed the title feat: add vitePlugins() helper for conditional plugin loading feat: extend defineConfig to support lazy plugin loading via factory functions Apr 7, 2026

This comment was marked as outdated.

chatgpt-codex-connector[bot]

This comment was marked as outdated.

@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch 2 times, most recently from 4f0cf8a to 3c27538 Compare April 8, 2026 09:27
@fengmk2 fengmk2 marked this pull request as ready for review April 8, 2026 09:27
@fengmk2 fengmk2 requested a review from TheAlexLichter April 8, 2026 09:27
@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from 3c27538 to 63140ee Compare April 8, 2026 10:06

This comment was marked as duplicate.

chatgpt-codex-connector[bot]

This comment was marked as outdated.

@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from 63140ee to a1c78a7 Compare April 9, 2026 02:50

This comment was marked as outdated.

chatgpt-codex-connector[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Member

@cpojer cpojer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's beautiful. From a UX perspective, I love it. I don't know if there are any remaining concerns from the Vite side, cc @sapphi-red if you don't mind signing off on this 🙇‍♂️

@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from e9d0689 to db118db Compare April 9, 2026 11:57
…functions

The `plugins` field in `defineConfig` now accepts factory functions
(`() => PluginOption[]` or `async () => Promise<PluginOption[]>`)
in addition to the standard `PluginOption[]` array.

The factory is only called for vite commands (dev, build, test, preview)
and skipped for non-vite commands (lint, fmt, check, etc.), avoiding
unnecessary plugin loading overhead. When VP_COMMAND is unset (e.g.,
running vitest directly or via VS Code extension), plugins load by default.

VP_COMMAND is set automatically by `vp` in bin.ts and injected into
child process envs by the Rust resolver for synthesized subcommands.

Refs vitejs/vite#22085
@fengmk2 fengmk2 force-pushed the how-to-use-lazy-field branch from db118db to ca6266c Compare April 9, 2026 12:48
@fengmk2
Copy link
Copy Markdown
Member Author

fengmk2 commented Apr 10, 2026

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ca6266c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test: e2e Auto run e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants