181 lines
6.1 KiB
JavaScript
181 lines
6.1 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* fix-wechat-miniapp.js
|
||
*
|
||
* 该脚本用于修复微信小程序的一些问题:
|
||
* 1. 将项目根目录下的 site.js 文件拷贝到 unpackage/dist/build/mp-weixin 目录下,如果文件存在则覆盖
|
||
* 2. 将 `import site from "../site.js";` 这段代码追加到
|
||
* unpackage/dist/build/mp-weixin/common/vendor.js 文件内容开头部分,
|
||
* 如果这个文件开头已经有了这行代码,则不追加
|
||
*
|
||
* 使用:
|
||
* node fix-wechat-miniapp.js
|
||
*
|
||
* 注意:
|
||
* - 在 Windows 上路径使用反斜杠也是可以的;脚本使用 path.join 来兼容不同平台。
|
||
* - 运行前请确认在项目根目录运行(site.js 在当前工作目录下)。
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const fsp = fs.promises;
|
||
const path = require('path');
|
||
|
||
const { exec } = require('child_process');
|
||
const { promisify } = require('util');
|
||
const execAsync = promisify(exec);
|
||
|
||
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);
|
||
|
||
// 复制 site.js 到目标目录(覆盖)
|
||
await fsp.copyFile(srcSitePath, destSitePath);
|
||
console.log(`已拷贝: ${srcSitePath} -> ${destSitePath}`);
|
||
|
||
// 2) 处理 vendor.js:在开头追加 import 语句(如果还没有的话)
|
||
const vendorExists = await exists(vendorPath);
|
||
if (!vendorExists) {
|
||
console.warn(`目标 vendor.js 不存在,跳过追加 import。路径: ${vendorPath}`);
|
||
return;
|
||
}
|
||
|
||
let vendorContent = await fsp.readFile(vendorPath, 'utf8');
|
||
|
||
const importLine = 'import site from "../site.js";';
|
||
// 检查文件开头(例如前 5 行或前 400 字符)是否已经包含该 import 语句
|
||
const inspectPrefix = vendorContent.slice(0, 400);
|
||
const importRegex = new RegExp(
|
||
// 匹配可能存在的引号或分号差异,但我们只需要确切匹配这行文字
|
||
'^\\s*import\\s+site\\s+from\\s+[\'"]\\.\\./site\\.js[\'"];?',
|
||
'm'
|
||
);
|
||
|
||
if (importRegex.test(inspectPrefix)) {
|
||
console.log('vendor.js 开头已包含 import site 语句,跳过追加。');
|
||
return;
|
||
}
|
||
|
||
// 如果文件以 shebang 或者注释开头,决定放在哪:通常我们把 import 放在文件最顶部(index 0)
|
||
// 但如果文件以 "use strict"; 等指令开头,import 必须在所有非-import/非-comment 语句之前。
|
||
// 简单实现:如果文件开头有 UTF BOM,保留它;然后把 importLine + 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 newContent = prefix + importLine + eol + vendorContent;
|
||
await fsp.writeFile(vendorPath, newContent, 'utf8');
|
||
console.log(`已在 vendor.js 开头追加: ${importLine}`);
|
||
} catch (err) {
|
||
console.error('发生错误:', err);
|
||
process.exitCode = 1;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 使用系统命令创建ZIP(跨平台)
|
||
* @param {string} sourceDir - 要压缩的目录路径
|
||
* @param {string} outputDir - 压缩文件输出目录
|
||
* @returns {Promise<string>} - 压缩文件的路径
|
||
*/
|
||
async function createZipWithSystemCommand(sourceDir, outputDir) {
|
||
// 检查源目录
|
||
if (!fs.existsSync(sourceDir)) {
|
||
throw new Error(`源目录不存在: ${sourceDir}`);
|
||
}
|
||
|
||
// 生成文件名
|
||
const dateString = new Date().toISOString().split('T')[0];
|
||
const zipFileName = `mp-weixin-${dateString}-${new Date().getTime()}.zip`;
|
||
const zipFilePath = path.join(outputDir, zipFileName);
|
||
|
||
let command;
|
||
|
||
// 根据操作系统选择命令
|
||
if (process.platform === 'win32') {
|
||
// Windows: 使用PowerShell的Compress-Archive
|
||
const sourcePath = sourceDir.replace(/'/g, "''");
|
||
const destPath = zipFilePath.replace(/'/g, "''");
|
||
command = `powershell -Command "Compress-Archive -Path '${sourcePath}\\*' -DestinationPath '${destPath}' -Force"`;
|
||
} else {
|
||
// Linux/Mac: 使用zip命令
|
||
const sourceBase = path.dirname(sourceDir);
|
||
const sourceName = path.basename(sourceDir);
|
||
command = `cd '${sourceBase}' && zip -r '${zipFilePath}' '${sourceName}' -x '*/node_modules/*' '*.git/*' '*.DS_Store' '*.log'`;
|
||
}
|
||
|
||
try {
|
||
console.log(`执行命令: ${command}`);
|
||
const { stdout, stderr } = await execAsync(command);
|
||
|
||
if (stderr) {
|
||
console.warn('警告:', stderr);
|
||
}
|
||
|
||
console.log(`✅ ZIP文件创建完成: ${zipFileName}`);
|
||
return zipFilePath;
|
||
} catch (error) {
|
||
throw new Error(`系统命令执行失败: ${error.message}`);
|
||
}
|
||
}
|
||
|
||
async function main() {
|
||
// 1) 打补丁
|
||
await commonPatch('production');
|
||
// await commonPatch('development');
|
||
|
||
// 2) 创建 ZIP 文件
|
||
const cwd = path.join(__dirname, '..');
|
||
const sourceDir = path.join(cwd, 'unpackage', 'dist', 'build', 'mp-weixin');
|
||
const destDir = path.join(cwd, 'unpackage', 'dist', 'build');
|
||
const zipFilePath = await createZipWithSystemCommand(sourceDir, destDir);
|
||
console.log(`ZIP 文件路径: ${zipFilePath}`);
|
||
}
|
||
|
||
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();
|
||
|
||
|