跪拜 Guibai
← Back to the summary

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

Version: 1.2.0 | License: MIT | Dependencies: Vite >=5.0.0 <9.0.0


Foreword

The theme of v1.2.0 is: Added generatePages plugin, enabling automatic generation of pages.json.

Previously, generateRouter was "read pages.json → generate route configuration", but pages.json itself still required manual maintenance. v1.2.0 adds the 16th plugin generatePages, which does the opposite — scans Vue files + <route-config> custom blocks within pages, automatically generating / updating pages.json for pages / subPackages / tabBar, completely freeing you from manual page configuration.

Additionally, this version relaxes Vite's peerDependencies range to <9.0.0, ensuring compatibility with Vite 8.

Highlights of this version:

Capability One-sentence description What you need to do
New generatePages plugin Scans Vue files + <route-config> blocks to auto-generate pages.json Replace manual maintenance of pages.json page section
Main / sub-package pages pagesDir + subPackages auto-scan to generate pages and subPackages Just place page files according to directory structure conventions
tabBar auto-collection isTab flag + tabBar template auto-assembles list Declare isTab + tab icons within the page
Proximate configuration declaration <route-config> custom block declares title / style / meta / name within the page Configuration follows the page file, no centralized maintenance needed
Entry page fixed entryPage ensures the startup page is pages[0] Specify the entry page path
Non-page fields preserved Only overwrites the page section, preserves globalStyle / condition etc. No extra configuration needed

Upgrade method: Change the version number in devDependencies to ^1.2.0. No Breaking Changes, 1.x users can upgrade smoothly.


1. Quick Start in 5 Minutes

1.1 Installation and Upgrade

{
	"devDependencies": {
		"@meng-xi/vite-plugin": "^1.2.0"
	}
}

1.2 Basic Usage

Scans src/pages as the main package and src/pages-sub as sub-packages by default, automatically generating src/pages.json:

// vite.config.ts
import { defineConfig } from 'vite'
import { generatePages } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [generatePages()]
})

1.3 Proximate Configuration Declaration within Pages

Declare title, meta, and tabBar affiliation in each page using the <route-config> custom block:

<!-- src/pages/index/index.vue -->
<route-config>
{
	"title": "Home",
	"isTab": true,
	"tab": {
		"iconPath": "static/tab/home.png",
		"selectedIconPath": "static/tab/home-active.png"
	}
}
</route-config>

Generated pages.json snippet:

{
	"pages": [
		{
			"path": "pages/index/index",
			"style": { "navigationBarTitleText": "Home" },
			"meta": { "isTab": true }
		}
	],
	"tabBar": {
		"color": "#999999",
		"list": [
			{
				"pagePath": "pages/index/index",
				"text": "Home",
				"iconPath": "static/tab/home.png",
				"selectedIconPath": "static/tab/home-active.png"
			}
		]
	}
}

1.4 Combining with generateRouter

generatePages generates pages.json, and generateRouter reads pages.json to generate route configuration — the two can be seamlessly combined:

// Note: generatePages should be placed before generateRouter
;(generatePages({ tabBar: { color: '#999999', selectedColor: '#42b883' } }), generateRouter({ pagesJsonPath: 'src/pages.json' }))

2. generatePages Plugin Details

2.1 Core Capabilities

Capability Configuration / Usage Description
Main package page generation pagesDir: 'src/pages' Recursively scans to generate pages, stable page path sorting
Sub-package page generation subPackages: [{ root, dir }] Auto-scans to generate subPackages, skips if directory is missing
tabBar collection <route-config> declares isTab + tabBar template Automatically collects tab pages into tabBar.list
Proximate configuration declaration <route-config> custom block Title / style / meta / name / tab declared proximately within the page
Entry page fixed entryPage: 'pages/index/index' Ensures pages[0] is the startup page, not overwritten by alphabetical sorting
tabBar sorting <route-config>.tab.order Sorts list by order ascending, used only for sorting, not written to output
Merge strategy Automatic (no configuration needed) Only overwrites the page section, preserves globalStyle / condition etc.
Dev watch watch: true (default) Auto-regenerates when page directory files change

2.2 route-config Custom Block

Declare configuration proximately within the page (content is JSON, supports comments):

<route-config>
{
	"title": "Details",
	"name": "DetailPage",
	"meta": { "requireAuth": true },
	"isTab": true,
	"tab": { "text": "Details", "iconPath": "static/tab/detail.png", "order": 1 }
}
</route-config>
Field Type Description
title string Page title, mapped to style.navigationBarTitleText
name string Page name, written to the name field
style object Written as-is to the style field
meta object Written as-is to the meta field
isTab boolean Whether it's a tabBar page, automatically collected into tabBar.list
tab TabBarItemOverride tabBar icon / text / order sorting weight

Note: tabBar pages are only allowed in the main package; isTab flags in sub-packages will be ignored.

2.3 Entry Page Fixed

uni-app uses pages[0] as the startup page. If sorted directly by path, the entry page can drift alphabetically (e.g., the default entry pages/index/index might be replaced by pages/about/about). entryPage ensures the entry page is always fixed at the first position:

