uni-app 自动化生成 pages.json?我写了个 chokidar 脚本来给路由续命

2026-08-14 0 985

用过 uni-app 的兄弟都知道,每次新建一个页面,都要去 pages.json 里手动注册路由。页面少还行,项目到了几十个页面的时候,一不留神就忘了加,然后编译报错“页面未找到”。这破事我已经犯过 N 次了。

后来实在忍不了,我就琢磨着写一个脚本,专门监听 src/pages 目录,只要新增或删除了 .vue 文件,就自动重写 pages.json。现在开发新页面,只需要在 pages 下新建一个 xxx.vue,其他啥都不用管,路由自动就有了。

今天这篇就是分享一下我这个小工具的思路和完整代码,不是特别复杂,但对懒人非常实用。

1. 先说思路

uni-app 用 Vite 构建的话,项目结构一般是 src/pages 放页面文件,src/pages.json 是全局配置文件。新建一个页面,本质就是在 src/pages 下加一个 .vue 文件。

所以我只要监听 src/pages 目录下的文件变化,然后遍历整个目录,把每个 .vue 文件的相对路径提取出来,转成 pages 数组里的一项,再写回 pages.json。就这么简单。

但直接覆盖写不太行,因为 pages.json 里还有 globalStyletabBar 这些配置,所以脚本得先读原来的 pages.json,保留这些字段,只替换 pages 数组。

2. 工具选择:chokidar 加 prettier

监听文件变化我用的是 chokidar,这个库老牌稳定,Webpack 也是用它来监听文件的。写 JSON 的时候顺便用 prettier 格式化一下,不然生成出来的 JSON 挤成一坨心里难受。

当然,如果你想临时快速跑一下,也可以直接用 Node 自带的 fs.watch,但 chokidar 支持递归监听、忽略隐藏文件、防抖,省心很多。

安装依赖:

npm install chokidar prettier

如果你还需要同时跑多个命令,建议再装一个 concurrently

npm install concurrently

3. 脚本完整代码

我把脚本放在项目根目录,命名为 auto-pages.js。直接看代码:

// auto-pages.js
const chokidar = require('chokidar')
const fs = require('fs')
const path = require('path')
const prettier = require('prettier')

const PAGES_DIR = path.join(__dirname, 'src', 'pages')
const PAGES_JSON_PATH = path.join(__dirname, 'src', 'pages.json')

// 默认页面配置
const DEFAULT_NAV = {
    navigationBarTitleText: '默认标题',
    enablePullDownRefresh: false
}

// 递归获取 pages 数组
function getPages() {
    const pages = []

    function walk(dir, parentPath = '') {
        const entries = fs.readdirSync(dir, { withFileTypes: true })
        entries
            .sort((a, b) => a.name.localeCompare(b.name))
            .forEach(entry => {
                const fullPath = path.join(dir, entry.name)
                const relativePath = path.join(parentPath, entry.name).replace(/\/g, '/')

                if (entry.isDirectory()) {
                    walk(fullPath, relativePath)
                } else if (entry.isFile() && entry.name.endsWith('.vue')) {
                    const pagePath = relativePath.replace('.vue', '')
                    // 读取页面顶部注释,支持自定义标题
                    const content = fs.readFileSync(fullPath, 'utf-8')
                    const configMatch = content.match(/<!--s*pages?s*({[sS]*?})s*-->/)
                    let styleOverrides = {}
                    if (configMatch) {
                        try {
                            styleOverrides = JSON.parse(configMatch[1])
                        } catch (e) {
                            console.warn(`解析 ${pagePath} 页面配置失败:`, e)
                        }
                    }
                    pages.push({
                        path: pagePath,
                        style: { ...DEFAULT_NAV, ...styleOverrides }
                    })
                }
            })
    }

    walk(PAGES_DIR)
    return pages
}

// 写入 pages.json
function writeJson(pages) {
    let existing = {}
    try {
        existing = JSON.parse(fs.readFileSync(PAGES_JSON_PATH, 'utf8'))
    } catch (e) {
        existing = { globalStyle: {}, tabBar: {} }
    }

    const newJson = {
        ...existing,
        pages: [...pages]
    }

    const formatted = prettier.format(JSON.stringify(newJson), { parser: 'json' })
    fs.writeFileSync(PAGES_JSON_PATH, formatted, 'utf8')
    console.log(`[auto-pages] 更新了 pages.json,共 ${pages.length} 个页面`)
}

async function update() {
    const pages = getPages()
    writeJson(pages)
}

// 首次启动时先跑一次
update()

// 监听文件变化
const watcher = chokidar.watch(PAGES_DIR, {
    ignoreInitial: true,
    ignored: /(^|[/\])../,
    persistent: true
})

watcher
    .on('add', filePath => {
        console.log(`[auto-pages] 新页面: ${filePath}`)
        update()
    })
    .on('unlink', filePath => {
        console.log(`[auto-pages] 删除页面: ${filePath}`)
        update()
    })
    .on('addDir', dirPath => {
        console.log(`[auto-pages] 新目录: ${dirPath}`)
        update()
    })
    .on('unlinkDir', dirPath => {
        console.log(`[auto-pages] 删除目录: ${dirPath}`)
        update()
    })

