如何在 DENO 中使用 npm 模块?

新手上路,请多包涵

Deno 超级酷。早上看到了,现在想迁移到deno。我试图将我现有的 nodejs 脚本移动到 deno。任何人都可以帮助我了解如何在 deno 中使用 npm 模块。我需要 esprima 模块。这个有包 https://github.com/denoland/deno_third_party/tree/master/node_modules 但我不知道如何使用它。

原文由 Vinod Sai 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

Deno 提供了一个 Node Compatibility Library ,它允许使用一些不使用 non-polyfilled Node.js APIs 的 NPM 包。

Deno 1.25 开始,通过使用 npm: 说明符提供 实验性 NPM 支持

npm:<package-name>[@<version-requirement>][/<sub-path>]

 import express from "npm:express";
const app = express();

app.get("/", function (req, res) {
  res.send("Hello World");
});

app.listen(3000);
console.log("listening on http://localhost:3000/");

--unstable 标志是必需的。

执行此操作时,不需要 npm install ,也不需要创建 node_modules 文件夹


您还可以 require 并使用 https://deno.land/std/node/module.ts 安装 npm 包

以下适用于 deno >= 1.0.0

 npm install esprima

 import { createRequire } from "https://deno.land/std/node/module.ts";

const require = createRequire(import.meta.url);
const esprima = require("esprima");

const program = 'const answer = 42';
console.log(esprima.tokenize(program))

上面的代码将使用 esprima 来自 node_modules/

要运行它,您需要 --allow-read && --allow-env 标志

# you can also use --allow-all
deno run --allow-read --allow-env esprima.js

您只能将其限制为 node_modules

 deno run --allow-read=node_modules esprima.js

哪些输出:

 [
 { type: "Keyword", value: "const" },
 { type: "Identifier", value: "answer" },
 { type: "Punctuator", value: "=" },
 { type: "Numeric", value: "42" }
]

注意std/ 使用的许多 API 仍然 不稳定,因此您可能需要使用 --unstable 标志运行它。


尽管由于整个项目已经用 TypeScript 编写,并且没有使用任何依赖项,因此他们很容易将其改编为 Deno。他们需要做的就是使用 .ts 扩展 他们的进口。您还可以分叉项目并进行更改。

 // import { CommentHandler } from './comment-handler';
import { CommentHandler } from './comment-handler.ts';
// ...

一旦他们这样做了,你就可以做到:

 // Ideally they would issue a tagged release and you'll use that instead of master
import esprima from 'https://raw.githubusercontent.com/jquery/esprima/master/src/esprima.ts';

const program = 'const answer = 42';
console.log(esprima.tokenize(program))

选择

您还可以使用 https://jspm.io/ 将 NPM 模块转换为 ES 模块

npm 上的所有模块都被转换为 ES 模块,处理完整的 CommonJS 兼容性,包括严格模式转换。

 import esprima from "https://dev.jspm.io/esprima";

const program = 'const answer = 42';
console.log(esprima.tokenize(program))

对于使用 jspm 不支持的 Node.js 模块的包,它将抛出错误:

 Uncaught Error: Node.js fs module is not supported by jspm core.
Deno support here is tracking in
https://github.com/jspm/jspm-core/issues/4, +1's are appreciated!

要填充这些 Node.js API,您必须包含 std/node

 // import so polyfilled Buffer is exposed
import "https://deno.land/std/node/module.ts";
import BJSON from 'https://dev.jspm.io/buffer-json';

const str = BJSON.stringify({ buf: Buffer.from('hello') })

console.log(str);

原文由 Marcos Casagrande 发布,翻译遵循 CC BY-SA 4.0 许可协议

问题

一般来说,Deno 中的 npm 包有两个问题:

  1. 未给出 ES 模块 (ESM) 一致性。
  • import _ from "lodash" 这样的裸导入 不起作用 - 没有“魔法” node_modules 分辨率
  • 所有导入说明符都需要包含文件扩展名 - .ts , .js 等。
  • CommonJS 模块系统在 Deno 中不可用
  1. npm 包使用原生 Node.js 内置函数,例如 fspath

问题 1 的解决方案

1.1:第三方模块

第三方模块 部分是发现兼容包的最快方式。

1.2:ESM CDN 提供商

另请查看 CDN 提供商,它可以将 npm 包自动转换为 ES 模块 (ESM):

Skypack CDN 可以提供自动转换的包,例如在 package.json 中设置了 “模块” 入口点。对于 TypeScript 用户:它获取 .d.ts 类型定义以及 .js 文件(通过 X-TypeScript-Types Deno 使用的 HTTP 标头)。

unpkg.com 描述其 ?module 标志如下:“将 JavaScript 模块中的所有‘裸’导入说明符扩展到 unpkg URL。此功能是非常实验性的”。

Esprima 不依赖于 Node.js 内置函数,因此我们可以通过 CDN URL 简化其导入:

 import esprima from "https://cdn.skypack.dev/esprima@^4.0.1"; // Option 1: Skypack
import esprima from "https://dev.jspm.io/esprima"; // Option 2: jspm
// your program
const tokens = esprima.tokenize("const foo = 'bar'"); // works

jspm 在这里是一个不错的选择——在这种特殊情况下,Skypack TS 类型对我不起作用。

1.3:其他方法

您也可以尝试直接从 存储库源(例如 ESM 分支)导入 ESM 兼容版本。尽管对于 Esprima,它不会工作,因为代码中缺少文件扩展名。

Snowpackjspm 代表一种更手动的方法来转换 CommonJS → ESM。汇总插件 @rollup/plugin-commonjs (Snowpack 内部使用)甚至是一个更底层的工具。


问题2的解决方案

Deno 提供了一个 Node 兼容层,参见 Marcos Casagrande 的回答。但是,并非所有原生 Node.js 内置插件都得到完全支持。

由于 Esprima 不依赖于 Node 内置,您可以使用更简单的 CDN 选项。

原文由 ford04 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