node程序打包成.exe,为什么无法脱离node独立运行,.exe必须和node_modules放在同级目录并且电脑要有node环境才能运行,如何解决?
我需要将3d-tiles-tools增加批处理功能,并且将装个项目打包成.exe,双击.exe要运行optimizeB3dm.cjs(代码如下)
//optimizeB3dm.cjs
// import { spawn } from 'child_process';
// import fs from 'fs';
// import path from 'path';
// import async from 'async';
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const async = require('async');
// 获取当前执行目录,即虚拟文件系统根目录
const baseDir = path.dirname(process.execPath);
// 输入和输出目录
const rootDir = path.join(baseDir, 'specs/MyData');
const outputDir = path.join(baseDir, 'output');
// 如果输出根目录不存在,则创建它
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// 创建一个限制并发执行数量的队列
const queue = async.queue((fileData, callback) => {
const { inputFilePath, outputFilePath, isJson } = fileData;
if (isJson) {
// 如果是 JSON 文件,直接复制
fs.copyFile(inputFilePath, outputFilePath, (err) => {
if (err) {
console.error(`复制 JSON 文件失败 ${inputFilePath}: ${err.message}`);
} else {
console.log(`复制成功 ${inputFilePath}`);
}
callback();
});
} else {
// 如果不是 JSON 文件,则执行压缩
const command = path.join(baseDir, 'node_modules/.bin/3d-tiles-tools');
const args = [
'optimizeB3dm',
'-i', path.resolve(inputFilePath),
'-o', path.resolve(outputFilePath),
'--options',
'--draco.compressMeshes',
'--draco.compressionLevel=10'
];
const proc = spawn(command, args, { shell: true });
let dracoError = false;
proc.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
proc.stderr.on('data', (data) => {
const errorMessage = data.toString();
console.error(`stderr: ${errorMessage}`);
if (errorMessage.includes("Draco encoding failed")) {
dracoError = true;
}
});
proc.on('error', (err) => {
console.error(`Error processing ${inputFilePath}: ${err.message}`);
callback(err);
});
proc.on('close', (code) => {
if (dracoError) {
console.log(`文件 ${inputFilePath} 不可被压缩。`);
} else if (code !== 0) {
console.error(`压缩失败 ${inputFilePath}`);
} else {
console.log(`压缩成功 ${inputFilePath}`);
}
callback();
});
}
}, 5); // 并发处理 5 个文件
// 递归遍历目录
function processDirectory(directory) {
fs.readdir(directory, (err, files) => {
if (err) throw err;
files.forEach(file => {
const fullPath = path.join(directory, file);
fs.stat(fullPath, (err, stats) => {
if (err) throw err;
if (stats.isDirectory()) {
// 递归处理子目录
processDirectory(fullPath);
} else {
const inputFilePath = fullPath;
const relativePath = path.relative(rootDir, fullPath);
const outputFilePath = path.join(outputDir, relativePath);
// 确保输出目录存在
const outputFileDir = path.dirname(outputFilePath);
if (!fs.existsSync(outputFileDir)) {
fs.mkdirSync(outputFileDir, { recursive: true });
}
if (path.extname(file) === '.json') {
// 如果是 .json 文件,直接复制
queue.push({ inputFilePath, outputFilePath, isJson: true });
} else if (path.extname(file) === '.b3dm') {
// 如果是 .b3dm 文件,添加到队列进行压缩
queue.push({ inputFilePath, outputFilePath, isJson: false });
}
}
});
});
});
}
// 开始处理
processDirectory(rootDir);
// 当队列中的任务完成时,打印完成消息
queue.drain(() => {
console.log('全部文件处理完毕');
});
我的package.json
{
"name": "3d-tiles-tools",
"version": "0.4.2",
"license": "Apache-2.0",
"description": "3D Tiles tools",
"author": {
"name": "Cesium GS, Inc. and Contributors"
},
"type": "module",
"source": "./src/index.ts",
"exports": "./build/src/index.js",
"types": "./build/src/index.d.ts",
"bin": "./scripts/optimizeB3dm.cjs",
"pkg": {
"assets": [
"node_modules/**/*",
"scripts/optimizeB3dm.cjs",
"src/**/*",
"node_modules/.bin/3d-tiles-tools"
],
"targets": [
"node18-win-x64"
],
"scripts": [
"scripts/optimizeB3dm.cjs"
]
},
"keywords": [
"3D Tiles"
],
"homepage": "https://github.com/CesiumGS/3d-tiles-tools",
"repository": {
"type": "git",
"url": "https://github.com/CesiumGS/3d-tiles-tools.git"
},
"bugs": {
"url": "https://github.com/CesiumGS/3d-tiles-tools/issues"
},
"engines": {
"node": ">=16.0.0"
},
"dependencies": {
"@gltf-transform/core": "^3.9.0",
"@gltf-transform/extensions": "^3.9.0",
"@gltf-transform/functions": "^3.9.0",
"3d-tiles-tools": "^0.4.2",
"archiver": "^5.3.1",
"async": "^3.2.6",
"better-sqlite3": "^8.0.1",
"cesium": "^1.103.0",
"draco3d": "^1.5.6",
"draco3dgltf": "^1.5.6",
"gltf-pipeline": "^4.1.0",
"gltfpack": "^0.19.1",
"meshoptimizer": "^0.19.0",
"minimist": "^1.2.7",
"node-stream-zip": "^1.15.0",
"pino": "^8.15.0",
"pino-pretty": "^10.2.0",
"seedrandom": "^3.0.5",
"sharp": "^0.32.1",
"yargs": "^17.5.1"
},
"devDependencies": {
"@microsoft/api-documenter": "^7.19.24",
"@microsoft/api-extractor": "^7.33.6",
"@types/jasmine": "^4.0.3",
"@types/yargs": "^17.0.22",
"@typescript-eslint/eslint-plugin": "^5.38.0",
"@typescript-eslint/parser": "^5.38.0",
"@vercel/ncc": "^0.38.1",
"c8": "^8.0.1",
"del-cli": "^5.0.0",
"eslint": "^8.23.1",
"eslint-config-cesium": "^9.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-node": "^11.1.0",
"glob": "^10.3.10",
"jasmine": "^4.3.0",
"mkdirp": "^1.0.4",
"nyc": "^15.1.0",
"prettier": "2.7.1",
"ts-node": "^10.9.1",
"typescript": "^4.8.3"
},
"scripts": {
"start": "node scripts/optimizeB3dm.cjs",
"about:start": "echo 'Start the tools, as a TypeScript command line application'",
"about:eslint": "echo 'Perform linting of the source code. This may modify the source files.'",
"about:build": "echo 'Run the TypeScript compiler to generate the build output.'",
"about:build-post": "echo 'Perform any post-build steps'",
"about:test": "echo 'Execute the unit tests'",
"about:coverage": "echo 'Compute the test coverage'",
"about:prettier-check": "echo 'Check the formatting of the source code (without fixing formatting errors).'",
"about:prettier": "echo 'Ensure the right formatting of the source code, automatically fixing formatting errors.'",
"about:generate-third-party": "echo 'Update the ThirdParty.json file with the most recent dependency versions'",
"about:docs-prepare-directory": "echo 'Prepare the output directory for the API definition file'",
"about:docs-extract-api": "echo 'Extract the API definition file from the current build output.'",
"about:docs-generate-markdown": "echo 'Generate the API documentation based on the API definition file'",
"about:docs-generate": "echo 'Generate the API documentation based on the current build output'",
"about:docs": "echo 'Perform a build and generate the API documentation based on the build output'",
"about:package-clean": "echo 'Delete the contents of the 'build' output folder'",
"about:package-prepare": "echo 'Prepare a package: Linting, formatting, build, test, documentation, and third-party information updates'",
"about:package": "echo 'Prepare a package that can then be published on NPM'",
"eslint": "eslint \"./**/*.ts\" --cache",
"build": "tsc --build --verbose --force && npm run build-post",
"build-post": "npm run build-post-ktx && npm run build-post-cli",
"build-post-ktx": "npx copyfiles --flat ./src/ktx/ktx/external/basis_encoder.* ./build/src/ktx/ktx/external",
"build-post-cli": "npx copyfiles --flat ./bin/cli.mjs ./build/src",
"test": "npx ts-node node_modules/jasmine/bin/jasmine.js --config=specs/jasmine.json",
"coverage": "npx c8 --clean npm run test",
"prettier-check": "prettier --check \"**/*\"",
"prettier": "prettier --write \"**/*\"",
"generate-third-party": "node generateThirdParty.js",
"docs-prepare-directory": "mkdirp etc",
"docs-extract-api": "api-extractor run --config api-extractor.jsonc --local --verbose",
"docs-generate-markdown": "api-documenter markdown -i build/api-extractor -o build/docs",
"docs-generate": "npm run docs-prepare-directory && npm run docs-extract-api && npm run docs-generate-markdown",
"docs": "npm run build && npm run docs-generate",
"package-clean": "del-cli ./build/** del-cli ./temp/**",
"package-prepare": "npm run eslint && npm run prettier-check && npm run build && npm run test && npm run coverage && npm run docs-generate && npm run generate-third-party",
"package": "npm run package-clean && npm run package-prepare && npm pack"
}
}
接着我进行打包
pkg . --targets node18-win-x64 --output 3d-tiles-tools.exe --assets 'node_modules/**/*'