本页内容

npm: 指定符

从 1.28 版本开始,Deno 原生支持导入 npm 包。这可以通过使用 npm: 指定符来实现。例如,以下代码

import { emojify } from "npm:node-emoji@2";

console.log(emojify(":t-rex: :heart: NPM"));

可以使用以下命令运行

$ deno run main.js
🦖 ❤️ NPM

这样做时,不需要 npm install 并且不会创建 node_modules 文件夹。这些包也受与 Deno 中其他代码相同的 权限 限制。

npm 指定符具有以下格式

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

有关热门库的示例,请参阅我们的 教程部分

TypeScript 类型 跳转到标题

许多包自带类型,您可以导入这些类型并轻松地将它们与类型一起使用

import chalk from "npm:chalk@5";

但是,有些包没有自带类型,您可以使用 @deno-types 指令指定它们的类型。例如,使用 @types

// @deno-types="npm:@types/express@^4.17"
import express from "npm:express@^4.17";

模块解析 跳转到标题

官方 TypeScript 编译器 tsc 支持不同的 moduleResolution 设置。Deno 仅支持现代的 node16 解析。不幸的是,许多 NPM 包在 node16 模块解析下无法正确提供类型,这会导致 deno check 报告类型错误,而 tsc 不会报告这些错误。

如果来自 npm: 导入的默认导出似乎具有错误的类型(而正确的类型似乎在 .default 属性下可用),则很可能是该包在 node16 模块解析下为来自 ESM 的导入提供了错误的类型。您可以通过检查错误是否也发生在 tsc --module node16package.json 中的 "type": "module" 或通过咨询 类型是否错误? 网站(特别是“node16 from ESM”行)来验证这一点。

如果您想使用不支持 TypeScript 的 node16 模块解析的包,您可以

  1. 在该包的问题跟踪器中打开一个关于该问题的问题。(也许可以贡献一个修复程序 😃(虽然目前不幸的是缺乏工具来让包同时支持 ESM 和 CJS,因为默认导出需要不同的语法,另请参阅 microsoft/TypeScript#54593))
  2. 使用 CDN,它会为 Deno 支持重新构建包,而不是使用 npm: 标识符。
  3. 使用 // @ts-expect-error// @ts-ignore 忽略代码库中出现的类型错误。

包含 Node 类型 跳转到标题

Node 附带许多内置类型,例如 Buffer,这些类型可能在 npm 包的类型中被引用。要加载这些类型,您必须向 @types/node 包添加类型引用指令

/// <reference types="npm:@types/node" />

请注意,在大多数情况下,不指定版本是可以的,因为 Deno 会尝试将其与内部 Node 代码保持同步,但您始终可以根据需要覆盖使用的版本。

npm 可执行脚本 跳转到标题

具有 bin 条目的 npm 包可以使用以下格式的指定符从命令行执行,而无需 npm install

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

例如

$ deno run --allow-read npm:cowsay@1.5.0 Hello there!
 ______________
< Hello there! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ deno run --allow-read npm:cowsay@1.5.0/cowthink What to eat?
 ______________
( What to eat? )
 --------------
        o   ^__^
         o  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

--node-modules-dir 标志 跳转到标题

npm 指定符将 npm 包解析到一个中央全局 npm 缓存中。这在大多数情况下都能很好地工作,并且是理想的选择,因为它占用空间更少,并且不需要 node_modules 目录。也就是说,您可能会发现 npm 包希望从 node_modules 目录执行。为了提高兼容性并支持这些包,您可以使用 --node-modules-dir 标志。

例如,给定 main.ts

import chalk from "npm:chalk@5";

console.log(chalk.green("Hello"));

使用 --node-modules-dir 运行此脚本,例如...

deno run --node-modules-dir main.ts

...将在当前目录中创建一个与 npm 具有类似文件夹结构的 node_modules 文件夹。

请注意,在调用 deno run 时,所有这些操作都会自动完成,无需单独的安装命令。

或者,如果您希望完全禁用 node_modules 目录的创建,可以将此标志设置为 false(例如 --node-modules-dir=false)或在您的 deno.json 配置文件中添加 "nodeModulesDir": false 条目,使该设置应用于整个目录树。

如果您希望在执行之前修改 node_modules 目录的内容,可以使用 --node-modules-dir 运行 deno cache,修改内容,然后运行脚本。

例如

deno cache --node-modules-dir main.ts
deno run --allow-read=. --allow-write=. scripts/your_script_to_modify_node_modules_dir.ts
deno run --node-modules-dir main.ts