更改为es2020模块适应Cocos/laya引擎

This commit is contained in:
YHH
2025-06-09 10:42:19 +08:00
parent 35ca1dd7ea
commit ce64de5b3d
8 changed files with 1706 additions and 113 deletions

1108
source/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "@esengine/ecs-framework", "name": "@esengine/ecs-framework",
"version": "2.1.0", "version": "2.1.6",
"description": "用于Laya、Cocos等游戏引擎的高性能ECS框架", "description": "用于Laya、Cocos等游戏引擎的高性能ECS框架",
"main": "bin/index.js", "main": "bin/index.js",
"types": "bin/index.d.ts", "types": "bin/index.d.ts",
@@ -19,7 +19,7 @@
"egret" "egret"
], ],
"scripts": { "scripts": {
"clean": "rimraf bin wasm", "clean": "rimraf bin wasm dist",
"clean:wasm": "rimraf src/wasm/rust-ecs-core/pkg src/wasm/rust-ecs-core/target", "clean:wasm": "rimraf src/wasm/rust-ecs-core/pkg src/wasm/rust-ecs-core/target",
"build:wasm": "cd src/wasm/rust-ecs-core && wasm-pack build --target web --out-dir ../../../bin/wasm --release", "build:wasm": "cd src/wasm/rust-ecs-core && wasm-pack build --target web --out-dir ../../../bin/wasm --release",
"build:ts": "tsc", "build:ts": "tsc",
@@ -27,21 +27,27 @@
"build": "npm run build:wasm && npm run build:ts", "build": "npm run build:wasm && npm run build:ts",
"build:watch": "tsc --watch", "build:watch": "tsc --watch",
"rebuild": "npm run clean && npm run clean:wasm && npm run build", "rebuild": "npm run clean && npm run clean:wasm && npm run build",
"bundle": "npm run build && node scripts/bundle.js",
"compress": "npm run build && node scripts/compress.js",
"package": "npm run bundle && npm run compress",
"build:npm": "npm run build && node scripts/build-single.js",
"test:benchmark": "npm run build && node bin/Testing/Performance/benchmark.js", "test:benchmark": "npm run build && node bin/Testing/Performance/benchmark.js",
"test:unit": "npm run build && node bin/Testing/test-runner.js", "test:unit": "npm run build && node bin/Testing/test-runner.js",
"benchmark": "node scripts/benchmark.js", "benchmark": "node scripts/benchmark.js",
"preversion": "npm run rebuild", "preversion": "npm run rebuild",
"postversion": "npm publish", "publish:patch": "npm version patch && npm run build:npm && cd dist && npm publish",
"publish:patch": "npm version patch", "publish:minor": "npm version minor && npm run build:npm && cd dist && npm publish",
"publish:minor": "npm version minor", "publish:major": "npm version major && npm run build:npm && cd dist && npm publish",
"publish:major": "npm version major", "publish:npm": "npm run build:npm && cd dist && npm publish"
"publish": "npm publish"
}, },
"author": "yhh", "author": "yhh",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/node": "^20.19.0", "@types/node": "^20.19.0",
"archiver": "^7.0.1",
"esbuild": "^0.25.5",
"rimraf": "^5.0.0", "rimraf": "^5.0.0",
"terser": "^5.41.0",
"typescript": "^5.8.3" "typescript": "^5.8.3"
}, },
"publishConfig": { "publishConfig": {
@@ -50,6 +56,5 @@
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/esengine/ecs-framework.git" "url": "https://github.com/esengine/ecs-framework.git"
}, }
"optionalDependencies": {}
} }

View File

