跪拜 Guibai
← All articles
Frontend · Vite

A Vite Plugin Now Generates uni-app's pages.json from Vue Files, Eliminating Manual Config

By PedroQue99 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Manually synchronizing a central `pages.json` with a growing set of page files is a persistent source of errors and merge conflicts in uni-app projects. Automating its generation from the pages themselves removes that friction and keeps configuration co-located with the code it describes.

Summary

Version 1.2.0 of the `@meng-xi/vite-plugin` suite adds a `generatePages` plugin that reverses the typical uni-app workflow. Instead of manually maintaining a central `pages.json` file and then generating routes from it, the plugin scans the project's Vue files and a custom `<route-config>` block within each page to build the configuration automatically. It handles main package pages, sub-packages, and tab bar assembly, while preserving non-page fields like `globalStyle`.

Page-level configuration—titles, meta fields, and tab bar icons—is declared directly inside the Vue file it affects. A stable sorting algorithm and an `entryPage` option prevent the startup page from drifting alphabetically. The plugin also watches for file changes during development, regenerating `pages.json` through a serial queue to avoid race conditions.

Combined with the existing `generateRouter` plugin, the toolchain now forms a complete automated pipeline: Vue files produce `pages.json`, which in turn produces typed route configurations. The upgrade is non-breaking for all 1.x users and expands Vite peer dependency compatibility up to version 8.

Takeaways
Scans `src/pages` and `src/pages-sub` directories by default to build the `pages` and `subPackages` arrays.
A `<route-config>` custom block inside each Vue file declares the page's title, style, meta, name, and tab bar properties.
An `entryPage` option locks the startup page to `pages[0]`, preventing alphabetical sorting from shifting it.
Tab bar items are auto-collected from pages marked `isTab: true` and sorted by an optional `order` field that is not written to the output.
The merge strategy overwrites only the page-related sections of `pages.json`, leaving `globalStyle`, `condition`, and `easycom` untouched.
File watching in dev mode uses a serial queue to safely regenerate `pages.json` when pages are added, removed, or modified.
Peer dependency range for Vite is relaxed to `<9.0.0`, adding Vite 8 compatibility.
Conclusions

Co-locating page configuration inside the Vue file itself, rather than in a separate JSON manifest, mirrors the shift in modern frameworks toward file-system-based routing and reduces the surface for configuration drift.

The explicit `entryPage` option addresses a real-world footgun in uni-app where relying on alphabetical path order can silently change the startup page as a project grows.

Using a serial queue for watch-mode regeneration is a pragmatic defense against race conditions that many file-watching tools overlook, especially when multiple file events fire in quick succession.

Concepts & terms
uni-app pages.json
A central manifest file in uni-app projects that declares all page paths, sub-packages, tab bar configuration, and global window styles. It is the single source of truth that the framework uses to register and navigate between pages.
route-config custom block
A custom Vue Single-File Component block (`<route-config>`) that contains JSON configuration for a specific page. The `generatePages` plugin reads this block to extract page-level settings like the navigation bar title, tab bar membership, and meta fields.
From the discussion
Featured comments
Undefined94515

Compared to the <route-config> configuration, a more elegant approach would be to declare a definePage in the page, for example: definePage({ name: 'mine', meta: { needLogin: false }, style: { navigationBarTitleText: '我的' } }) Also, files that don't declare route-config or definePage in the Vue page won't be generated into page.json, right?

PedroQue99

Files that don't declare route-config or definePage in the Vue page won't be generated into page.json.

Undefined94515  → PedroQue99

Yeah, that's what we expect. Adding a definePage would be perfect. One more question: definePage({ name: 'mine', meta: { needLogin: false }, style: { navigationBarTitleText: '我的' } }) In a case like this, where I haven't defined a title but have set navigationBarTitleText in style, will the final generation still preserve my style: { navigationBarTitleText: '我的' } and not fall back to a default strategy for a missing title?

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