将uniapp的pages.json中的分包进行拆分(vue3)

📦 Uni-app 项目分包提取与构建自动化脚本集

✨ 背景介绍

在 Uni-app 项目中,合理使用 subPackages(分包)不仅能提升 App 首屏加载速度,还能增强模块化管理,特别适用于大型项目或多人协作开发场景。

为了简化分包配置的维护,本文提供了一套完整的 Node.js 脚本方案,支持以下功能:

  • 自动从 pages.json 提取 subPackages 并生成独立配置文件(按需使用);
  • 将独立配置文件合并回 pages.json,避免手动修改;
  • 集成到 Vite 构建流程中,实现构建时自动更新配置,提升开发与发布效率。

⚠️ 使用前需确保本地已安装 Node.js


📁 项目结构概览

建议目录结构如下:

arduino 复制代码
arduino
复制编辑
your-project/
├─ pages.json                // 页面配置主文件
├─ createSubPackageDirs.js   // 提取并生成分包 JSON 的脚本
├─ build-pages.js            // 根据分包 JSON 写入 pages.json 的脚本
├─ vite.config.js            // Vite 构建配置,集成自动更新脚本
├─ subPackages_pages/        // 存放分包 JSON 的目录

🛠 脚本一:提取分包配置并生成 JSON 文件

✅ 脚本功能

  • 读取 pages.json 中的 subPackages 配置;
  • 为每个分包生成一个以 root 最后路径片段命名的 .json 文件;
  • 输出目录为 subPackages_pages/,便于模块管理与版本控制。

🔧 使用方法

⚠️ 该脚本是为了将就旧项目中pages.json里面的分包进行提取以便管理,该脚本也可以不执行

复制代码
bash
复制编辑
node createSubPackageDirs.js

执行后将自动生成对应的 JSON 文件。

📄 脚本源码

javascript 复制代码
js
复制编辑
// createSubPackageDirs.js
const fs = require('fs');
const path = require('path');

const pagesJsonPath = path.resolve(__dirname, 'pages.json');
const targetBaseDir = path.resolve(__dirname, 'subPackages_pages');

function readPagesJson() {
  try {
    const data = fs.readFileSync(pagesJsonPath, 'utf-8');
    return JSON.parse(data);
  } catch (err) {
    console.error('❌ 无法读取 pages.json:', err);
    process.exit(1);
  }
}

function createDirIfNotExists(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
    console.log(`✅ 已创建目录: ${dirPath}`);
  }
}

function writeJsonFile(filePath, data) {
  try {
    fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
    console.log(`✅ 写入成功: ${filePath}`);
  } catch (err) {
    console.error(`❌ 写入失败: ${filePath}`, err);
  }
}

function main() {
  createDirIfNotExists(targetBaseDir);
  const config = readPagesJson();
  const subPackages = config.subPackages || [];

  if (!subPackages.length) {
    console.log('⚠️ 未发现 subPackages 配置');
    return;
  }

  subPackages.forEach((pkg) => {
    if (pkg.root) {
      const fileName = path.basename(pkg.root) + '.json';
      const targetPath = path.join(targetBaseDir, fileName);
      writeJsonFile(targetPath, pkg);
    }
  });

  console.log('🎉 分包 JSON 提取完成!');
}

main();

🛠 脚本二:合并 JSON 文件回 pages.json

⚠️ 如果 pages.json 中已存在 subPackages 配置并包含部分分包内容,建议先执行 createSubPackageDirs.js 脚本,将现有分包配置导出为独立的 JSON 文件。

未执行导出脚本 ,在后续执行合并脚本时,subPackages_pages/ 目录中的 JSON 文件如果与现有 pages.json 中的某个 root 路径一致,将直接覆盖对应分包的配置内容,请谨慎操作以避免意外数据丢失。

✅ 脚本功能

  • 扫描 subPackages_pages/ 中的所有 .json 文件;
  • 校验 rootpages 字段;
  • 自动与已有 subPackages 做哈希比对,避免重复写入;
  • 更新并写入新的 pages.json 文件。

🔧 使用方法

复制代码
bash
复制编辑
node build-pages.js

📄 脚本源码

ini 复制代码
js
复制编辑
// build-pages.js
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

function getObjectHash(obj) {
  return crypto.createHash('md5').update(JSON.stringify(obj)).digest('hex');
}

const rootDir = path.resolve(__dirname);
const mainPagesPath = path.join(rootDir, 'pages.json');
const subPackagesDir = path.join(rootDir, 'subPackages_pages');

if (!fs.existsSync(mainPagesPath)) {
  console.error(`❌ pages.json 不存在: ${mainPagesPath}`);
  process.exit(1);
}

let mainConfig = {};
try {
  mainConfig = JSON.parse(fs.readFileSync(mainPagesPath, 'utf-8'));
} catch (e) {
  console.error('❌ 解析 pages.json 出错', e);
  process.exit(1);
}

const existingMap = new Map();
(mainConfig.subPackages || []).forEach(pkg => {
  if (pkg.root) {
    existingMap.set(pkg.root, {
      pkg,
      hash: getObjectHash(pkg)
    });
  }
});

const newSubPackages = [];

if (fs.existsSync(subPackagesDir)) {
  fs.readdirSync(subPackagesDir).forEach(file => {
    const fullPath = path.join(subPackagesDir, file);
    if (file.endsWith('.json')) {
      try {
        const pkg = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
        if (pkg.root && Array.isArray(pkg.pages)) {
          newSubPackages.push(pkg);
        }
      } catch (e) {
        console.warn(`⚠️ 解析失败: ${file}`, e);
      }
    }
  });
}

let changed = false;

newSubPackages.forEach(pkg => {
  const old = existingMap.get(pkg.root);
  const newHash = getObjectHash(pkg);
  if (!old || old.hash !== newHash) {
    existingMap.set(pkg.root, { pkg, hash: newHash });
    changed = true;
  }
});

if (changed) {
  const merged = Array.from(existingMap.values()).map(v => v.pkg);
  const updated = { ...mainConfig, subPackages: merged };
  try {
    fs.writeFileSync(mainPagesPath, JSON.stringify(updated, null, 2), 'utf8');
    console.log(`✅ 已更新 pages.json`);
  } catch (e) {
    console.error(`❌ 写入 pages.json 失败`, e);
  }
} else {
  console.log('✅ 分包未变化,无需写入');
}

⚙️ 集成 Vite 自动构建流程

将以下插件集成到你的 vite.config.js 中,可在打包时自动执行分包构建逻辑。

javascript 复制代码
js
复制编辑
// vite.config.js
import { defineConfig } from 'vite';
import { execSync } from 'child_process';
import uni from '@dcloudio/vite-plugin-uni';
import path from 'path';

export default defineConfig({
  plugins: [
    uni(),
    autoBuildPagesPlugin()
  ]
});

function autoBuildPagesPlugin() {
  return {
    name: 'auto-build-pages',
    apply: 'build',
    buildStart() {
      try {
        const scriptPath = path.resolve(__dirname, 'build-pages.js');
        execSync(`node "${scriptPath}"`, { stdio: 'inherit' });
        console.log('📦 pages.json 构建完成');
      } catch (error) {
        console.error('❌ 构建 pages.json 出错', error);
        throw error;
      }
    }
  };
}
相关推荐
passerby606140 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte3 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc