将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;
      }
    }
  };
}
相关推荐
wgod1 分钟前
new AbortController()
前端
UXbot8 分钟前
UXbot 是什么?一句指令生成完整应用的 AI 工具
前端·ai·交互·个人开发·ai编程·原型模式·ux
棒棒的唐23 分钟前
WSL2用npm安装的openclaw,无法正常使用openclaw gateway start启动服务的问题
前端·npm·gateway
吴声子夜歌30 分钟前
Node.js——操作MySQL数据库
数据库·mysql·node.js
哔哩哔哩技术31 分钟前
使用Compose Navigation3进行屏幕适配
前端
咬人喵喵1 小时前
E2.COOL 平台深度解析:从特效分类到实战操作指南
前端·编辑器·svg
RisunJan2 小时前
Linux命令-named-checkzone
linux·前端
小陈工2 小时前
Python Web开发入门(十):数据库迁移与版本管理——让数据库变更可控可回滚
前端·数据库·人工智能·python·sql·云原生·架构
吹晚风吧2 小时前
解决vite打包,base配置前缀,nginx的dist包找不到资源
服务器·前端·nginx
weixin199701080163 小时前
《施耐德商品详情页前端性能优化实战》
前端·性能优化