Heroku应用报ERR_MODULE_NOT_FOUND错误,本地运行正常求解决
模块导入错误:ERR_MODULE_NOT_FOUND(Heroku部署失败,本地正常)
我的技术栈
- Postgres
- Node 20.17.0
- Express
- Sequelize ORM
- JavaScript
问题背景
将应用从require语法迁移到import语法后出现该问题,同时在package.json中添加了"type": "module"配置,还将migrations和seeders文件更新为.cjs扩展名。本地运行项目一切正常,但部署到Heroku后报错。
已尝试的方案
- 将默认导出改为命名导出,未解决问题。
错误详情
Node在/app/app/utils/auth/auth_utils.js路径下找不到AuthUtils模块,该模块从/app/app/controllers/auth_controller.js导入,返回ERR_MODULE_NOT_FOUND错误。完整日志如下:
2024-11-22T00:56:21.633194+00:00 app[web.1]: [heroku-exec] Starting 2024-11-22T00:56:21.896719+00:00 app[web.1]: (node:2) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification. 2024-11-22T00:56:21.896722+00:00 app[web.1]: (Use `node --trace-warnings ...` to show where the warning was created) 2024-11-22T00:56:21.908747+00:00 app[web.1]: 2024-11-22T00:56:21.908751+00:00 app[web.1]: > backend-webapp@1.0.0 start 2024-11-22T00:56:21.908751+00:00 app[web.1]: > node app.js 2024-11-22T00:56:21.908751+00:00 app[web.1]: 2024-11-22T00:56:22.003330+00:00 app[web.1]: node:internal/modules/esm/resolve:265 2024-11-22T00:56:22.003332+00:00 app[web.1]: throw new ERR_MODULE_NOT_FOUND( 2024-11-22T00:56:22.003332+00:00 app[web.1]: ^ 2024-11-22T00:56:22.003332+00:00 app[web.1]: 2024-11-22T00:56:22.003334+00:00 app[web.1]: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/app/utils/auth/auth_utils.js' imported from /app/app/controllers/auth_controller.js 2024-11-22T00:56:22.003335+00:00 app[web.1]: at finalizeResolution (node:internal/modules/esm/resolve:265:11) 2024-11-22T00:56:22.003336+00:00 app[web.1]: at moduleResolve (node:internal/modules/esm/resolve:933:10) 2024-11-22T00:56:22.003336+00:00 app[web.1]: at defaultResolve (node:internal/modules/esm/resolve:1169:11) 2024-11-22T00:56:22.003336+00:00 app[web.1]: at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:540:12) 2024-11-22T00:56:22.003337+00:00 app[web.1]: at ModuleLoader.resolve (node:internal/modules/esm/loader:509:25) 2024-11-22T00:56:22.003337+00:00 app[web.1]: at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:239:38) 2024-11-22T00:56:22.003337+00:00 app[web.1]: at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:96:40) 2024-11-22T00:56:22.003338+00:00 app[web.1]: at link (node:internal/modules/esm/module_job:95:36) { 2024-11-22T00:56:22.003338+00:00 app[web.1]: code: 'ERR_MODULE_NOT_FOUND', 2024-11-22T00:56:22.003338+00:00 app[web.1]: url: 'file:///app/app/utils/auth/auth_utils.js' 2024-11-22T00:56:22.003338+00:00 app[web.1]: } 2024-11-22T00:56:22.003339+00:00 app[web.1]: 2024-11-22T00:56:22.003349+00:00 app[web.1]: Node.js v20.17.0 2024-11-22T00:56:22.010187+00:00 app[web.1]: npm notice 2024-11-22T00:56:22.010189+00:00 app[web.1]: npm notice New minor version of npm available! 10.8.2 -> 10.9.1 2024-11-22T00:56:22.010189+00:00 app[web.1]: npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.1 2024-11-22T00:56:22.010190+00:00 app[web.1]: npm notice To update run: npm install -g npm@10.9.1 2024-11-22T00:56:22.010190+00:00 app[web.1]: npm notice 2024-11-22T00:56:22.064090+00:00 heroku[web.1]: Process exited with status 1
相关代码
package.json
{ "name": "backend-webapp", "version": "1.0.0", "type": "module", "description": "Matchbook backend web application", "main": "index.js", "scripts": { "format": "prettier --write \"**/*.js\"", "serve": "nodemon app.js", "start": "node app.js", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js" }, "author": "Benjamin Cáceres", "license": "ISC", "dependencies": { "@aws-sdk/client-s3": "^3.0.0", "@aws-sdk/lib-storage": "^3.0.0", "@sendgrid/mail": "^7.6.0", "axios": "^1.7.0", "bcrypt": "^5.0.1", "body-parser": "^1.20.3", "connect-multiparty": "^2.2.0", "cors": "^2.8.5", "dotenv": "^10.0.0", "express": "^4.21.0", "fs": "^0.0.1-security", "handlebars": "^4.7.7", "jsonwebtoken": "^9.0.0", "jwt-decode": "^3.1.2", "lodash": "^4.17.21", "nanoid": "^5.0.0", "node-cron": "^3.0.2", "nodemailer": "^6.7.5", "pdf-creator-node": "^2.3.5", "pg": "^8.7.1", "rollbar": "^2.26.2", "sequelize": "^6.31.0", "transbank-sdk": "3.0.0" }, "devDependencies": { "jest": "^29.7.0", "nodemon": "^3.1.0", "prettier": "^3.0.3", "proxyquire": "^2.1.3", "sequelize-cli": "^6.3.0", "sinon": "^19.0.2" }, "engines": { "node": "20.17.0" } }
auth_controller.js(仅展示导入部分)
import { nanoid } from "nanoid"; import jwt from "jsonwebtoken"; import jwtDecode from "jwt-decode"; import messages from "../utils/messages.json" assert { type: "json" }; import UserRepository from "../repositories/user_repository.js"; import BalanceRepository from "../repositories/balance_repository.js"; import { AuthUtils } from "./../utils/auth/auth_utils.js"; import { removeWhiteSpaces } from "../utils/functions.js"; import "dotenv/config"; // 业务逻辑代码省略... export { signinWithEmailAndPassword, signUp, signUpWithGoogle, signInWithGoogle, auth, checkAuth, refreshTokenForUpdate, resetPassword, forgotPassword, resetPasswordEmail, };
auth_utils.js
import bcrypt from "bcrypt"; import lodash from "lodash"; import { sendEmailHelper } from "../../controllers/email_sender_controller.js"; export class AuthUtils { // 根据姓名生成用户名 static generateUsername({ firstName, lastName }) { const randomNum = `${Math.floor(Math.random() * 100)}`; const username = ( firstName[0] + firstName[1] + firstName[2] + lastName + randomNum ).toLowerCase(); const finalUsername = username.replace(/[^a-zA-Z0-9]/g, ""); return finalUsername; } static async hashPassword(password) { return await bcrypt.hash(password, 10); } static async comparePassword({ password, storedPassword }) { return await bcrypt.compare(password, storedPassword); } static secureUserObject(user) { return lodash.pick(user, [ "rut", "user_id", "rut", "username", "type", "first_name", "last_name", "email", "phone_number", "profile_image", "shipping_preference", "country_id", "region_id", "city_id", "created_at", "updated_at", ]); } static async sendForgotPasswordEmail({ verificationLink, email }) { try { let data = { data: { resetPasswordLink: verificationLink, }, }; sendEmailHelper({ type: "password_reset", data: data, destinationEmail: email, subject: "Restablecimiento de contraseña", }); } catch (error) { throw error; } } }
内容的提问来源于stack exchange,提问作者Benjamín Cáceres Ramirez
相关产品推荐
相关产品推荐

