在本页
模块和依赖项
Deno 使用 ECMAScript 模块 作为其默认模块系统,以符合现代 JavaScript 标准并提升更高效和一致的开发体验。它是 JavaScript 模块的官方标准,允许更好的摇树优化、改进的工具集成以及跨不同环境的原生支持。
通过采用 ECMAScript 模块,Deno 确保与不断发展的 JavaScript 生态系统的兼容性。对于开发者来说,这意味着一个简化且可预测的模块系统,避免了与 CommonJS 等传统模块格式相关的复杂性。
导入模块 跳转到标题
在此示例中,从本地 calc.ts
模块导入 add
函数。
export function add(a: number, b: number): number {
return a + b;
}
// imports the `calc.ts` module next to this file
import { add } from "./calc.ts";
console.log(add(1, 2)); // 3
您可以在包含 main.ts
和 calc.ts
的目录中通过调用 deno run main.ts
来运行此示例。
使用 ECMAScript 模块时,本地导入说明符必须始终包含完整的文件扩展名,不能省略。
// WRONG: missing file extension
import { add } from "./calc";
// CORRECT: includes file extension
import { add } from "./calc.ts";
导入第三方模块和库 跳转到标题
在 Deno 中使用第三方模块时,请使用与本地代码相同的 import
语法。第三方模块通常从远程注册表导入,并以 jsr:
、npm:
或 https://
开头。
import { camelCase } from "jsr:@luca/[email protected]";
import { say } from "npm:[email protected]";
import { pascalCase } from "https://deno.land/x/case/mod.ts";
Deno 推荐使用现代 JavaScript 注册表 JSR 来获取第三方模块。在那里,您可以找到许多为您的项目准备的文档完善的 ES 模块,包括 Deno 标准库。
您可以在此处阅读有关 Deno 对 npm 包支持的更多信息。
管理第三方模块和库 跳转到标题
在多个文件中导入远程模块时,完整键入模块名称和版本说明符可能会变得很繁琐。您可以使用 deno.json
文件中的 imports
字段集中管理远程模块。我们将此 imports
字段称为**导入映射**,它基于 导入映射标准。
{
"imports": {
"@luca/cases": "jsr:@luca/cases@^1.0.0",
"cowsay": "npm:cowsay@^1.6.0",
"cases": "https://deno.land/x/case/mod.ts"
}
}
使用重新映射的说明符后,代码看起来更简洁
import { camelCase } from "@luca/cases";
import { say } from "cowsay";
import { pascalCase } from "cases";
重新映射的名称可以是任何有效的说明符。这是 Deno 中一个非常强大的功能,可以重新映射任何内容。您可以在此处了解更多关于导入映射的功能。
使用 deno add
添加依赖项 跳转到标题
使用 deno add
子命令可以轻松完成安装过程。它会自动将您请求的最新版本包添加到 deno.json
中的 imports
部分。
# Add the latest version of the module to deno.json
$ deno add jsr:@luca/cases
Add @luca/cases - jsr:@luca/[email protected]
{
"imports": {
"@luca/cases": "jsr:@luca/cases@^1.0.0"
}
}
您还可以指定确切的版本
# Passing an exact version
$ deno add jsr:@luca/[email protected]
Add @luca/cases - jsr:@luca/[email protected]
在deno add
参考中了解更多信息。
您还可以使用 deno remove
删除依赖项
$ deno remove @luca/cases
Remove @luca/cases
{
"imports": {}
}
在deno remove
参考中了解更多信息。
包版本 跳转到标题
可以为要导入的包指定版本范围。这是使用 @
符号后跟版本范围说明符来完成的,并遵循 semver 版本控制方案。
例如
@scopename/mypackage # highest version
@scopename/[email protected] # exact version
@scopename/mypackage@16 # highest 16.x version >= 16.0.0
@scopename/mypackage@^16.1.0 # highest 16.x version >= 16.1.0
@scopename/mypackage@~16.1.0 # highest 16.1.x version >= 16.1.0
以下是指定版本或范围的所有方法的概述
符号 | 描述 | 示例 |
---|---|---|
1.2.3 |
确切版本。仅使用此特定版本。 | 1.2.3 |
^1.2.3 |
兼容 1.2.3 版本。允许不更改最左边非零数字的更新。 例如,允许 1.2.4 和 1.3.0 ,但不允许 2.0.0 。 |
^1.2.3 |
~1.2.3 |
大约相当于 1.2.3 版本。允许更新补丁版本。 例如,允许 1.2.4 ,但不允许 1.3.0 。 |
~1.2.3 |
>=1.2.3 |
大于或等于 1.2.3 版本。允许 1.2.3 或更高版本。 |
>=1.2.3 |
<=1.2.3 |
小于或等于 1.2.3 版本。允许 1.2.3 或更低版本。 |
<=1.2.3 |
>1.2.3 |
大于 1.2.3 版本。仅允许高于 1.2.3 的版本。 |
>1.2.3 |
<1.2.3 |
小于 1.2.3 版本。仅允许低于 1.2.3 的版本。 |
<1.2.3 |
1.2.x |
次要版本 1.2 中的任何补丁版本。例如,1.2.0 、1.2.1 等。 |
1.2.x |
1.x |
主要版本 1 中的任何次要版本和补丁版本。例如,1.0.0 、1.1.0 、1.2.0 等。 |
1.x |
* |
允许任何版本。 | * |
HTTPS 导入 跳转到标题
Deno 也支持直接引用 HTTP/HTTPS URL 的导入语句
import { Application } from "https://deno.land/x/oak/mod.ts";
或者作为 deno.json
导入映射的一部分
{
"imports": {
"oak": "https://deno.land/x/oak/mod.ts"
}
}
由于以下 JavaScript CDN 提供了对 JavaScript 模块的 URL 访问,因此支持 HTTPS 导入使我们能够支持它们:
如果您有一个小型(通常是单个文件)的 Deno 项目,并且不需要任何其他配置,那么 HTTPS 导入非常有用。使用 HTTPS 导入,您可以完全避免使用 deno.json
文件。然而,不建议在较大的应用程序中使用这种导入方式,因为您最终可能会遇到版本冲突(不同的文件使用不同的版本说明符)。
请谨慎使用 HTTPS 导入,并且只从受信任的来源导入。如果服务器遭到入侵,它可能会向您的应用程序提供恶意代码。如果您在不同的文件中导入不同的版本,它们也可能导致版本控制问题。HTTPS 导入仍然受支持,但我们建议使用包注册表以获得最佳体验。
覆盖 HTTPS 导入 跳转到标题
导入映射非常有用的另一种情况是覆盖特定模块中的 HTTPS 导入。
假设您要将 https://deno.land/x/[email protected]/mod.ts
说明符(在来自 https://deno.land/x/example/
的文件中使用)覆盖为本地补丁版本。您可以通过在导入映射中使用如下所示的作用域来实现此目的
{
"imports": {
"example/": "https://deno.land/x/example/"
},
"scopes": {
"https://deno.land/x/example/": {
"https://deno.land/x/[email protected]/mod.ts": "./patched/mod.ts"
}
}
}
HTTPS 导入没有包的概念。仅使用项目根目录下的导入映射。URL 依赖项中使用的导入映射将被忽略。
发布模块 跳转到标题
任何定义了导出的 Deno 程序都可以作为模块发布。这允许其他开发人员在他们自己的项目中导入和使用您的代码。模块可以发布到
- JSR - 推荐,原生支持 TypeScript 并自动为您生成文档
- npm - 使用 dnt 创建 npm 包
- deno.land/x - 对于 HTTPS 导入,如果可能,请改用 JSR
重新加载模块 跳转到标题
默认情况下,Deno 使用全局缓存目录 (DENO_DIR
) 来存放下载的依赖项。此缓存由所有项目共享。
您可以使用 --reload
标志强制 deno 重新获取模块并将其重新编译到缓存中。
# Reload everything
deno run --reload my_module.ts
# Reload a specific module
deno run --reload=jsr:@std/fs my_module.ts
仅使用缓存的模块 跳转到标题
要强制 Deno 仅使用以前缓存的模块,请使用 --cached-only
标志
deno run --cached-only mod.ts
如果 mod.ts 的依赖项树中存在尚未缓存的依赖项,则此操作将失败。
将远程模块加入 vendor 跳转到标题
如果您的项目具有外部依赖项,您可能希望将它们存储在本地,以避免每次构建项目时都从互联网下载它们。在 CI 服务器或 Docker 容器中构建项目,或者修补或修改远程依赖项时,此功能尤其有用。
Deno 通过 deno.json
文件中的设置提供此功能
{
"vendor": true
}
将上述代码段添加到您的 deno.json
文件中,Deno 将在项目运行时将所有依赖项本地缓存在 vendor
目录中,或者您可以选择运行 deno install --entrypoint
命令立即缓存依赖项
deno install --entrypoint main.ts
然后,您可以使用 deno run
照常运行应用程序
deno run main.ts
完成依赖项缓存后,您可以使用 --cached-only
标志运行 main.ts
,无需联网。此标志强制 Deno 仅使用本地可用的模块。
完整性检查和锁文件 跳转到标题
假设您的模块依赖于位于 https://some.url/a.ts 的远程模块。当您首次编译模块时,会获取、编译并缓存 a.ts
。此缓存版本将一直使用,直到您在其他机器上运行模块(例如在生产环境中)或手动重新加载缓存(使用类似 deno install --reload
的命令)。
但是,如果 https://some.url/a.ts
的内容发生变化怎么办?这可能导致您的生产模块运行的依赖项代码与本地模块不同。为了检测这种情况,Deno 使用完整性检查和锁文件。
Deno 使用 deno.lock
文件来检查外部模块的完整性。要启用锁文件,您可以:
-
在当前目录或祖先目录中创建一个
deno.json
文件,这将自动在deno.lock
创建一个增量锁文件。请注意,可以通过在 deno.json 中指定以下内容来禁用此功能
deno.json{ "lock": false }
-
使用
--lock
标志启用并指定锁文件检查。
冻结锁文件 跳转到标题
默认情况下,Deno 使用增量锁文件,其中新的依赖项会被添加到锁文件中,而不是报错。
在某些情况下(例如 CI 管道或生产环境),您可能希望 Deno 在遇到以前从未见过的依赖项时报错,而不是自动添加。要启用此功能,您可以指定 --frozen
标志或在 deno.json 文件中设置以下内容
{
"lock": {
"frozen": true
}
}
当使用冻结的锁文件运行 deno 命令时,任何尝试用新内容更新锁文件的操作都将导致命令以错误退出,并显示将要进行的修改。
如果您希望更新锁文件,请在命令行上指定 --frozen=false
以临时禁用冻结的锁文件。
更改锁文件路径 跳转到标题
可以通过指定 --lock=deps.lock
或在 Deno 配置文件中指定以下内容来配置锁文件路径
{
"lock": {
"path": "deps.lock"
}
}
私有仓库 跳转到标题
在某些情况下,您可能希望加载位于*私有*仓库中的远程模块,例如 GitHub 上的私有仓库。
Deno 支持在请求远程模块时发送 Bearer 令牌。Bearer 令牌是 OAuth 2.0 使用的主要访问令牌类型,并且受到托管服务(例如 GitHub、GitLab、Bitbucket、Cloudsmith 等)的广泛支持。
DENO_AUTH_TOKENS 跳转到标题
Deno CLI 将查找名为 DENO_AUTH_TOKENS
的环境变量,以确定在请求远程模块时应考虑使用哪些身份验证令牌。环境变量的值的格式是由分号 (;
) 分隔的 *n* 个令牌,其中每个令牌可以是:
- 格式为
{token}@{hostname[:port]}
的 Bearer 令牌,或 - 格式为
{username}:{password}@{hostname[:port]}
的基本身份验证数据
例如,deno.land
的单个令牌如下所示
DENO_AUTH_TOKENS=[email protected]
或者
DENO_AUTH_TOKENS=username:[email protected]
多个令牌如下所示
DENO_AUTH_TOKENS=[email protected];[email protected]:8080;username:[email protected]
当 Deno 获取远程模块时,如果远程模块的主机名与请求的主机名匹配,Deno 会将请求的 Authorization
标头设置为 Bearer {token}
或 Basic {base64EncodedData}
的值。这允许远程服务器识别该请求是与特定已认证用户关联的授权请求,并提供对服务器上相应资源和模块的访问权限。
GitHub 跳转到标题
要访问 GitHub 上的私有仓库,您需要为自己创建一个*个人访问令牌*。您可以通过登录 GitHub 并进入*设置 -> 开发者设置 -> 个人访问令牌*来完成此操作。
然后,您需要选择*生成新令牌*,并为您的令牌提供描述和对 repo
范围的适当访问权限。repo
范围将启用读取文件内容(更多信息请参阅GitHub 文档中的范围)。
创建完成后,GitHub 将只显示一次新令牌,您需要将该令牌的值用于环境变量中。
为了访问 GitHub 上私有仓库中包含的模块,您需要在 DENO_AUTH_TOKENS
环境变量中使用生成的令牌,并将其作用域设置为 raw.githubusercontent.com
主机名。例如:
DENO_AUTH_TOKENS=[email protected]
这应该允许 Deno 访问为其颁发令牌的用户有权访问的任何模块。
当令牌不正确或用户无权访问模块时,GitHub 将返回 404 Not Found
状态,而不是未授权状态。因此,如果您在命令行上收到您尝试访问的模块未找到的错误,请检查环境变量设置和个人访问令牌设置。
此外,deno run -L debug
应该会打印一条关于从环境变量中解析出的令牌数量的调试消息。如果它认为任何令牌格式错误,它将打印一条错误消息。出于安全考虑,它不会打印任何有关令牌的详细信息。