@error-monitor/sdk
Version:
Monitor SDK - 多平台前端监控SDK解决方案,支持自动环境检测,Web、Taro小程序一站式监控方案
455 lines (391 loc) • 12.8 kB
JavaScript
#!/usr/bin/env node
/**
* Taro小程序自动化配置工具
* 自动检测Taro项目并配置监控SDK和构建脚本
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
// 颜色输出
const colors = {
red: (text) => `\x1b[31m${text}\x1b[0m`,
green: (text) => `\x1b[32m${text}\x1b[0m`,
yellow: (text) => `\x1b[33m${text}\x1b[0m`,
blue: (text) => `\x1b[34m${text}\x1b[0m`,
cyan: (text) => `\x1b[36m${text}\x1b[0m`
};
// 日志函数
function logInfo(message) {
console.log(colors.blue('ℹ'), message);
}
function logSuccess(message) {
console.log(colors.green('✓'), message);
}
function logWarning(message) {
console.log(colors.yellow('⚠'), message);
}
function logError(message) {
console.log(colors.red('✗'), message);
}
// 检查文件是否存在
function fileExists(filePath) {
return fs.existsSync(filePath);
}
// 读取JSON文件
function readJsonFile(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
return JSON.parse(content);
} catch (error) {
return null;
}
}
// 写入JSON文件
function writeJsonFile(filePath, data) {
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
}
// 检测Taro项目
function detectTaroProject() {
logInfo('正在检测Taro项目...');
const packageJsonPath = path.join(process.cwd(), 'package.json');
if (!fileExists(packageJsonPath)) {
logError('未找到package.json文件');
return false;
}
const packageJson = readJsonFile(packageJsonPath);
if (!packageJson) {
logError('无法读取package.json文件');
return false;
}
const isTaroProject = packageJson.dependencies && (
packageJson.dependencies['@tarojs/taro'] ||
packageJson.dependencies['@tarojs/cli'] ||
packageJson.dependencies['@tarojs/components']
);
if (!isTaroProject) {
logError('当前目录不是Taro项目');
return false;
}
logSuccess('检测到Taro项目');
return true;
}
// 自动配置Taro构建
function configureTaroBuild() {
logInfo('正在配置Taro构建...');
const configDir = path.join(process.cwd(), 'config');
if (!fileExists(configDir)) {
fs.mkdirSync(configDir, { recursive: true });
}
// 检查并配置index.ts
const configIndexPath = path.join(configDir, 'index.ts');
if (!fileExists(configIndexPath)) {
const configContent = `import { defineConfig, type UserConfigExport } from '@tarojs/cli'
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'
import devConfig from './dev'
import prodConfig from './prod'
// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数
export default defineConfig<'webpack5'>(async (merge, { command, mode }) => {
const baseConfig: UserConfigExport<'webpack5'> = {
projectName: 'taroMini',
date: '${new Date().toISOString().split('T')[0]}',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
375: 2,
828: 1.81 / 2
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: [
"@tarojs/plugin-generator"
],
defineConstants: {
},
copy: {
patterns: [
],
options: {
}
},
framework: 'react',
compiler: 'webpack5',
cache: {
enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
},
mini: {
postcss: {
pxtransform: {
enable: true,
config: {
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
},
webpackChain(chain) {
chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)
// 为监控平台生成sourcemap
chain.devtool('source-map')
}
},
h5: {
publicPath: '/',
staticDirectory: 'static',
output: {
filename: 'js/[name].[hash:8].js',
chunkFilename: 'js/[name].[chunkhash:8].js'
},
miniCssExtractPluginOption: {
ignoreOrder: true,
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[name].[chunkhash].css'
},
postcss: {
autoprefixer: {
enable: true,
config: {}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
},
webpackChain(chain) {
chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)
}
},
rn: {
appName: 'taroDemo',
postcss: {
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
}
}
}
}
if (process.env.NODE_ENV === 'development') {
// 本地开发构建配置(不混淆压缩)
return merge({}, baseConfig, devConfig)
}
// 生产构建配置(默认开启压缩混淆等)
return merge({}, baseConfig, prodConfig)
})
`;
fs.writeFileSync(configIndexPath, configContent);
logSuccess('创建config/index.ts配置文件');
} else {
logWarning('config/index.ts已存在,跳过创建');
}
// 检查并配置dev.ts
const devConfigPath = path.join(configDir, 'dev.ts');
if (!fileExists(devConfigPath)) {
const devContent = `import type { UserConfigExport } from "@tarojs/cli"
export default {
logger: {
quiet: false,
stats: true
},
mini: {},
h5: {}
} satisfies UserConfigExport<'webpack5'>
`;
fs.writeFileSync(devConfigPath, devContent);
logSuccess('创建config/dev.ts配置文件');
}
// 检查并配置prod.ts
const prodConfigPath = path.join(configDir, 'prod.ts');
if (!fileExists(prodConfigPath)) {
const prodContent = `import type { UserConfigExport } from "@tarojs/cli"
export default {
mini: {},
h5: {
/**
* 启用sourcemap生成
*/
webpackChain(chain) {
chain.devtool('source-map')
}
}
} satisfies UserConfigExport<'webpack5'>
`;
fs.writeFileSync(prodConfigPath, prodContent);
logSuccess('创建config/prod.ts配置文件');
}
}
// 检查并更新配置文件中的sourcemap配置
function updateConfigForSourcemap() {
logInfo('正在检查配置文件中的sourcemap配置...');
const configIndexPath = path.join(process.cwd(), 'config/index.ts');
if (fileExists(configIndexPath)) {
let content = fs.readFileSync(configIndexPath, 'utf8');
// 检查是否已配置sourcemap
if (!content.includes('chain.devtool') && !content.includes('source-map')) {
// 在webpackChain函数中添加sourcemap配置
if (content.includes('webpackChain(chain)')) {
content = content.replace(
'webpackChain(chain) {',
'webpackChain(chain) {\n // 为监控平台生成sourcemap\n chain.devtool(\"source-map\")'
);
fs.writeFileSync(configIndexPath, content);
logSuccess('在config/index.ts中添加sourcemap配置');
}
} else {
logSuccess('config/index.ts中已配置sourcemap');
}
}
}
// 智能更新构建脚本配置
function updateBuildScriptConfiguration() {
logInfo('正在智能更新构建脚本配置...');
const buildScriptPath = path.join(process.cwd(), 'build-with-sourcemap.sh');
if (fileExists(buildScriptPath)) {
let content = fs.readFileSync(buildScriptPath, 'utf8');
// 更新项目ID和版本配置
if (content.includes('PROJECT_ID="taro-mini-app"')) {
// 获取当前项目的package.json信息
const packageJsonPath = path.join(process.cwd(), 'package.json');
if (fileExists(packageJsonPath)) {
const packageJson = readJsonFile(packageJsonPath);
if (packageJson) {
const projectName = packageJson.name || 'taro-mini-app';
const version = packageJson.version || '1.0.0';
content = content.replace(
'PROJECT_ID="taro-mini-app"',
`PROJECT_ID="${projectName}"`
);
content = content.replace(
'VERSION="1.0.0"',
`VERSION="${version}"`
);
fs.writeFileSync(buildScriptPath, content);
logSuccess('更新构建脚本中的项目配置');
}
}
}
}
}
// 自动配置构建脚本
function configureBuildScript() {
logInfo('正在配置构建脚本...');
const buildScriptPath = path.join(process.cwd(), 'build-with-sourcemap.sh');
if (!fileExists(buildScriptPath)) {
// 从SDK脚本目录复制构建脚本
const sdkScriptPath = path.join(__dirname, 'build-with-sourcemap.sh');
if (fileExists(sdkScriptPath)) {
const scriptContent = fs.readFileSync(sdkScriptPath, 'utf8');
fs.writeFileSync(buildScriptPath, scriptContent);
// 设置执行权限
fs.chmodSync(buildScriptPath, '755');
logSuccess('复制构建脚本并设置执行权限');
// 更新构建脚本配置
updateBuildScriptConfiguration();
} else {
logWarning('未找到SDK构建脚本,请手动配置');
}
} else {
logWarning('构建脚本已存在,进行智能更新');
updateBuildScriptConfiguration();
}
}
// 配置package.json脚本
function configurePackageScripts() {
logInfo('正在配置package.json脚本...');
const packageJsonPath = path.join(process.cwd(), 'package.json');
const packageJson = readJsonFile(packageJsonPath);
if (!packageJson) {
logError('无法读取package.json');
return;
}
if (!packageJson.scripts) {
packageJson.scripts = {};
}
// 添加监控构建脚本
if (!packageJson.scripts['build:monitor']) {
packageJson.scripts['build:monitor'] = './build-with-sourcemap.sh';
logSuccess('添加build:monitor脚本');
}
// 添加sourcemap构建脚本
if (!packageJson.scripts['build:sourcemap']) {
packageJson.scripts['build:sourcemap'] = 'npm run build:weapp';
logSuccess('添加build:sourcemap脚本');
}
writeJsonFile(packageJsonPath, packageJson);
}
// 安装监控SDK
function installMonitorSDK() {
logInfo('正在检查监控SDK依赖...');
const packageJsonPath = path.join(process.cwd(), 'package.json');
const packageJson = readJsonFile(packageJsonPath);
if (!packageJson) {
logError('无法读取package.json');
return;
}
const sdkDependency = '@monitor/sdk';
const hasSDK = packageJson.dependencies && packageJson.dependencies[sdkDependency];
if (!hasSDK) {
logWarning('未找到监控SDK依赖,请手动安装: npm install @monitor/sdk');
logWarning('如果包未发布,可以使用本地安装: npm install /path/to/monitor/sdk');
} else {
logSuccess('监控SDK依赖已配置');
}
}
// 主函数
function main() {
console.log(colors.cyan('🚀 Taro小程序自动化配置工具'));
console.log(colors.cyan('============================'));
console.log();
// 检测当前目录是否为Taro项目
if (!detectTaroProject()) {
process.exit(1);
}
try {
// 执行配置步骤
configureTaroBuild();
configureBuildScript();
configurePackageScripts();
installMonitorSDK();
// 智能更新现有配置
updateConfigForSourcemap();
console.log();
logSuccess('自动化配置完成!');
console.log();
console.log(colors.cyan('📋 下一步操作:'));
console.log('1. 安装监控SDK: npm install @monitor/sdk');
console.log('2. 在src/app.ts中引入监控SDK');
console.log('3. 运行构建: npm run build:monitor');
console.log('4. 上传生成的ZIP包到监控平台');
console.log();
console.log(colors.yellow('💡 本地开发提示:'));
console.log('如果 @monitor/sdk 尚未发布,可以使用:');
console.log('- 本地安装: npm install /path/to/monitor/sdk');
console.log('- 或者直接使用相对路径运行脚本');
console.log();
console.log(colors.cyan('💡 提示:'));
console.log('- 构建脚本: ./build-with-sourcemap.sh');
console.log('- 配置文件: config/index.ts, config/dev.ts, config/prod.ts');
console.log();
} catch (error) {
logError(`配置过程中发生错误: ${error.message}`);
process.exit(1);
}
}
// 执行主函数
if (require.main === module) {
main();
}
module.exports = {
detectTaroProject,
configureTaroBuild,
configureBuildScript,
configurePackageScripts,
installMonitorSDK
};