这段代码核心就是 getPages() 函数。它遍历 src/pages 目录,找所有 .vue 文件,把相对路径拼成类似 order/detail 的字符串,作为 path。同时解析每个文件最顶部的注释,如果注释是 <!-- {"navigationBarTitleText": "订单详情"} --> 这种格式,就用它来覆盖默认的页面标题。

最后把已有的 pages.json 内容扩展一下,替换掉原来的 pages 数组,格式化后写回。

4. 页面里怎么自定义标题等配置

比如你要新建一个订单详情页,不想用默认标题,那就在 order/detail.vue 文件顶部加一行注释:

<!-- { "navigationBarTitleText": "订单详情" } -->
<template>
    <view>
        <text>这里是订单详情</text>
    </view>
</template>

脚本运行后,pages.json 里对应的页面会自动带上这个标题。除了导航栏标题,你还能加 enablePullDownRefreshbackgroundColor 之类的配置,写法就是 JSON 格式。

5. 和 dev 命令一起跑

光有脚本还不够,你得让它和 uni-app 的 dev 进程同时跑。我用 concurrently 来做这事。比如在 package.json 里这样配:

{
  "scripts": {
    "dev:h5": "concurrently "node auto-pages.js" "uni -p h5"",
    "dev:app": "concurrently "node auto-pages.js" "uni -p app"",
    "dev:mp-weixin": "concurrently "node auto-pages.js" "uni -p mp-weixin""
  }
}

这样启动后,你只管新建 .vue 文件,auto-pages.js 在后台监听到变化,自动改 pages.json。同一时间 uni-app 的编译器也在运行,重新编译后新页面就能直接访问了。

6. 踩过的一些坑

首先,脚本千万不要在 uni-app 编译前跑完了才启动。 最好是用 concurrently 同时跑,不然你后来新建文件它不会监听。我第一次就是单独跑了个 node auto-pages.js,然后忘了放在后台,结果搞半天没动静。

其次,pages.json 里的 pages 数组顺序不能乱来。 虽然 uni-app 没强制要求第一个页面是首页,但如果你 tabBar 里配置了页面,顺序也必须对应。脚本只是把目录里的文件按字母序排了,这可能导致你的 tabBar 页面顺序变乱。所以如果你有 tabBar,我的建议是脚本只负责新增页面,手动调整一下关键顺序,或者干脆在 pages.json 里写一个静态的部分,让脚本合并。但这会复杂很多,我目前也没做特别好的处理,基本靠每次改了以后瞄一眼。

还有,删除文件的时候要小心。 如果你删了一个目录,脚本会触发 unlinkDir,然后重新生成 pages.json,这是对的。但如果目录里还有其他文件,可能会产生不正确的路径。所以我的脚本在删除时直接重新遍历整个目录,保证最终结果是符合当前文件系统的。

最后,关于分包。 我这个简化版没有处理 subPackages,分包里的页面你得手动写在 subPackages 数组里。不过思路可以扩展,判断一下目录名是否在分包列表里,然后分别生成。我项目里暂时没用到,就没折腾了。

7. 实际用下来什么感觉

真香。虽然前期装依赖写脚本花了一小时,但之后每次新建页面都特别顺滑。尤其是从别人仓库拉下来以后,页面很多,不用再去核对 pages.json 缺了哪个。只需要看一眼文件在不在。

有一次同事拉代码,新建了一个页面,结果跑起来报错“page not found”。我说你等两秒,看看 pages.json 里有没有。他说还没呢,我说那就再等一下,脚本要反应。过了两秒他再去找,发现已经自动写进去了。

这感觉,咋说呢,就像请了一个管家,你只管往房间里扔东西,他会自动帮你收拾整齐。

8. 可以改进的地方

如果你想要更完美的方案,可以考虑这些点:

  • 支持分包:解析 src/pages 下的一级目录作为分包根路径。
  • 支持页面配置注释中的 path 字段:允许某个页面自定义路由路径,而不是强制用目录结构。
  • 加入防抖:短时间内大量新增文件,避免多次写磁盘。
  • 直接集成到 Vite 插件里,不过那要单独开发 uni-app 插件了,复杂度高一些。

9. 总结一下

自动生成 pages.json 不是玄学,就是一个 Node 脚本的事。它解决的是“重复劳动”和“低级遗忘”的问题。如果你也在用 uni-app,并且手头项目页面不少,我强烈建议你复制上面的代码改吧改吧用起来。

反正对我来说,自从用了这个脚本,再也没因为漏写 pages.json 被同事喊过“页面呢?”。

代码拿去吧,不用谢。

uni-app 自动化生成 pages.json?我写了个 chokidar 脚本来给路由续命
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

版权声明:
本站资源有的来自互联网收集整理,本站纯免费分享提供学习使用,如果侵犯了您的合法权益,请联系本站我们会及时删除。
本站资源仅供研究、学习交流之用,免费开源项目不代表完全可商用,若商业用途请先咨询开发企业能否商用,否则产生的一切后果将由下载用户自行承担。
原创板块未经允许不得转载,否则将追究法律责任。

淘吗网 uniapp uni-app 自动化生成 pages.json?我写了个 chokidar 脚本来给路由续命 https://www.taomawang.com/web/uniapp/2539.html

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务