如何在 DENO 中使用 npm module?

IT技术 javascript node.js npm esprima deno
2021-03-16 06:07:38

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

3个回答

Deno 提供了一个Node Compatibility Library,它允许使用一些不使用非 polyfill Node.js API 的NPM 包你将能够require通过使用包https://deno.land/std/node/module.ts

以下工作在 deno 1.0.0

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))

上面的代码将使用esprimafrom node_modules/

要运行它,你需要--allow-read标志

deno run --allow-read 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" }
]

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


尽管整个项目已经是用 TypeScript 编写的,而且它没有使用任何依赖项,但他们很容易将其适配到 Deno。他们需要做的就是.ts他们的进口使用扩展您还可以 fork 项目并进行更改。

// 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/which 将 NPM module转换为 ES module

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

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

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

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

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!

现在,您可以使用仅使用 的包Buffer,为此您必须包含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);
上面的代码片段有效,我对其进行了测试。你使用的是什么 Deno 版本?
2021-04-15 06:07:38
太好了,谢谢你的努力。尝试得到这些类型的错误 TS2339 [错误]:属性 'dir' 在类型 'typeof Deno' 上不存在。
2021-04-16 06:07:38
那么您的代码中还有其他内容,因为我没有使用--unstable标志。你所拥有的只是我在回答中提交的片段?
2021-04-21 06:07:38
但该标志是否会导致生产中出现任何问题:)
2021-05-05 06:07:38
最新版本。1.0.0 在我使用 --unstable 标志后它起作用了。谢谢
2021-05-06 06:07:38

问题

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

  1. 未给出 ES module (ESM) 符合性。
  • import _ from "lodash"不工作一样的裸进口- 没有“神奇”的node_modules解决方案
  • 所有进口符需要包括文件扩展名- .ts.js等等。
  • CommonJS module系统在 Deno 中不可用
  1. npm 包使用原生 Node.js 内置函数,如fspath

问题 1 的解决方案

1.1:第三方module

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

1.2:ESM CDN 提供商

另请查看CDN providers,它可以将 npm 包自动转换为 ES module(ESM):

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

unpkg.com 将其?module标志描述如下:“将 JavaScript module中的所有‘裸’导入说明符扩展到 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 插件@rollup/plugin-commonjs(由 Snowpack 内部使用)甚至是一个更底层的工具。


问题 2 的解决方案

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

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

从 v1.15 开始,Deno 提供了Node 兼容模式,可以直接在 Deno 中运行为 Node.js 编写的程序子集。可以通过在 CLI 中传递 --compat 标志来激活兼容模式。

deno run  --compat --unstable --allow-read test.js

目前,并非所有的 node.js 内置module都受支持,而且很多都得到了部分支持。

以下module尚未实现:

  • 集群、dgram、http2、https、repl、tls、vm、lib