将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;
      }
    }
  };
}
相关推荐
归于尽3 分钟前
为什么你的 React 项目越改越乱?这 3 个配置细节藏着答案
前端·react.js
JiaLin_Denny20 分钟前
javascript 中数组对象操作方法
前端·javascript·数组对象方法·数组对象判断和比较
代码老y22 分钟前
Vue3 从 0 到 ∞:Composition API 的底层哲学、渲染管线与生态演进全景
前端·javascript·vue.js
LaoZhangAI30 分钟前
ComfyUI集成GPT-Image-1完全指南:8步实现AI图像创作革命【2025最新】
前端·后端
LaoZhangAI31 分钟前
Cline + Gemini API 完整配置与使用指南【2025最新】
前端·后端
whhhhhhhhhw32 分钟前
Node.js链接MySql
node.js
Java&Develop36 分钟前
防止电脑息屏 html
前端·javascript·html
Maybyy39 分钟前
javaScript中数组常用的函数方法
开发语言·前端·javascript
国王不在家40 分钟前
组件-多行文本省略-展开收起
前端·javascript·html