Files
lucky_shop/scripts/mp-weixin.patch.js

202 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* fix-wechat-miniapp.js
*
* 该脚本用于修复微信小程序的一些问题:
* 1. 将项目根目录下的 site.js 文件拷贝到 unpackage/dist/build/mp-weixin 目录下,如果文件存在则覆盖
* 2. 将 project.config.json 及 project.private.config.json 拷贝到目标目录
* 3. 生成 version.js(CommonJS 模块)和 version.json 到目标目录
* 4. 将 `const site = require("../site");` 和 `const __app_version = require("../version");`
* 追加到 unpackage/dist/build/mp-weixin/common/vendor.js 文件内容开头部分,
* 如果文件开头已有则跳过
*
* 使用:
* node fix-wechat-miniapp.js # 打补丁并创建 ZIP 文件(默认 mode=production)
* node fix-wechat-miniapp.js --no-zip # 只打补丁,不创建 ZIP 文件
* node fix-wechat-miniapp.js --mode development # 使用 development 模式打补丁
* node fix-wechat-miniapp.js --mode production # 使用 production 模式打补丁(默认)
*
* 注意:
* - 在 Windows 上路径使用反斜杠也是可以的;脚本使用 path.join 来兼容不同平台。
* - 运行前请确认在项目根目录运行(site.js 在当前工作目录下)。
*/
const fs = require('fs');
const fsp = fs.promises;
const path = require('path');
const { execSync } = require('child_process');
const { openFileDirectory } = require('./open-directory');
const { createZipWithSystemCommand } = require('./create-zip');
async function commonPatch(mode = 'production') {
try {
// 根据当前脚本所在目录(scripts),定位到项目根目录
const cwd = path.join(__dirname, '..');
const srcSitePath = path.join(cwd, 'site.js');
const destDir = path.join(cwd, 'unpackage', 'dist', mode === 'production' ? 'build' : 'dev', 'mp-weixin');
const destSitePath = path.join(destDir, 'site.js');
const vendorPath = path.join(destDir, 'common', 'vendor.js');
// 1) 检查源文件是否存在
const srcExists = await exists(srcSitePath);
if (!srcExists) {
console.error(`源文件不存在: ${srcSitePath}`);
process.exitCode = 2;
return;
}
// 确保目标目录存在
await ensureDir(destDir);
// 复制 project.config.json 及 project.private.config.json 文件到 destDir 下面
const configFiles = ['project.config.json', 'project.private.config.json'];
for (const fileName of configFiles) {
const srcPath = path.join(cwd, fileName);
const destPath = path.join(destDir, fileName);
// 检查源文件是否存在
const fileExists = await exists(srcPath);
if (fileExists) {
await fsp.copyFile(srcPath, destPath);
console.log(`已拷贝: ${srcPath} -> ${destPath}`);
} else {
console.warn(`源文件不存在,跳过复制: ${srcPath}`);
}
}
// 复制 site.js 到目标目录(覆盖)
await fsp.copyFile(srcSitePath, destSitePath);
console.log(`已拷贝: ${srcSitePath} -> ${destSitePath}`);
// 3) 生成 version.js(包含 Git 提交 ID 和构建时间,CommonJS 格式供 require 使用)
let commitId = 'unknown';
try {
commitId = execSync('git rev-parse --short HEAD', { cwd }).toString().trim();
} catch (e) {
console.warn('无法获取 Git 提交 ID,使用 unknown 代替');
}
const versionData = {
commitId,
buildTime: new Date().toISOString()
};
// 同时生成 version.js(供 require)和 version.json(供文件系统读取)
const versionJsPath = path.join(destDir, 'version.js');
await fsp.writeFile(versionJsPath, `module.exports = ${JSON.stringify(versionData, null, 2)};\n`);
console.log(`已生成: ${versionJsPath} (commitId: ${commitId})`);
const versionJsonPath = path.join(destDir, 'version.json');
await fsp.writeFile(versionJsonPath, JSON.stringify(versionData, null, 2));
console.log(`已生成: ${versionJsonPath} (commitId: ${commitId})`);
// 4) 处理 vendor.js:在开头追加 require 语句(如果还没有的话)
const vendorExists = await exists(vendorPath);
if (!vendorExists) {
console.warn(`⚠ 目标 vendor.js 不存在,跳过追加 require。路径: ${vendorPath}`);
console.warn(' → 请先执行 HBuilder 构建(uniapp 构建),产生 vendor.js 后再运行此脚本。');
console.warn(' → version.json/version.js 已生成,可在首页连击 5 次标题查看版本信息。');
return;
}
let vendorContent = await fsp.readFile(vendorPath, 'utf8');
const requireLine = 'const site = require("../site");';
const versionLine = 'const __app_version = require("../version");';
// 检查文件开头(例如前 1000 字符)是否已经包含这些 require 语句
const inspectPrefix = vendorContent.slice(0, 1000);
const hasSiteRequire = new RegExp(
'^\\s*const\\s+site\\s*=\\s*require\\s*\\([\'"]\\.\\./site[\'"]\\);?',
'm'
).test(inspectPrefix);
const hasVersionRequire = new RegExp(
'^\\s*const\\s+__app_version\\s*=\\s*require\\s*\\([\'"]\\.\\./version[\'"]\\);?',
'm'
).test(inspectPrefix);
if (hasSiteRequire && hasVersionRequire) {
console.log('vendor.js 开头已包含 require 语句,跳过追加。');
return;
}
// 把 require 语句 + newline 插入文件最前面。
// 保留原始换行风格(若可能)
const eol = vendorContent.includes('\r\n') ? '\r\n' : '\n';
let prefix = '';
// 保留可能的 BOM
if (vendorContent.charCodeAt(0) === 0xfeff) {
prefix = '\uFEFF';
vendorContent = vendorContent.slice(1);
}
const linesToInject = [requireLine];
if (!hasVersionRequire) {
linesToInject.push(versionLine);
}
const newContent = prefix + linesToInject.join(eol) + eol + vendorContent;
await fsp.writeFile(vendorPath, newContent, 'utf8');
console.log(`已在 vendor.js 开头追加: ${linesToInject.join(', ')}`);
} catch (err) {
console.error('发生错误:', err);
process.exitCode = 1;
}
}
async function main() {
// 解析命令行参数
const argv = process.argv.slice(2);
const options = {
noZip: argv.includes('--no-zip'),
mode: 'production' // 默认值
};
// 解析 --mode 参数
const modeIndex = argv.indexOf('--mode');
if (modeIndex !== -1 && modeIndex + 1 < argv.length) {
options.mode = argv[modeIndex + 1];
}
// 1) 打补丁
await commonPatch(options.mode);
// await commonPatch('development');
// 2) 创建 ZIP 文件(如果未指定 --no-zip)
if (!options.noZip) {
const cwd = path.join(__dirname, '..');
const buildDir = options.mode === 'production' ? 'build' : 'dev';
const sourceDir = path.join(cwd, 'unpackage', 'dist', buildDir, 'mp-weixin');
const destDir = path.join(cwd, 'unpackage', 'dist', buildDir);
const zipFilePath = await createZipWithSystemCommand(sourceDir, destDir);
console.log(`ZIP 文件路径: ${zipFilePath}`);
// 3) 自动打开zip所在的目录
await openFileDirectory(zipFilePath);
} else {
console.log('跳过创建 ZIP 文件和打开目录');
}
}
async function exists(p) {
try {
await fsp.access(p, fs.constants.F_OK);
return true;
} catch (e) {
return false;
}
}
async function ensureDir(dirPath) {
try {
await fsp.mkdir(dirPath, { recursive: true });
} catch (e) {
// ignore if exists
if (e.code !== 'EEXIST') throw e;
}
}
main();