vite-plugin-uni-pages 有提供一个钩子方法onBeforeWriteFile,此方法在生成 pages.json 之前调用
我们可以在此方法里面访问 uni-pages 插件的上下文,可以看到, pages.json 是通过pagesGlobConfig 和 pageMetaData 和 subPageMetaData 合并生成
在我的 微信小程序 『轻便万物迹』中,分包里面有两个文件夹,现在我不想打包 storage/index 这个页面, 于是我在 route 定义中添加了一个字段 __enable, 用来表示我不想打包此文件, 可以看到, 打包的时候有输出此自定义字段。于是我们可以在读到有此字段的时候,将该对象进行移除,这样,打包后的pages.json 就不会出现此页面。
onBeforeWriteFile(ctx) {
console.log(ctx.pageMetaData);
console.log(ctx.subPageMetaData);
ctx.subPageMetaData.forEach((item) = >{
const newPages = item.pages.filter((route) = >route.__enable === false);
item.pages = newPages;
});
}
可以看到, 构建产物中不包含有__enable: false 字段的页面。
如何控制不同平台的打包
同理, 我们只需要在页面的route对象中声明哪些平台打包,哪些平台不打包,然后通过 UNI_PLATFORM 获取当前正在打包平台名,进行页面过滤。如下图,此时设置了storage/index 这个页面不进行打包(微信平台 mp-weixin),构建产物也不会包含 storage/index 这个页面
const { UNI_PLATFORM } = process.env;
console.log('UNI_PLATFORM -> ', UNI_PLATFORM); // 得到 mp-weixin, h5, app 等
如何直接生成完整的pages.json, 但是在pages.json 里面进行条件编译
可以通过json转js然后添加注释实现
vite-plugin-uni-page 还有一个钩子函数,onBeforeWriteFile 可以在生成pages.json 进行操作。
const parser = require('@babel/parser');
const t = require('@babel/types');
const fs = require('fs')
const path = require('path')
const generate = require('@babel/generator').default;
// 读取 JSON 文件
const jsonFilePath = path.resolve(__dirname, './pages.json');
const jsonContent = fs.readFileSync(jsonFilePath, 'utf-8');
// 解析为 JavaScript 对象
const ast = t.file( t.program([ t.variableDeclaration('const', [ t.variableDeclarator( t.identifier('data'), t.valueToNode(jsonObj) ) ]) ]) );
// 转换 AST
traverse(ast, {
ObjectExpression(path) {
// console.log(path.node.properties)
const hasComment = path.node.properties.some(
prop =>
prop.key.value === '__comment'
);
if (hasComment) {
console.log('有注释')
// 获取父路径的起始和结束位置
const parentPath = path.parentPath;
// 在前一个token后添加 #ifdef
path.addComment('leading', '#ifdef A');
// 在后一个token前添加 #endif
if (t.isVariableDeclarator(parentPath)) {
parentPath.addComment('trailing', '#endif');
} else {
path.addComment('trailing', '#endif');
}
// 可选:移除 __comment 属性
path.node.properties = path.node.properties.filter(
prop => !(t.isObjectProperty(prop) &&
t.isIdentifier(prop.key) &&
prop.key.name === '__comment')
);
}
}
});
// 生成代码
const output = generator(ast, {
comments: true, // 确保保留注释
retainLines: true,
concise: false
});
然后将生成的代码转成json
// 解析代码
const ast = parser.parse(code, {
sourceType: 'module',
attachComment: true, // 保留注释
});
// 提取对象
const userObject = ast.program.body[0].declarations[0].init;
// 生成 JSON5
const json5 = generate(userObject, {
comments: true, // 保留注释
jsonCompatibleStrings: true, // 使用双引号
concise: false, // 格式化输出
}).code;
// 移除 const code = 和分号
const cleanedJson5 = json5
.replace(/^const\s+\w+\s*=\s*/, '') // 移除 const code =
.replace(/;\s*$/, ''); // 移除末尾分号
// 确保键和字符串值都使用双引号
const finalJson5 = cleanedJson5
.replace(/(\b\w+\b)(?=\s*:)/g, '"$1"') // 确保键带双引号
.replace(/'([^']*)'/g, '"$1"'); // 将单引号字符串替换为双引号
console.log(finalJson5);