generatePages({
	entryPage: 'pages/index/index' // Inherits existing pages.json's pages[0] if not configured
})

2.4 tabBar Template and Priority

After providing a tabBar template, the plugin automatically collects all main package pages with isTab: true into list:

generatePages({
	tabBar: {
		color: '#999999',
		selectedColor: '#42b883',
		iconPath: 'static/tab/home.png', // Global default icon, inherited by all tab items
		selectedIconPath: 'static/tab/home-active.png',
		overrides: {
			// Override per page path (optional)
			'pages/about/about': {
				text: 'About Us',
				iconPath: 'static/tab/about.png',
				selectedIconPath: 'static/tab/about-active.png'
			}
		}
	}
})

Icon and text priority (from high to low):

  1. <route-config>.tab declaration within the page
  2. tabBar.overrides[pagePath]
  3. tabBar.iconPath / selectedIconPath (global template)
  4. Page title / filename (as text fallback)

list sorting: Sorted by each item's tab.order ascending (smaller values first), items without declared order are placed after declared ones, maintaining their original relative order; order is only used for sorting and will not be written into the generated tabBar.list.

2.5 Merge Strategy

The plugin "only generates the page section, preserves the rest":

2.6 Dev Watch

In dev mode, watch: true (default) monitors main package and sub-package directories, auto-regenerating when pages are added / deleted / modified. Generation tasks are processed through a serial queue to avoid concurrent read-write race conditions during high-frequency changes.


3. Configuration Options

Option Type Default Value Description
pagesJsonPath string 'src/pages.json' pages.json file path
pagesDir string 'src/pages' Main package page directory
subPackages SubPackageConfig[] [{ root:'pages-sub', dir:'src/pages-sub' }] Sub-package configuration list (skipped if directory is missing)
routeConfigBlock string 'route-config' Page configuration custom block name
entryPage string Existing pages[0] Main package entry page path, fixed as pages[0]
titleFallback 'filename' | 'none' 'filename' Fallback strategy when title is missing
tabBar TabBarTemplate - tabBar template (only generated when provided)
includeExtensions string[] ['.vue'] Page file extension list
excludePatterns string[] ['node_modules'] Path pattern list to exclude
watch boolean true Watch page directory changes and auto-regenerate

Inherits BasePluginOptions: enabled, logLevel, errorStrategy.

Type Exports


4. Sub-path Export Changes

New

Dependency Range


5. Practical Scenarios

5.1 uni-app Project: Fully Automatic Page Configuration

// vite.config.ts
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { generatePages, generateRouter } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [
		uni(),
		// 1. Generate pages.json (must be before generateRouter)
		generatePages({
			pagesDir: 'src/pages',
			subPackages: [{ root: 'pages-sub', dir: 'src/pages-sub' }],
			entryPage: 'pages/index/index',
			tabBar: {
				color: '#999999',
				selectedColor: '#42b883',
				backgroundColor: '#ffffff'
			}
		}),
		// 2. Generate route configuration based on pages.json
		generateRouter({ pagesJsonPath: 'src/pages.json' })
	]
})

Proximate declaration within the page:

<!-- src/pages/mine/mine.vue -->
<route-config>
{
	"title": "Mine",
	"isTab": true,
	"tab": {
		"iconPath": "static/tab/mine.png",
		"selectedIconPath": "static/tab/mine-active.png"
	}
}
</route-config>

5.2 Multiple Sub-packages + Namespace

generatePages({
	pagesDir: 'src/pages',
	subPackages: [
		{ root: 'pages-sub', dir: 'src/pages-sub' },
		{ root: 'pages-home', dir: 'src/pages-home' }
	],
	// Note: sub-package dir should match the directory structure corresponding to root, otherwise uni-app cannot find sub-package files
	excludePatterns: ['node_modules']
})

5.3 Zero-Configuration Experience

Without passing any parameters, the defaults cover most scenarios:

generatePages()
// Scans src/pages → pages, src/pages-sub → subPackages, auto-generates src/pages.json

6. Plugin List (Changes)

Total plugins increased from 15 to 16, groups remain at 7:

Group Plugins
generate autoImport, generatePages, generateRouter, generateVersion (increased from 3 to 4)
analyze buildProgress, bundleAnalyzer
compress compressAssets, imageOptimizer
copy assetManifest, copyFile
guard envGuard
inject faviconManager, htmlInject, loadingManager, versionUpdateChecker
proxy proxyManager

7. Notes


Afterword

v1.2.0 completes the "page configuration" link in the uni-app development chain: generatePages is responsible for generating pages.json, and generateRouter is responsible for generating route configuration and type declarations based on pages.json, forming a complete "page file → page configuration → route configuration" automation loop.

Future versions will focus on: more automation for uni-app scenarios (such as manifest.json configuration generation), deep integration of generatePages with uni-app conditional compilation. If you have any suggestions or questions, feel free to provide feedback on GitHub Issues.

Comments

Top 1 of 5 from juejin.cn, machine-translated. The original thread is authoritative.

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?