Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(config): Hierarchical site configuration using distributed config files #4660

Open
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

zhangyx1998
Copy link
Contributor

@zhangyx1998 zhangyx1998 commented Mar 30, 2025

Description

Please see #4659 for more context.

Summary of changes

  1. ‎src/client/app/data.ts:

  2. ‎src/client/app/utils.ts:

    • Added stackView() and supporting utilities to merge multiple layers of objects into a readonly view, without mutating the original objects - this is important because certain layers may be dropped later when user navigates outside its scope.
  3. Configuration Files

    The configuration files are moved from .vitepress/config to their corresponding language subdirectories (e.g. docs/.vitepress/config/en.ts -> docs/en/config.ts) to demonstrate the benefits of the proposed changes. In addition, a language-specific locale is added for 404 pages under /zh/ directory. It is reflected in the rendered preview.

Linked Issues

closes #4659
closes #4654

Additional Context

Please refer to the linked issue for highlights of this PR.


Tip

The author of this PR can publish a preview release by commenting /publish below.

/publish

@brc-dd
Copy link
Member

brc-dd commented Mar 30, 2025

An obvious downside is we can't use node stuff in configs. What if we glob and load all the configs at plugin-level instead of doing it via import.meta.glob in client code? We can create a virtual module that exports extraConfig. Probably resolveUserConfig can be adjusted and reused. That would also avoid hardcoding things in manualChunks.

@brc-dd
Copy link
Member

brc-dd commented Mar 30, 2025

Also, the site appears to be broken. There is probably a circular dependency somewhere in generated code.

@brc-dd
Copy link
Member

brc-dd commented Mar 30, 2025

/publish

Copy link

pkg-pr-new bot commented Mar 30, 2025

npm i https://pkg.pr.new/vitepress@4660

commit: e142477

@zhangyx1998
Copy link
Contributor Author

An obvious downside is we can't use node stuff in configs. What if we glob and load all the configs at plugin-level instead of doing it via import.meta.glob in client code? We can create a virtual module that exports extraConfig. Probably resolveUserConfig can be adjusted and reused. That would also avoid hardcoding things in manualChunks.

This seems like a better solution. I'll try to adapt this approach.

@zhangyx1998
Copy link
Contributor Author

zhangyx1998 commented Mar 30, 2025

Updates:

1. Removed import.meta.glob from client side. Config file collection is now implemented inside resolveUserConfig().

2. Instead of creating a virtual module @additionalConfig, an optional configuration entry UserConfig.additionalConfig is implemented for better flexibility:

  • When left undefined, resolveUserConfig will automatically collect all eligible config files and organize them into a dictionary as its default value. It utilizes loadConfigFromFile() and hence supports node APIs.

  • When defined as an object, the client code will auto select config layers to apply. For example:

    import en_config from './en'
    import zh_config from './zh'
    export default defineConfig({
        /* ... */
        additionalConfig: {
            '/en/': en_config,
            '/zh/': zh_config,
        }
    })
  • When defined as a function (path: string) => AdditionalConfig[], user can have even higher flexibility defining which configuration layers should be applied, and in what order they will apply:

    export default defineConfig({
        /* ... */
        additionalConfig(path) {
            return [{
                title: `Hello from ${path}`
            }]
        }
    })

    Produces:

    image

@brc-dd could you please review this again? Appreciate it!

@zhangyx1998 zhangyx1998 requested a review from brc-dd March 30, 2025 15:58
@brc-dd
Copy link
Member

brc-dd commented Mar 30, 2025

Thanks a lot! 🙌 Overall looks good. I'll test some stuff locally and merge if nothing pops up.

@zhangyx1998
Copy link
Contributor Author

zhangyx1998 commented Mar 31, 2025

Summary of update:

Code Cleanup

  • Removed type annotation for injected symbol (VP_SOURCE - internal dev use only).
  • Renamed the injection symbol from VP_SOURCE to [VP_SOURCE]. It is now impossible to be confused with a JS variable nor a legal URL path component. The new symbol is consistent with the one introduced in feat(config, theme): add clientOnly marker #4663 [VP_CLIENT_ONLY]

Typing Helper

  • Added type DeepPartial<...> to reflect the nature of type AdditionalConfig
  • Added type helper defineAdditionaConfig() and defineAdditionalConfigWithTheme()
  • Updated additional config files under /docs/ to reflect the above update.

There is no major change since last review. This PR should be ready to merge.

@zhangyx1998 zhangyx1998 requested a review from brc-dd April 1, 2025 04:24
@brc-dd
Copy link
Member

brc-dd commented Apr 3, 2025

Give me a day or two. I'll check everything and merge it by weekend. Got bit busy with day job.

@zhangyx1998 zhangyx1998 force-pushed the feat/hierarchical-theme-config branch from e9da2e4 to 787b825 Compare April 5, 2025 11:14
@zhangyx1998
Copy link
Contributor Author

zhangyx1998 commented Apr 5, 2025

The latest commit relocates config synthesis from initData() (client/data.ts) to resolveSiteDataByRoute() (shared.ts). This ensures the SSR context also receives correct configuration based on its route.

@zhangyx1998
Copy link
Contributor Author

@brc-dd Since commit 27c4151, Netlify build constantly fails due to "javascript heap out of memory". My local build and test runs did not have the same problem though.

@brc-dd
Copy link
Member

brc-dd commented Apr 6, 2025

ah it's failing on main too. I'll revert it

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

Successfully merging this pull request may close these issues.

Multi-layer hierarchical configuration overloading
3 participants