为什么Vite开发模式可以解析模块但不能解析构建的产品?

问题描述 投票:0回答:1

我正在使用 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

javascript node.js jwt vite es6-modules
1个回答
0
投票

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
的引用的句柄。

© www.soinside.com 2019 - 2024. All rights reserved.