如何在 DENO 中使用 npm 模块?
How to use npm module in DENO?
Deno 超级酷。早上看到了,现在想迁移到deno。我试图将我现有的 nodejs 脚本移动到 deno。任何人都可以帮助我了解如何在 deno 中使用 npm 模块。我需要 esprima 模块。这个有包 https://github.com/denoland/deno_third_party/tree/master/node_modules 但我不知道如何使用它。
Deno 提供了一个Node Compatibility Library, that will allow to use some NPM packages that do not use non-polyfilled Node.js APIs。您将能够 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))
以上代码将使用 node_modules/
中的 esprima
。
要运行它,你需要--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" }
]
注意:std/
使用的许多API仍然是unstable,因此您可能需要运行它与--unstable
旗帜。
虽然整个项目已经用 TypeScript 编写,并且没有使用任何依赖项,但他们很容易将其改编为 Deno。他们所需要做的就是在 their imports 上使用 .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/
将 NPM 模块转换为 ES 模块
All modules on npm are converted into ES modules handling full
CommonJS compatibility including strict mode conversions.
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!
目前,您可以使用仅使用 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 中的 npm 包有两个问题:
- 未提供 ES 模块 (ESM) 一致性。
- Bare imports 喜欢
import _ from "lodash"
不起作用 - 没有“魔法”node_modules
分辨率
- 所有导入说明符都需要包含文件扩展名 -
.ts
、.js
等
- CommonJS 模块系统在 Deno 中不可用
- npm 包使用本机 Node.js 内置函数,例如
fs
或 path
。
问题 1 的解决方案
1.1:第三方模块
Third Party Modules 部分是发现兼容包的最快方法。
1.2:ESM CDN 提供商
也看看 CDN providers,可以 auto-convert npm 包到 ES 模块(ESM):
- Skypack CDN
- jspm.io
- unpkg.com 与
?module
查询参数
Skypack CDN 可以传送 auto-converted 包,例如已经设置了 Deno 使用的 "module" entrypoint in package.json
. For TypeScript users: It fetches .d.ts
type definitions along with .js
files (via X-TypeScript-Types
HTTP headers。
unpkg.com 描述其 ?module
标志如下:“扩展 JavaScript 模块中的所有 'bare' 导入说明符以解包 URLs。此功能是非常具有实验性。
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:其他方法
您也可以尝试直接从 repository sources(例如 ESM 分支)导入 ESM 兼容版本。尽管对于 Esprima 它不会工作,因为代码中缺少文件扩展名。
Snowpack and jspm stand in for a more manual approach to convert CommonJS → ESM. The rollup plugin @rollup/plugin-commonjs
(Snowpack内部使用)更是一个low-level的工具。
问题 2 的解决方案
Deno 提供了一个节点 compatibility layer, see Marcos Casagrande's answer。但是,并非所有原生 Node.js built-ins 都得到完全支持。
由于 Esprima 不依赖于 Node 内置,您可以使用更简单的 CDN 选项。
Starting with v1.15 Deno provides Node compatibility mode that makes it possible to run a subset of programs authored for Node.js directly in Deno. Compatibility mode can be activated by passing --compat flag in CLI.
deno run --compat --unstable --allow-read test.js
目前,并非所有 node.js 个内置模块都受支持,而且很多都得到部分支持。
以下模块尚未实现:
- 集群、dgram、http2、https、repl、tls、vm、lib
Deno 超级酷。早上看到了,现在想迁移到deno。我试图将我现有的 nodejs 脚本移动到 deno。任何人都可以帮助我了解如何在 deno 中使用 npm 模块。我需要 esprima 模块。这个有包 https://github.com/denoland/deno_third_party/tree/master/node_modules 但我不知道如何使用它。
Deno 提供了一个Node Compatibility Library, that will allow to use some NPM packages that do not use non-polyfilled Node.js APIs。您将能够 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))
以上代码将使用 node_modules/
中的 esprima
。
要运行它,你需要--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" }
]
注意:std/
使用的许多API仍然是unstable,因此您可能需要运行它与--unstable
旗帜。
虽然整个项目已经用 TypeScript 编写,并且没有使用任何依赖项,但他们很容易将其改编为 Deno。他们所需要做的就是在 their imports 上使用 .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/
将 NPM 模块转换为 ES 模块
All modules on npm are converted into ES modules handling full CommonJS compatibility including strict mode conversions.
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!
目前,您可以使用仅使用 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 中的 npm 包有两个问题:
- 未提供 ES 模块 (ESM) 一致性。
- Bare imports 喜欢
import _ from "lodash"
不起作用 - 没有“魔法”node_modules
分辨率 - 所有导入说明符都需要包含文件扩展名 -
.ts
、.js
等 - CommonJS 模块系统在 Deno 中不可用
- npm 包使用本机 Node.js 内置函数,例如
fs
或path
。
问题 1 的解决方案
1.1:第三方模块
Third Party Modules 部分是发现兼容包的最快方法。
1.2:ESM CDN 提供商
也看看 CDN providers,可以 auto-convert npm 包到 ES 模块(ESM):
- Skypack CDN
- jspm.io
- unpkg.com 与
?module
查询参数
Skypack CDN 可以传送 auto-converted 包,例如已经设置了 Deno 使用的 "module" entrypoint in package.json
. For TypeScript users: It fetches .d.ts
type definitions along with .js
files (via X-TypeScript-Types
HTTP headers。
unpkg.com 描述其 ?module
标志如下:“扩展 JavaScript 模块中的所有 'bare' 导入说明符以解包 URLs。此功能是非常具有实验性。
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:其他方法
您也可以尝试直接从 repository sources(例如 ESM 分支)导入 ESM 兼容版本。尽管对于 Esprima 它不会工作,因为代码中缺少文件扩展名。
Snowpack and jspm stand in for a more manual approach to convert CommonJS → ESM. The rollup plugin @rollup/plugin-commonjs
(Snowpack内部使用)更是一个low-level的工具。
问题 2 的解决方案
Deno 提供了一个节点 compatibility layer, see Marcos Casagrande's answer。但是,并非所有原生 Node.js built-ins 都得到完全支持。
由于 Esprima 不依赖于 Node 内置,您可以使用更简单的 CDN 选项。
Starting with v1.15 Deno provides Node compatibility mode that makes it possible to run a subset of programs authored for Node.js directly in Deno. Compatibility mode can be activated by passing --compat flag in CLI.
deno run --compat --unstable --allow-read test.js
目前,并非所有 node.js 个内置模块都受支持,而且很多都得到部分支持。
以下模块尚未实现:
- 集群、dgram、http2、https、repl、tls、vm、lib