@@ -0,0 +1,279 @@
#!/usr/bin/env node
const esbuild = require('esbuild');
const fs = require('fs');
const path = require('path');
/**
* ECS Framework 单文件构建脚本
* 专门用于npm包发布的单文件版本
*/
const config = {
// 输入配置
entryPoint: './bin/index.js',
// 输出配置
outputDir: './dist',
outputFile: 'index.js',
// 压缩配置
minify: true,
sourcemap: true,
// 目标环境 - 适配更多平台
target: ['es2017'],
format: 'esm',
// npm包配置
generatePackageJson: true,
generateTypes: true
};
async function buildSingleFile() {
console.log('🚀 构建单文件npm包...');
try {
// 确保输出目录存在
if (!fs.existsSync(config.outputDir)) {
fs.mkdirSync(config.outputDir, { recursive: true });
}
// 第一步使用esbuild打包
console.log('📦 使用 esbuild 打包...');
const result = await esbuild.build({
entryPoints: [config.entryPoint],
bundle: true,
minify: config.minify,
sourcemap: config.sourcemap,
target: config.target,
format: config.format,
outfile: path.join(config.outputDir, config.outputFile),
platform: 'neutral', // 支持多平台
// 外部依赖
external: [],
// 定义全局变量
define: {
'process.env.NODE_ENV': '"production"'
},
// 元信息
metafile: true,
// 日志级别
logLevel: 'info',
// 保持类名(便于调试)
keepNames: true,
// 生成更兼容的代码
legalComments: 'none'
});
// 显示打包结果
if (result.metafile) {
const analysis = await esbuild.analyzeMetafile(result.metafile);
console.log('📊 打包分析:');
console.log(analysis);
}
// 第二步:生成类型定义文件
if (config.generateTypes) {
console.log('📝 生成类型定义文件...');
await generateTypeDefinitions();
}
// 第三步生成package.json
if (config.generatePackageJson) {
console.log('📋 生成package.json...');
await generatePackageJson();
}
// 第四步:复制必要文件
await copyEssentialFiles();
console.log('✅ 单文件构建完成!');
console.log(`📄 主文件: ${path.join(config.outputDir, config.outputFile)}`);
// 显示文件大小
const stats = fs.statSync(path.join(config.outputDir, config.outputFile));
console.log(`📏 文件大小: ${(stats.size / 1024).toFixed(2)} KB`);
console.log('\n🚀 发布到npm:');
console.log('cd dist && npm publish');
} catch (error) {
console.error('❌ 构建失败:', error);
process.exit(1);
}
}
/**
* 生成类型定义文件
*/
async function generateTypeDefinitions() {
const sourceTypesFile = './bin/index.d.ts';
const targetTypesFile = path.join(config.outputDir, 'index.d.ts');
if (fs.existsSync(sourceTypesFile)) {
// 读取原始类型定义
let typesContent = fs.readFileSync(sourceTypesFile, 'utf8');
// 处理相对路径导入,将其转换为绝对导入
typesContent = typesContent.replace(/from ['"]\.\//g, "from './");
typesContent = typesContent.replace(/from ['"]\.\.\//g, "from './");
// 添加版本信息注释
const header = `/**
* @esengine/ecs-framework
* 高性能ECS框架 - 适用于Cocos Creator和Laya引擎
* 版本: ${require('../package.json').version}
* 构建时间: ${new Date().toISOString()}
*/
`;
fs.writeFileSync(targetTypesFile, header + typesContent);
console.log(` ✓ 生成: ${targetTypesFile}`);
}
}
/**
* 生成npm包的package.json
*/
async function generatePackageJson() {
const sourcePackage = require('../package.json');
// 创建完全干净的package.json只包含发布必需的字段
const distPackage = {};
// 按顺序添加字段,确保没有任何开发相关字段
distPackage.name = sourcePackage.name;
distPackage.version = sourcePackage.version;
distPackage.description = sourcePackage.description;
distPackage.main = 'index.js';
distPackage.types = 'index.d.ts';
distPackage.module = 'index.js';
distPackage.type = 'module';
// 导出配置
distPackage.exports = {
".": {
"import": "./index.js",
"types": "./index.d.ts"
}
};
// 文件配置
distPackage.files = [
'index.js',
'index.js.map',
'index.d.ts',
'wasm/**/*',
'README.md',
'LICENSE'
];
// 关键词
distPackage.keywords = [
...sourcePackage.keywords,
'single-file',
'bundled',
'minified'
];
// 元信息
distPackage.author = sourcePackage.author;
distPackage.license = sourcePackage.license;
// Repository信息
distPackage.repository = {
type: 'git',
url: 'git+https://github.com/esengine/ecs-framework.git'
};
// 发布配置
distPackage.publishConfig = {
access: 'public'
};
// 引擎兼容性
distPackage.engines = {
node: '>=16.0.0'
};
const packagePath = path.join(config.outputDir, 'package.json');
fs.writeFileSync(packagePath, JSON.stringify(distPackage, null, 2));
console.log(` ✓ 生成: ${packagePath}`);
}
/**
* 复制必要文件
*/
async function copyEssentialFiles() {
console.log('📁 复制必要文件...');
const filesToCopy = [
{ src: '../README.md', dest: 'README.md' },
{ src: '../LICENSE', dest: 'LICENSE', optional: true }
];
for (const file of filesToCopy) {
const srcPath = path.resolve(file.src);
const destPath = path.join(config.outputDir, file.dest);
if (fs.existsSync(srcPath)) {
fs.copyFileSync(srcPath, destPath);
console.log(` ✓ 复制: ${file.dest}`);
} else if (!file.optional) {
console.warn(` ⚠️ 文件不存在: ${srcPath}`);
}
}
// 复制WASM文件
await copyWasmFiles();
}
/**
* 复制WASM文件
*/
async function copyWasmFiles() {
const wasmSrcDir = './bin/wasm';
const wasmDestDir = path.join(config.outputDir, 'wasm');
if (fs.existsSync(wasmSrcDir)) {
console.log('📦 复制WASM文件...');
// 创建目标目录
if (!fs.existsSync(wasmDestDir)) {
fs.mkdirSync(wasmDestDir, { recursive: true });
}
// 复制所有WASM相关文件
const wasmFiles = fs.readdirSync(wasmSrcDir);
for (const file of wasmFiles) {
// 排除.gitignore文件
if (file === '.gitignore') continue;
const srcPath = path.join(wasmSrcDir, file);
const destPath = path.join(wasmDestDir, file);
if (fs.statSync(srcPath).isFile()) {
fs.copyFileSync(srcPath, destPath);
console.log(` ✓ 复制WASM: ${file}`);
}
}
} else {
console.warn(' ⚠️ WASM目录不存在: ' + wasmSrcDir);
}
}
// 运行构建
if (require.main === module) {
buildSingleFile();
}
module.exports = { buildSingleFile, config };

210
source/scripts/bundle.js Normal file
View File

@@ -0,0 +1,210 @@
#!/usr/bin/env node
const esbuild = require('esbuild');
const fs = require('fs');
const path = require('path');
const { minify } = require('terser');
/**
* ECS Framework 打包脚本
* 将bin目录中的所有文件合并成一个压缩文件
*/
const config = {
// 输入配置
entryPoint: './bin/index.js',
// 输出配置
outputDir: './dist',
outputFile: 'ecs-framework.min.js',
// 压缩配置
minify: true,
sourcemap: true,
// 包含WASM文件
includeWasm: true,
// 目标环境
target: ['es2017'],
format: 'esm'
};
async function createBundle() {
console.log('🚀 开始打包 ECS Framework...');
try {
// 确保输出目录存在
if (!fs.existsSync(config.outputDir)) {
fs.mkdirSync(config.outputDir, { recursive: true });
}
// 第一步使用esbuild打包
console.log('📦 使用 esbuild 打包...');
const result = await esbuild.build({
entryPoints: [config.entryPoint],
bundle: true,
minify: config.minify,
sourcemap: config.sourcemap,
target: config.target,
format: config.format,
outfile: path.join(config.outputDir, config.outputFile),
platform: 'browser',
// 外部依赖(如果有的话)
external: [],
// 定义全局变量
define: {
'process.env.NODE_ENV': '"production"'
},
// 处理WASM文件
loader: {
'.wasm': 'binary'
},
// 插件配置
plugins: [
{
name: 'wasm-loader',
setup(build) {
// 处理WASM文件导入
build.onLoad({ filter: /\.wasm$/ }, async (args) => {
const wasmBuffer = await fs.promises.readFile(args.path);
const base64 = wasmBuffer.toString('base64');
return {
contents: `
const wasmBase64 = "${base64}";
const wasmBinary = Uint8Array.from(atob(wasmBase64), c => c.charCodeAt(0));
export default wasmBinary;
`,
loader: 'js'
};
});
}
}
],
// 元信息
metafile: true,
// 日志级别
logLevel: 'info'
});
// 显示打包结果
if (result.metafile) {
const analysis = await esbuild.analyzeMetafile(result.metafile);
console.log('📊 打包分析:');
console.log(analysis);
}
// 第二步复制WASM文件到dist目录
if (config.includeWasm) {
console.log('📁 复制 WASM 文件...');
await copyWasmFiles();
}
// 第三步:生成压缩包信息
await generateBundleInfo();
console.log('✅ 打包完成!');
console.log(`📄 输出文件: ${path.join(config.outputDir, config.outputFile)}`);
// 显示文件大小
const stats = fs.statSync(path.join(config.outputDir, config.outputFile));
console.log(`📏 文件大小: ${(stats.size / 1024).toFixed(2)} KB`);
} catch (error) {
console.error('❌ 打包失败:', error);
process.exit(1);
}
}
/**
* 复制WASM文件到dist目录
*/
async function copyWasmFiles() {
const wasmDir = './bin/wasm';
const distWasmDir = path.join(config.outputDir, 'wasm');
if (fs.existsSync(wasmDir)) {
if (!fs.existsSync(distWasmDir)) {
fs.mkdirSync(distWasmDir, { recursive: true });
}
const wasmFiles = fs.readdirSync(wasmDir);
for (const file of wasmFiles) {
// 排除 .gitignore 文件
if (file === '.gitignore') {
console.log(` ⏭️ 跳过: ${file}`);
continue;
}
const srcPath = path.join(wasmDir, file);
const destPath = path.join(distWasmDir, file);
if (fs.statSync(srcPath).isFile()) {
fs.copyFileSync(srcPath, destPath);
console.log(` ✓ 复制: ${file}`);
}
}
}
}
/**
* 生成打包信息文件
*/
async function generateBundleInfo() {
const bundleInfo = {
name: '@esengine/ecs-framework',
version: require('../package.json').version,
buildTime: new Date().toISOString(),
files: {
main: config.outputFile,
sourcemap: config.outputFile + '.map',
wasm: 'wasm/'
},
target: config.target,
format: config.format,
minified: config.minify,
size: {
main: fs.statSync(path.join(config.outputDir, config.outputFile)).size,
wasm: getWasmSize()
}
};
const infoPath = path.join(config.outputDir, 'bundle-info.json');
fs.writeFileSync(infoPath, JSON.stringify(bundleInfo, null, 2));
console.log(`📋 生成打包信息: ${infoPath}`);
}
/**
* 获取WASM文件总大小
*/
function getWasmSize() {
const wasmDir = path.join(config.outputDir, 'wasm');
let totalSize = 0;
if (fs.existsSync(wasmDir)) {
const files = fs.readdirSync(wasmDir);
for (const file of files) {
const filePath = path.join(wasmDir, file);
if (fs.statSync(filePath).isFile()) {
totalSize += fs.statSync(filePath).size;
}
}
}
return totalSize;
}
// 运行打包
if (require.main === module) {
createBundle();
}
module.exports = { createBundle, config };

165
source/scripts/compress.js Normal file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const archiver = require('archiver');
/**
* ECS Framework 压缩脚本
* 将bin目录压缩成ZIP文件
*/
const config = {
sourceDir: './bin',
outputDir: './dist',
outputFile: 'ecs-framework-bin.zip',
compressionLevel: 9, // 最高压缩级别
includeSourceMaps: false // 是否包含source map文件
};
async function createCompressedArchive() {
console.log('🗜️ 开始压缩 bin 目录...');
try {
// 确保输出目录存在
if (!fs.existsSync(config.outputDir)) {
fs.mkdirSync(config.outputDir, { recursive: true });
}
const outputPath = path.join(config.outputDir, config.outputFile);
const output = fs.createWriteStream(outputPath);
const archive = archiver('zip', {
zlib: { level: config.compressionLevel }
});
// 监听事件
output.on('close', () => {
const sizeKB = (archive.pointer() / 1024).toFixed(2);
console.log('✅ 压缩完成!');
console.log(`📄 输出文件: ${outputPath}`);
console.log(`📏 压缩后大小: ${sizeKB} KB`);
console.log(`📊 压缩了 ${archive.pointer()} 字节`);
// 生成压缩信息
generateCompressionInfo(outputPath, archive.pointer());
});
output.on('end', () => {
console.log('数据已全部写入');
});
archive.on('warning', (err) => {
if (err.code === 'ENOENT') {
console.warn('⚠️ 警告:', err);
} else {
throw err;
}
});
archive.on('error', (err) => {
throw err;
});
// 连接输出流
archive.pipe(output);
// 添加bin目录中的所有文件
console.log('📁 添加文件到压缩包...');
// 递归添加目录
archive.directory(config.sourceDir, false, (entry) => {
// 过滤文件
if (!config.includeSourceMaps && entry.name.endsWith('.map')) {
console.log(` ⏭️ 跳过: ${entry.name}`);
return false;
}
// 排除 .gitignore 文件
if (entry.name === '.gitignore' || entry.name.endsWith('/.gitignore')) {
console.log(` ⏭️ 跳过: ${entry.name}`);
return false;
}
console.log(` ✓ 添加: ${entry.name}`);
return entry;
});
// 完成压缩
await archive.finalize();
} catch (error) {
console.error('❌ 压缩失败:', error);
process.exit(1);
}
}
/**
* 生成压缩信息文件
*/
function generateCompressionInfo(outputPath, compressedSize) {
const originalSize = getDirectorySize(config.sourceDir);
const compressionRatio = ((originalSize - compressedSize) / originalSize * 100).toFixed(2);
const compressionInfo = {
name: '@esengine/ecs-framework',
version: require('../package.json').version,
compressionTime: new Date().toISOString(),
files: {
archive: config.outputFile
},
size: {
original: originalSize,
compressed: compressedSize,
ratio: `${compressionRatio}%`
},
settings: {
compressionLevel: config.compressionLevel,
includeSourceMaps: config.includeSourceMaps
}
};
const infoPath = path.join(config.outputDir, 'compression-info.json');
fs.writeFileSync(infoPath, JSON.stringify(compressionInfo, null, 2));
console.log(`📋 生成压缩信息: ${infoPath}`);
console.log(`📈 压缩率: ${compressionRatio}%`);
}
/**
* 获取目录总大小
*/
function getDirectorySize(dirPath) {
let totalSize = 0;
function calculateSize(currentPath) {
const stats = fs.statSync(currentPath);
if (stats.isDirectory()) {
const files = fs.readdirSync(currentPath);
for (const file of files) {
calculateSize(path.join(currentPath, file));
}
} else {
// 过滤source map文件
if (!config.includeSourceMaps && currentPath.endsWith('.map')) {
return;
}
// 排除 .gitignore 文件
if (currentPath.endsWith('.gitignore')) {
return;
}
totalSize += stats.size;
}
}
calculateSize(dirPath);
return totalSize;
}
// 运行压缩
if (require.main === module) {
createCompressedArchive();
}
module.exports = { createCompressedArchive, config };

View File

@@ -8,10 +8,8 @@ export * from './Emitter';
export * from './GlobalManager'; export * from './GlobalManager';
export * from './PerformanceMonitor'; export * from './PerformanceMonitor';
export { Time } from './Time'; export { Time } from './Time';
/**
* WebAssembly核心模块 // WebAssembly核心模块
* 提供高性能的ECS查询和计算功能
*/
export { export {
WasmEcsCore, WasmEcsCore,
ecsCore, ecsCore,
@@ -20,5 +18,5 @@ export {
EntityId, EntityId,
ComponentMask, ComponentMask,
QueryResult, QueryResult,
PerformanceStats PerformanceStats as WasmPerformanceStats
} from './WasmCore'; } from './WasmCore';

View File

@@ -17,21 +17,6 @@ export { Timer } from './Utils/Timers/Timer';
// ECS核心组件 // ECS核心组件
export * from './ECS'; export * from './ECS';
// 工具类 // 工具类和类型定义
export * from './Utils/Pool'; export * from './Utils';
export * from './Utils/PerformanceMonitor';
export * from './Utils/Extensions';
// WebAssembly核心模块
export {
WasmEcsCore,
ecsCore,
initializeEcs,
Query,
EntityId,
ComponentMask,
QueryResult
} from './Utils/WasmCore';
// 类型定义
export * from './Types'; export * from './Types';

View File

@@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ES2020",
"module": "CommonJS", "module": "ES2020",
"moduleResolution": "node", "moduleResolution": "node",
"lib": ["ES2020", "DOM"], "lib": ["ES2020", "DOM"],
"outDir": "./bin", "outDir": "./bin",
@@ -27,7 +27,10 @@
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"importHelpers": false, "importHelpers": false,
"downlevelIteration": true "downlevelIteration": true,
"isolatedModules": false,
"allowJs": true,
"resolveJsonModule": true
}, },
"include": [ "include": [
"src/**/*" "src/**/*"