Typescript 转译错误仅出现在生产服务器上
Typescript transpile errors appear only on production server
在为两台机器更新我的节点版本/依赖项的过程中,我注意到
在另一台机器上构建我的生产应用程序会输出错误,而在我的主机上构建生产环境则不会。
如果我将受影响的 devDependencies 移动到我的 package.json
中的 dependencies 数组,错误就会消失,但这更像是一种解决方法,我想知道为什么我会看到不同的行为。
据我了解,当 运行 npm install
投入生产时,它 不会 安装我的开发依赖项。
这很好,因为我在我的开发机器上测试过它,即使没有我的开发依赖,应用程序也能正常构建。
但是,在生产中,我遇到如下错误:
Cannot find module 'sinon' or its corresponding type declarations.
Could not find a declaration file for module 'cors'. '/home/ubuntu/brobot/source/node_modules/cors/lib/index.js' implicitly has an 'any' type. Try `npm i --save-dev @types/cors` if it exists or add a new declaration (.d.ts) file containing `declare module 'cors';
如果我将受影响的包移动到 dependencies 数组而不是 dev dependencies,它们就会消失,但为什么呢?为什么它在我的开发机器上没有我的开发依赖性的情况下构建良好?
这是我的配置:
package.json
缩短:
{
"main": "dist/src/index.js",
"type": "module",
"scripts": {
"build": "rimraf dist && tsc",
"test": "mocha",
"dev:old": "cross-env NODE_ENV=development concurrently \"tsc -w\" \"nodemon -q -r dotenv/config --es-module-specifier-resolution=node dist/src/index.js\"",
"deploy": "pm2 deploy ecosystem.config.cjs production",
"preserve": "npm run build",
},
"dependencies": {
"@pkmn/randoms": "^0.5.11",
"@pkmn/sim": "^0.5.11",
"@twurple/api": "^5.0.18",
"@twurple/auth": "^5.0.18",
"@twurple/chat": "^5.0.18",
"@twurple/eventsub": "^5.0.18",
"@twurple/eventsub-ngrok": "^5.0.18",
"@types/cookie-session": "^2.0.44",
"@types/express": "^4.17.13",
"@types/express-ws": "^3.0.1",
"@types/mocha": "^9.1.0",
"@types/node": "^17.0.23",
"@types/passport": "^1.0.7",
"@types/request": "^2.48.8",
"axios": "^0.26.1",
"cookie-session": "^2.0.0",
"cors": "^2.8.5",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-ws": "^5.0.2",
"helmet": "^5.0.2",
"mocha": "^9.2.2",
"moment-timezone": "^0.5.34",
"mongoose": "^6.2.8",
"passport": "^0.5.2",
"passport-oauth": "^1.0.0",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"typescript": "^4.6.2",
"winston": "^3.6.0",
"ws": "^8.5.0"
},
"devDependencies": {
"@types/chai": "^4.3.0",
"@types/cors": "^2.8.12",
"@types/sinon": "^10.0.11",
"@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"chai": "^4.3.6",
"concurrently": "^7.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.11.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
"lint-staged": "^12.3.7",
"nodemon": "^2.0.15",
"pm2": "^5.2.0",
"prettier": "^2.6.0",
"sinon": "^13.0.1",
"ts-node": "^10.7.0"
},
"lint-staged": {
"*.{js,ts}": [
"eslint --cache --fix",
"prettier --check"
]
}
}
tsconfig.json
:
{
"compilerOptions": {
"target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
"outDir": "dist", /* Redirect output structure to the directory. */
"strict": true, /* Enable all strict type-checking options. */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
PM2 ecosystem.config.cjs:
require('dotenv').config();
// Default configuration
module.exports = {
apps: [...],
deploy: {
production: {
user: process.env.AWS_USER,
host: process.env.AWS_PUBLIC_IP,
key: process.env.AWS_SSH_KEY,
ref: 'origin/main',
repo: '...',
path: process.env.AWS_EC2_PATH,
node_args: "--experimental-modules --es-module-specifier-resolution=node",
env: { NODE_ENV: 'production', },
'post-deploy':
'npm install && npm run build && pm2 startOrRestart ecosystem.config.cjs --env production'
^^^^^^^^^^^^^^^ this is where errors are thrown in production. `npm run build` works fine on development without dev dependencies installed.
}
}
};
我考虑过的事情:
- 不要在生产环境中转译。我在部署过程中克隆我的存储库,所以我不能这样做,除非我将我的构建包含在我的存储库中。
- 将 devDependencies 切换为 dependencies:我真的想避免这样做,因为它们应该 是 dev dependencies
我尝试过的其他事情:
- 正在清除 npm 缓存
- 完全删除我的 PM2 实例并重新配置它
- 正在删除包-lock.json(我知道这很糟糕但我很绝望,没有看到冲突)
- 删除 --experimental-modules 并重新添加“.js”扩展导入
- 在 tsconfig.json
中排除我的 node_modules
我的 dev/prod 机器之间肯定有一些配置错误。虽然它们是 运行 相同版本的 node 和 Typescript。
据我所知,两台机器都没有使用全局安装的软件包。奇怪的是,这之前在我的生产机器上运行得很好,尽管我可能没有 运行 它正确地使用生产标志。即使我的 node_env 是“生产”,它也可能在我不注意的情况下安装了我的开发依赖项。
我 运行 在这里没有选择,非常感谢任何帮助。
sinon 是一个开发依赖项,因此它没有捆绑用于生产。如果您需要它用于生产,您可以将它添加到依赖项中,如果不需要,您可以删除对 sinon 的引用并重新捆绑,它应该会自行解决。
编辑 1:
The errors go away if I move the affected devDependencies to the dependencies array in my package.json
我最初忽略了这一点。是的,听起来您在生产代码中使用了这些库,但由于它们不在依赖项中,因此它们不包含在您的生产包中。它们在开发中工作,因为您将它们作为开发依赖项。
在为两台机器更新我的节点版本/依赖项的过程中,我注意到 在另一台机器上构建我的生产应用程序会输出错误,而在我的主机上构建生产环境则不会。
如果我将受影响的 devDependencies 移动到我的 package.json
中的 dependencies 数组,错误就会消失,但这更像是一种解决方法,我想知道为什么我会看到不同的行为。
据我了解,当 运行 npm install
投入生产时,它 不会 安装我的开发依赖项。
这很好,因为我在我的开发机器上测试过它,即使没有我的开发依赖,应用程序也能正常构建。
但是,在生产中,我遇到如下错误:
Cannot find module 'sinon' or its corresponding type declarations.
Could not find a declaration file for module 'cors'. '/home/ubuntu/brobot/source/node_modules/cors/lib/index.js' implicitly has an 'any' type. Try `npm i --save-dev @types/cors` if it exists or add a new declaration (.d.ts) file containing `declare module 'cors';
如果我将受影响的包移动到 dependencies 数组而不是 dev dependencies,它们就会消失,但为什么呢?为什么它在我的开发机器上没有我的开发依赖性的情况下构建良好?
这是我的配置:
package.json
缩短:
{
"main": "dist/src/index.js",
"type": "module",
"scripts": {
"build": "rimraf dist && tsc",
"test": "mocha",
"dev:old": "cross-env NODE_ENV=development concurrently \"tsc -w\" \"nodemon -q -r dotenv/config --es-module-specifier-resolution=node dist/src/index.js\"",
"deploy": "pm2 deploy ecosystem.config.cjs production",
"preserve": "npm run build",
},
"dependencies": {
"@pkmn/randoms": "^0.5.11",
"@pkmn/sim": "^0.5.11",
"@twurple/api": "^5.0.18",
"@twurple/auth": "^5.0.18",
"@twurple/chat": "^5.0.18",
"@twurple/eventsub": "^5.0.18",
"@twurple/eventsub-ngrok": "^5.0.18",
"@types/cookie-session": "^2.0.44",
"@types/express": "^4.17.13",
"@types/express-ws": "^3.0.1",
"@types/mocha": "^9.1.0",
"@types/node": "^17.0.23",
"@types/passport": "^1.0.7",
"@types/request": "^2.48.8",
"axios": "^0.26.1",
"cookie-session": "^2.0.0",
"cors": "^2.8.5",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-ws": "^5.0.2",
"helmet": "^5.0.2",
"mocha": "^9.2.2",
"moment-timezone": "^0.5.34",
"mongoose": "^6.2.8",
"passport": "^0.5.2",
"passport-oauth": "^1.0.0",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"typescript": "^4.6.2",
"winston": "^3.6.0",
"ws": "^8.5.0"
},
"devDependencies": {
"@types/chai": "^4.3.0",
"@types/cors": "^2.8.12",
"@types/sinon": "^10.0.11",
"@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"chai": "^4.3.6",
"concurrently": "^7.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.11.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
"lint-staged": "^12.3.7",
"nodemon": "^2.0.15",
"pm2": "^5.2.0",
"prettier": "^2.6.0",
"sinon": "^13.0.1",
"ts-node": "^10.7.0"
},
"lint-staged": {
"*.{js,ts}": [
"eslint --cache --fix",
"prettier --check"
]
}
}
tsconfig.json
:
{
"compilerOptions": {
"target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
"outDir": "dist", /* Redirect output structure to the directory. */
"strict": true, /* Enable all strict type-checking options. */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
PM2 ecosystem.config.cjs:
require('dotenv').config();
// Default configuration
module.exports = {
apps: [...],
deploy: {
production: {
user: process.env.AWS_USER,
host: process.env.AWS_PUBLIC_IP,
key: process.env.AWS_SSH_KEY,
ref: 'origin/main',
repo: '...',
path: process.env.AWS_EC2_PATH,
node_args: "--experimental-modules --es-module-specifier-resolution=node",
env: { NODE_ENV: 'production', },
'post-deploy':
'npm install && npm run build && pm2 startOrRestart ecosystem.config.cjs --env production'
^^^^^^^^^^^^^^^ this is where errors are thrown in production. `npm run build` works fine on development without dev dependencies installed.
}
}
};
我考虑过的事情:
- 不要在生产环境中转译。我在部署过程中克隆我的存储库,所以我不能这样做,除非我将我的构建包含在我的存储库中。
- 将 devDependencies 切换为 dependencies:我真的想避免这样做,因为它们应该 是 dev dependencies
我尝试过的其他事情:
- 正在清除 npm 缓存
- 完全删除我的 PM2 实例并重新配置它
- 正在删除包-lock.json(我知道这很糟糕但我很绝望,没有看到冲突)
- 删除 --experimental-modules 并重新添加“.js”扩展导入
- 在 tsconfig.json 中排除我的 node_modules
我的 dev/prod 机器之间肯定有一些配置错误。虽然它们是 运行 相同版本的 node 和 Typescript。 据我所知,两台机器都没有使用全局安装的软件包。奇怪的是,这之前在我的生产机器上运行得很好,尽管我可能没有 运行 它正确地使用生产标志。即使我的 node_env 是“生产”,它也可能在我不注意的情况下安装了我的开发依赖项。
我 运行 在这里没有选择,非常感谢任何帮助。
sinon 是一个开发依赖项,因此它没有捆绑用于生产。如果您需要它用于生产,您可以将它添加到依赖项中,如果不需要,您可以删除对 sinon 的引用并重新捆绑,它应该会自行解决。
编辑 1:
The errors go away if I move the affected devDependencies to the dependencies array in my package.json
我最初忽略了这一点。是的,听起来您在生产代码中使用了这些库,但由于它们不在依赖项中,因此它们不包含在您的生产包中。它们在开发中工作,因为您将它们作为开发依赖项。