简体   繁体   English

如何在DENO中使用npm模块?

[英]How to use npm module in DENO?

Deno is super cool.德诺超级酷。 I saw it in the morning and want to migrate to deno now.早上看到了,现在想迁移到deno。 I was trying to move my existing nodejs script to deno.我试图将我现有的 nodejs 脚本移动到 deno。 Can any one help me on how to use npm modules in deno.任何人都可以帮助我了解如何在 deno 中使用 npm 模块。 I need esprima module.我需要 esprima 模块。 This one has the package https://github.com/denoland/deno_third_party/tree/master/node_modules but i am not able to figure out how to use that.这个有 package https://github.com/denoland/deno_third_party/tree/master/node_modules但我不知道如何使用它。

Deno provides a Node Compatibility Library , that will allow to use some NPM packages that do not use non-polyfilled Node.js APIs . Deno 提供了一个Node Compatibility Library ,这将允许使用一些不使用非填充 Node.js API 的NPM 包。 You'll be able to require the package by using https://deno.land/std/node/module.ts您将能够通过使用https://deno.land/std/node/module.tsrequire package

The following works on deno 1.0.0以下适用于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))

The above code will use esprima from node_modules/ .上面的代码将使用来自esprima node_modules/的 esprima。

To run it, you'll need --allow-read flag要运行它,您需要--allow-read标志

deno run --allow-read esprima.js

You can restrict it only to node_modules您只能将其限制为node_modules

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

Which outputs:哪个输出:

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

Note : many APIs used by std/ are still unstable , so you may need to run it with --unstable flag.注意std/使用的许多 API 仍然不稳定,因此您可能需要使用--unstable标志运行它。


Although since that whole project is written in TypeScript already, and it's not using any dependencies, it will be very easy for them to adapt it to Deno.尽管由于整个项目已经用 TypeScript 编写,并且没有使用任何依赖项,但他们很容易将其适应 Deno。 All they need to do is use .ts extension on their imports .他们需要做的就是在他们的 imports上使用.ts扩展名。 You can also fork the project and do the changes.您还可以分叉项目并进行更改。

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

Once they do, you'll be able to just do:一旦他们这样做,你就可以做到:

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

Alternative选择

You can also use https://jspm.io/ which will convert NPM modules to ES Modules您还可以使用https://jspm.io/将 NPM 模块转换为 ES 模块

All modules on npm are converted into ES modules handling full CommonJS compatibility including strict mode conversions. npm 上的所有模块都被转换为处理完全 CommonJS 兼容性的 ES 模块,包括严格的模式转换。

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

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

For packages that use Node.js modules not supported by jspm it will throw an error:对于使用 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!

For now, you can use packages that only use Buffer , for that you'll have to include std/node .现在,您可以使用仅使用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);

Issue问题

In general, there are two issues with npm packages in Deno:总的来说,Deno 中的 npm 包有两个问题:

  1. ES Module (ESM) conformity is not given.未给出 ES 模块 (ESM) 一致性。
  • Bare imports like import _ from "lodash" don't work - no "magic" node_modules resolutionimport _ from "lodash"这样的导入不起作用 - 没有“魔术” node_modules分辨率
  • All import specifiers need to include the file extension - .ts , .js etc.所有导入说明符都需要包含文件扩展名 - .ts.js等。
  • CommonJS module system is not usable in Deno CommonJS 模块系统在 Deno 中不可用
  1. The npm package uses native Node.js builtins like fs or path . npm package 使用原生 Node.js 内置函数,如fspath

Solutions to issue 1问题 1 的解决方案

1.1: Third party modules 1.1:第三方模块

The Third Party Modules section is the quickest way to discover compatible packages.第三方模块部分是发现兼容包的最快方式。

1.2: ESM CDN providers 1.2:ESM CDN 提供商

Also take a look at CDN providers , that can auto-convert npm packages to ES Modules (ESM):还可以查看CDN 提供商,它们可以自动将 npm 包转换为 ES 模块 (ESM):

Skypack CDN can deliver auto-converted packages, that eg have set a "module" entrypoint in package.json . Skypack CDN 可以提供自动转换的包,例如在package.json中设置了“模块”入口点。 For TypeScript users: It fetches .d.ts type definitions along with .js files (via X-TypeScript-Types HTTP headers used by Deno).对于 TypeScript 用户:它获取.d.ts类型定义以及.js文件(通过 Deno 使用的X-TypeScript-Types HTTP 标头)。

unpkg.com describes its ?module flag as follows: "Expands all 'bare' import specifiers in JavaScript modules to unpkg URLs. This feature is very experimental". unpkg.com 描述其?module标志如下:“将 JavaScript 模块中的所有‘裸’导入说明符扩展到 unpkg URL。此功能非常实验性”。

Esprima does not depend on Node.js builtins, so we can simplify its import by a CDN 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 would be a good choice here - Skypack TS types didn't work for me in this particular case. jspm 在这里是一个不错的选择——在这种特殊情况下,Skypack TS 类型对我不起作用。

1.3: Other approaches 1.3:其他方法

You might also try to import an ESM compatible version directly from repository sources (eg an ESM branch).您也可以尝试直接从存储库源(例如 ESM 分支)导入 ESM 兼容版本。 Though for Esprima it won't work because of missing file extensions in code.尽管对于 Esprima,由于代码中缺少文件扩展名,它无法工作。

Snowpack and jspm stand in for a more manual approach to convert CommonJS → ESM. Snowpackjspm代表了一种更手动的方法来转换 CommonJS → ESM。 The rollup plugin@rollup/plugin-commonjs (internally used by Snowpack) is even a more low-level tool. rollup 插件@rollup/plugin-commonjs (Snowpack 内部使用)甚至是更底层的工具。


Solution to issue 2问题2的解决方案

Deno provides a Node compatibility layer , see Marcos Casagrande's answer . Deno 提供了一个 Node兼容层,请参阅Marcos Casagrande 的回答 However, not all native Node.js built-ins are fully supported.但是,并非完全支持所有原生 Node.js 内置插件。

As Esprima doesn't rely on Node builtins, you can go with the simpler CDN option.由于 Esprima 不依赖 Node 内置,您可以使用更简单的 CDN 选项 go。

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.从 v1.15 开始,Deno 提供了Node 兼容模式,可以直接在 Deno 中运行为 Node.js 编写的程序子集。 Compatibility mode can be activated by passing --compat flag in CLI.可以通过在 CLI 中传递 --compat 标志来激活兼容模式。

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

Currently, not all node.js built-in modules are supported and many are partially supported.目前,并非所有 node.js 内置模块都受支持,许多模块部分支持。

The following modules are not yet implemented:以下模块尚未实现:

  • cluster, dgram, http2, https, repl, tls, vm, lib集群,dgram,http2,https,repl,tls,vm,lib

As of version Deno 1.2.5 (released today) deno is now included with experimental npm support .从 Deno 1.2.5 (今天发布)版本开始,deno 现在包含在实验性 npm 支持中。

// main.ts
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/");

You can now run deno run --unstable --A main.ts and express will be downloaded.您现在可以运行deno run --unstable --A main.ts并下载express

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM