【问题标题】:How to use npm module in DENO?如何在 DENO 中使用 npm 模块?
【发布时间】:2020-09-01 09:15:02
【问题描述】:

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

【问题讨论】:

标签: javascript node.js npm esprima deno


【解决方案1】:

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

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

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

以下模块尚未实现:

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

【讨论】:

    【解决方案2】:

    问题

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

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

    问题 1 的解决方案

    1.1:第三方模块

    Third Party Modules 部分是发现兼容包的最快方式。

    1.2:ESM CDN 提供商

    还可以查看CDN providers,它可以自动将 npm 包转换为 ES 模块 (ESM):

    Skypack CDN 可以提供自动转换的包,例如在package.json 中设置了"module" 入口点。对于 TypeScript 用户:它获取 .d.ts 类型定义以及 .js 文件(通过 Deno 使用的 X-TypeScript-Types 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:其他方法

    您也可以尝试直接从 repository sources(例如 ESM 分支)导入 ESM 兼容版本。虽然对于 Esprima,由于代码中缺少文件扩展名,它无法工作。

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


    问题 2 的解决方案

    Deno 提供了一个节点 compatibility layer,参见 Marcos Casagrande's answer。但是,并非所有原生 Node.js 内置插件都得到完全支持。

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

    【讨论】:

      【解决方案3】:

      Deno 提供了一个Node Compatibility Library,这将允许使用一些不使用non-polyfilled Node.js APIs 的 NPM 包。您将能够使用https://deno.land/std/node/module.tsrequire

      以下作品适用于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 模块

      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!
      

      目前,您可以使用仅使用 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);
      

      【讨论】:

      • 太好了,感谢您的努力。尝试得到这类错误 TS2339 [ERROR]: Property 'dir' does not exist on type 'typeof Deno'。
      • 上面的sn-p工作我测试过了。你用的是什么 Deno 版本?
      • 最新版本。 1.0.0 在我使用 --unstable 标志后它起作用了。谢谢
      • 但是该标志会导致生产中的任何问题:)
      • 那么您的代码中还有其他内容,因为我没有使用--unstable 标志。你只有我在回答中提交的 sn-p 吗?
      猜你喜欢
      • 2020-12-03
      • 2016-03-23
      • 2019-01-26
      • 1970-01-01
      • 2014-03-07
      • 2020-04-22
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多