Skip to content

feat!: refine bundler options#1714

Open
Mister-Hope wants to merge 2 commits into
mainfrom
bundler-refine
Open

feat!: refine bundler options#1714
Mister-Hope wants to merge 2 commits into
mainfrom
bundler-refine

Conversation

@Mister-Hope
Copy link
Copy Markdown
Member

@Mister-Hope Mister-Hope commented May 21, 2026

Summary

Refine the Bundler interface and bundler configuration hooks to give plugin authors the tools they need to configure bundler-specific behavior correctly and completely.


Problems & Rationale

1. Complex comparison to identify the active bundler

Plugins in extendsBundlerOptions need to know which bundler is active to add the right options (e.g. viteOptions vs chainWebpack). The only discriminator was bundler.name, which is the full scoped package name.

- app.options.bundler.name === '@vuepress/bundler-webpack'
+ app.options.bundler.type === 'webpack'

2. Missing merge helper in extendsBundlerOptions

When a plugin accepts user bundler options and wants to merge them into the resolved options, it needs the correct merge function (vite.mergeConfig vs webpack-merge differ in semantics). The hook only passes (options, app) — no merge helper.

We considered adding mergeConfig as a hook parameter, but all extends* hooks share the uniform signature (extendable: T, app: App):

// hooks.ts — every extends hook follows this pattern
extendsMarkdownOptions: ExtendsHook<MarkdownOptions>
extendsMarkdown: ExtendsHook<Markdown>
extendsPageOptions: ExtendsHook<PageOptions>
extendsPage: ExtendsHook<Page>
extendsBundlerOptions: ExtendsHook<BundlerOptions>

Adding a third parameter would break this consistency. So mergeConfig is exposed on the Bundler object instead:

  export interface Bundler {
    name: string
+   type: string
    dev: (app: App) => Promise<() => Promise<void>>
    build: (app: App) => Promise<void>
+   mergeConfig: <Config extends Record<string, any>>(
+     currentConfig: Config,
+     newConfig: DeepPartial<Config>,
+   ) => Config
  }

Plugins access it naturally: app.options.bundler.mergeConfig(...).

3. configureWebpack / configureVite cannot remove array items

The old merge-on-return model was purely additive — array items could only be appended, never deleted.

  // resolveWebpackConfig.ts
  const configureWebpackResult = options.configureWebpack?.(...)

- // if `configureWebpack` returns a configuration object,
- // use webpack-merge to merge it
  if (configureWebpackResult) {
-   return merge(webpackConfig, configureWebpackResult)
+   webpackConfig = configureWebpackResult
  }

Returning a value now fully replaces the config. To merge explicitly, use the mergeConfig callback parameter passed to the hook.

Note: the mergeConfig from vite always create a fresh new object at every level while merging.


Breaking changes

  • Bundler interface now requires type and mergeConfig.
  • configureWebpack return value replaces the config. Use the passed mergeConfig parameter to merge instead.

@coveralls
Copy link
Copy Markdown

Coverage Report for CI Build 26201119905

Coverage remained the same at 72.983%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1061
Covered Lines: 770
Line Coverage: 72.57%
Relevant Branches: 538
Covered Branches: 397
Branch Coverage: 73.79%
Branches in Coverage %: Yes
Coverage Strength: 45.72 hits per line

💛 - Coveralls

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants