我正在使用 Vite 开发 Fastify 应用程序。 我的产品使用 jsonwebtoken 包来签名和验证 JWT。
开发时,我可以通过Vite的开发模式使用所有
jsonwebtoken
功能。然而,在我构建应用程序后,虽然构建过程进展顺利,但构建的应用程序崩溃并产生TypeError: jwt.sign is not a function
。
为什么开发模式运行良好,但构建出来的产品却不行? 有什么办法可以在编译时检测到错误吗?还是我的建筑设置有什么错误?
这里是最小复制源代码。 https://github.com/randyumi/20240203jsonwebtoken-vite-build
npm run dev
-> curl http://localhost:8080/
-> 运行良好并返回签名的 JWT。npm run build
-> NODE_ENV=production node dist/index.js
-> curl http://localhost:8080/
-> 不起作用,说 jwt.sign is not a function
我发现了有关此问题的问题https://github.com/auth0/node-jsonwebtoken/issues/655
jsonwebtoken
是一个 CommonJS 模块,因此 您要将 CommonJS 模块导入到 ES 模块中,并且应该阅读 与 CommonJS 的互操作性。
您的特定(命名空间)导入语法正在导入 Module Namespace Exotic Object:
import * as jwt from 'jsonwebtoken'
上面的导入会产生这样的结果:
[Module: null prototype] {
decode: [Function (anonymous)],
default: {
decode: [Function (anonymous)],
verify: [Function (anonymous)],
sign: [Function (anonymous)],
JsonWebTokenError: [Function: JsonWebTokenError],
NotBeforeError: [Function: NotBeforeError],
TokenExpiredError: [Function: TokenExpiredError]
}
}
Node.js 文档指出
导入CommonJS模块时,可以使用ES模块默认导入或其相应的糖语法可靠地导入:
因此,您可以使用
default
: 从命名空间导入更改为命名导入
import { default as jwt } from 'jsonwebtoken'
可以使用等效(但更甜)的语法糖进一步简化:
import jwt from 'jsonwebtoken'
这会产生预期的模块导出:
{
decode: [Function (anonymous)],
verify: [Function (anonymous)],
sign: [Function (anonymous)],
JsonWebTokenError: [Function: JsonWebTokenError],
NotBeforeError: [Function: NotBeforeError],
TokenExpiredError: [Function: TokenExpiredError]
}
FWIW,如果您最初尝试为
sign
进行命名导入,Node.js 运行时会在尝试启动生产服务器时提供有用的错误消息。
例如这个:
import { sign } from 'jsonwebtoken'
会产生此错误消息:
import { sign } from "jsonwebtoken";
^^^^
SyntaxError: Named export 'sign' not found. The requested module 'jsonwebtoken' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'jsonwebtoken';
const { sign } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:132:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:214:5)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:113:12)
Node.js v20.11.0
这显示了另一种语法,可以正确获取对
sign
的引用的句柄。