作者:Bartek Iwaczuk、Leo Kettmeir等 2024年1月25日
咱们很快乐宣告发布 Deno 1.40,这是 Deno 进化的重要一步。这个新版别充满了增强 Deno 运用体验的功用,引入了强大的 Temporal API,用于高级日期和时刻操作,并选用了最新的 装修器语法 以完结更赋有表现力的代码。除此之外,咱们还完结了一系列的 弃用、安稳性改善和移除,旨在简化 Deno 的功用,并为 Deno 2 的到来做好准备。
假如你现已装置了 Deno,能够在终端中运用以下指令升级到 1.40 版别:
deno upgrade
假如你还没有装置 Deno,能够运用以下其中一条指令进行装置,或者 其他方式。
# MacOS / Linux 装置
curl -fsSL https://deno.land/install.sh | sh
# Windows 装置
irm https://deno.land/install.ps1 | iex
以下是 Deno 1.40 的新功用概览:
-
Temporal
API -
import.meta.filename
和import.meta.dirname
- 装修器
- 更简略的
deno.json
中的imports
- 弃用、安稳性改善和移除
- Web API:
rejectionhandled
事情 - WebGPU 窗口办理 / “自带窗口”
- Node.js API 更新
- LSP 改善
- 更美观的确诊信息
-
deno lint
更新 - 对不安稳功用处理的改变
Temporal
API
Temporal API 旨在解决 JavaScript 中现有 Date
方针存在的一些缺陷和复杂性。
Temporal
提案现已被全部主要的 JavaScript 引擎活跃完结,并咱们很快乐地宣告它现在在 Deno 中经过 --unstable-temporal
标志可用。
const birthday = Temporal.PlainMonthDay.from("12-15");
const birthdayIn2030 = birthday.toPlainDate({ year: 2030 });
console.log(birthdayIn2030.toString());
console.log("day of week", birthdayIn2030.dayOfWeek);
Temporal 的用户友爱型 API 使得解析和操作日期和时刻变得简略。
Temporal
API 不太可能发生更改,咱们的方针是在 Deno 2 中安稳它。咱们鼓舞你探索 Temporal
API 文档。
Deno 现在支撑 import.meta.filename
和 import.meta.dirname
特点。
这些特点镜像了 CommonJS 模块体系中的 __filename
和 __dirname
特点:
-
import.meta.filename
供给当时模块文件的绝对途径 -
import.meta.dirname
供给包括当时模块文件的目录的绝对途径
这两个特点意识到了 OS 特定的途径分隔符,并为当时渠道供给适当的分隔符:
console.log(import.meta.filename);
console.log(import.meta.dirname);
在 Unix 中:
$ deno run /dev/my_module.ts
/dev/my_module.ts
/dev/
而在 Windows 中:
$ deno run C:devmy_module.ts
C:devmy_module.ts
C:dev
这些特点仅对本地模块(即从文件体系加载的模块)可用,并对远程模块(从 http://
或 https://
导入的模块)为 undefined
。
装修器
Deno 现在支撑 TC39 阶段 3 的 装修器提案,这将很快在全部浏览器中完结。
装修器是一种用于扩展 JavaScript 类的提案,广泛在转译环境中得到选用,被广泛关注于标准化。TC39 在曩昔的五年里一直在迭代装修器提案。本文描述了根据曩昔全部提案的元素的一个新的装修器提案。
此功用在 .ts
、.jsx
和 .tsx
文件中可用。纯 JavaScript 的支撑正在等待在 V8中的完结。
以下是一个 @trace
装修器的示例,该装修器在每次调用函数时记载日志,以及当它返回时:
function trace(fn: any, ctx: ClassMethodDecoratorContext) {
return function (...args: unknown[]) {
console.log("ENTERED", ctx.name);
const v = fn(...args);
console.log("EXITED", ctx.name);
return v;
};
}
class App {
@trace
static start() {
console.log("Hello World!");
}
}
App.start();
假如你依赖于旧的“实验性 TypeScript 装修器”,你依然能够在装备文件中运用以下装备来运用它们:
{
"compilerOptions": {
"experimentalDecorators": true
}
}
留意: 在 v1.40.0 版别之后发现了一个 bug,TypeScript 的
experimentalDecorators
依然在 LSP 中打开。请升级到 v1.40.1 版别。
更简略的 deno.json
中的 imports
deno.json
中的 imports
字段现在支撑更简略的语法来指定具有子途径导出的依赖项。以前,假如想要运用 npm
中的 preact
,你有必要将以下内容添加到 deno.json
的 imports
方针中:
{
"imports": {
"preact": "npm:preact@10.5.13",
"preact/": "npm:/preact@10.5.13/"
}
}
这允许你一起导入 preact
和 preact/hooks
等子途径导出。
在这个版别中,咱们简化了这一点,现在你只需:
{
"imports": {
"preact": "npm:preact@10.5.13"
}
}
在 Deno 1.40.0 版别中,这将允许你从 npm 中导入 preact
和 preact/hooks
。
以前,Deno 将 deno.json
中的 imports
字段视为普通的 import map。现在,咱们在 deno.json
中的 imports
字段中预处理,并将右侧带有 npm:
前缀的条目展开为咱们用于解析的内部 import map 中的 两个 条目。
弃用、安稳性改善和移除
跟着咱们为 Deno 2 做准备,咱们致力于优化运转时,一起确保从 Deno 1 平滑过渡。虽然大多数 Deno 1 代码依然兼容,但咱们正在简化某些 API 以保证渠道的长期健康。
弃用
咱们引入了弃用来逐步淘汰旧的API,并供给正告来协助您的迁移:
-
window
– 全局变量window
在整个 JavaScript 生态体系中经常用于测验代码是否在浏览器中运转。运用globalThis
或self
来替代它是一个简略的修正办法。现在尚无此弃用的运转时正告,但将在此版别的deno lint
中显现。 -
Deno.run()
– 这是旧的且简略犯错的子进程API。咱们现已引入了更灵敏的[Deno.Command](https://deno.land/api?s=Deno.Command "Deno.Command")
API,一年前现已安稳化。 -
Deno.serveHttp()
– 已被更快速、更简略的Deno.serve()
替代。文档在这里。 -
Deno.metrics()
– 为了关注功能,咱们正在转向更有针对性的指令行标志和API。经过 op_metrics_factory_fn 和新的--strace-ops
标志进行运转时操作跟踪,能够运用自定义的度量完结。 - 与流相关的函数:为了过渡到 Web Streams,咱们正在弃用几个
Deno.Reader
/Deno.Writer
流函数。这些已弃用的函数依然能够经过 Deno 标准库访问:-
Deno.iter()
和Deno.iterSync()
-
Deno.copy()
– 能够在 deno.land/std/io/copy… 找到 -
Deno.readAll()
和Deno.readAllSync()
– 能够在 deno.land/std/io/read… 找到 -
Deno.writeAll()
和Deno.writeAllSync()
– 能够在 deno.land/std/io/writ… 找到 -
Deno.Buffer
– 能够在 deno.land/std/io/buff… 找到
-
-
Deno.FsWatcher.return()
– 为了与其他异步迭代器对齐,咱们正在弃用这个,推荐运用显式封闭办法。 -
Deno.customInspect
– 为了鼓舞与浏览器兼容的代码,咱们已切换到Symbol.for("Deno.customInspect")
。
在 Deno 2 中,咱们将移除“资源ID”的概念。资源ID是对在 JavaScript 之外办理的套接字、文件或其他资源的整数引证。它们类似于文件描述符。然而,大多数用户不直接操作这些,因而咱们期望开始引入由本机 JavaScript 方针引证的资源。因而,咱们正在弃用以下API:
-
Deno.isatty()
– 运用isTerminal()
办法来替代,例如Deno.stdout.isTerminal()
。 -
Deno.close()
– 此API也对rid
进行操作。主张用户在相关方针上运用.close()
办法,例如file.close()
而不是Deno.close(file.rid)
。 -
Deno.resources()
– 此API还揭露资源ID,并且实用性很小。 -
Deno.ftruncate()
和Deno.ftruncateSync()
– 这些函数现在在Deno.FsFile
上作为truncate()
和truncateSync()
供给。
全部 rid
特点现在都已被弃用,并将在 Deno 2.0 中删除:
Deno.Conn.rid
Deno.FsWatcher.rid
Deno.TcpConn.rid
Deno.TlsConn.rid
Deno.UnixConn.rid
Deno.Listener.rid
从文件加载证书现已弃用,请自行读取:
-
Deno.ListenTlsOptions.certFile
– 运用Deno.ListenTlsOptions.cert
和Deno.readTextFile
替代。 -
Deno.ListenTlsOptions.keyFile
– 运用Deno.ListenTlsOptions.key
和Deno.readTextFile
替代。 -
Deno.ConnectTlsOptions.certFile
– 运用Deno.ConnectTlsOptions.cert
和Deno.readTextFile
替代。
安稳化
以下 Deno
API 现已安稳化并取消符号:
Deno.Conn.ref()
Deno.Conn.unref()
-
Deno.connect()
用于unix
传输 Deno.connectTls
Deno.stderr.isTerminal()
Deno.stdin.isTerminal()
Deno.stdout.isTerminal()
Deno.TlsConn.handshake()
移除
最终,不安稳的 API Deno.upgradeHttp
已被移除。这个 API 简略犯错且简略被乱用。咱们鼓舞每个人运用 Deno.serve() 和 Deno.upgradeWebsocket()。
Web API: rejectionhandled
事情
咱们添加了对 rejectionhandled事情 的支撑,该事情在现已回绝的 Promise 上附加了 .catch()
处理程序时触发。此外,只有在您有一个调用 event.preventDefault()
的 unhandledrejection
事情监听器时,该事情才会触发(不然 Promise 将被回绝并且进程将以过错退出)。
globalThis.addEventListener("unhandledrejection", (event) => {
// Call `preventDefault()` to prevent the process from exiting.
event.preventDefault();
console.log("unhandledrejection", event.reason);
});
globalThis.addEventListener("rejectionhandled", (event) => {
console.log(
"A .catch() handler was added to the promise after it has already rejected.",
event.reason,
);
});
// Create a rejected promise...
const a = Promise.reject(new Error("boom!"));
// ...then attach a `.catch()` handler to after a timeout.
setTimeout(async () => {
a.catch(() => console.log("Added catch handler to the promise"));
}, 10);
$ deno run main.js
unhandledrejection Error: boom!
at file:///dev/main.js:12:26
Added catch handler to the promise
A .catch() handler was added to the promise after it has already rejected. Error: boom!
at file:///dev/main.js:12:26
WebGPU 窗口化 / “自带窗口”
咱们引入了一个新的不安稳的 Deno.UnsafeWindowSurface
API 来处理 Deno 中的窗口。咱们的方针是为 WebGPU 供给一个窗口化的解决方案,而无需链接到像 X11 这样的本机窗口体系。
这是一个能够被 FFI 窗口库(例如 sdl2、glfw、raylib、winit
等)运用的低级API,能够运用本机窗口和显现句柄创立一个 WebGPU 表面。
这里是运用 deno.land/x/sdl2
的示例:
import {
EventType,
WindowBuilder,
} from "https://deno.land/x/sdl2@0.8.0/mod.ts";
const win = new WindowBuilder("Hello, World!", 800, 600).build();
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
/* Returns a Deno.UnsafeWindowSurface */
const surface = win.windowSurface();
/* Returns a WebGPU GPUCanvasContext */
const context = surface.getContext("webgpu");
context.configure({/* ... */});
for (const event of win.events()) {
if (event.type == EventType.Quit) break;
// Sine wave
const r = Math.sin(Date.now() / 1000) / 2 0.5;
const g = Math.sin(Date.now() / 1000 2) / 2 0.5;
const b = Math.sin(Date.now() / 1000 4) / 2 0.5;
const textureView = context.getCurrentTexture().createView();
const renderPassDescriptor = {
colorAttachments: [
{
view: textureView,
clearValue: { r, g, b, a: 1.0 },
loadOp: "clear",
storeOp: "store",
},
],
};
const commandEncoder = device.createCommandEncoder();
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
surface.present();
}
运用 deno run --allow-ffi --unstable-webgpu --unstable-ffi
运转:
这是运用此 API 构建的演示音乐播放器应用程序的示例:github.com/littledivy/…
有关低级用法的更多详细信息,请检查 PR:github.com/denoland/de…
阅读有关 GPUCanvasContext
的更多信息 here。
Node.js API 更新
以下内置的 Node API 现在可用:
crypto.pseudoRandomBytes()
fs.contants
fs.cp()
fs.cpSync()
fs.promises.cp()
net.ClientRequest.setNoDelay()
-
net.UdpSocket.ref()
和net.UdpSocket.unref()
net.WriteStream.isTTY
os.cpus()
os.machine()
process.abort()
process.on("rejectionHandled")
此外,咱们在已支撑的 Node.js API 中修正了一些过错:
- 在 Windows 上修正了
child_process.ChildProcess.send()
-
crypto.createDeciperiv()
现在支撑aes-192-ecb
和aes-256-ecb
- 修正了
fs.promises.readFile()
http.ClientRequest.socket.remoteAddress
http.ClientRequest.socket.remotePort
querystring.stringify()
-
test
模块支撑嵌套测验 zlib.brotliCompress()
zlib.brotliCompressSync()
zlib.gzipSync()
zlib.unzipSync()
LSP 改善
自从 v1.39.0 以来,咱们加强了与 TypeScript 的 Language Service API 的集成,以完结显著的功能提高和一些过错修正。因为更智能的项目状态同步和缓存,Rust 和 TypeScript 隔离之间的数据交换愈加高效和不频繁。
关于 jsxImportSource
编译选项的用户来说,这是一个生活质量的提高:保存包括 deno.json
文件时,指定的远程资源将主动缓存。这是必要的,因为与未缓存的导入不同,因为短少此缺失的资源而导致的确诊是含糊的,无法指向问题的原因(不管从用户还是言语服务器的快速修正生成器的视点)。
主动导入完结将愈加一致地工作。因为 TypeScript 隔离中状态保存得更好,一些静默过错解决的状况得以解决。带有子途径的导入映射的 NPM 标准符正确地替换为预期的别名。
更好看的确诊
为 deno lint
和 deno doc
引入了新的确诊打印机。咱们将在下一个版别中扩展到其他子指令。
deno lint
更新
在 deno lint
中有三个新规则:
no-console
no-self-compare
no-window
no-window
规则默许启用,而其他两个需求在装备文件中启用:
{
"lint": {
"rules": ["no-console", "no-self-compare"]
}
}
保持代码质量对项目的成功至关重要,咱们都从前处于需求按捺来自 linter 的正告的状况。
在大多数状况下,咱们仅仅疏忽一个正告然后持续,但这种办法关于团队成员或未来的自己来说并不协助了解为什么要按捺特定的正告。
deno lint
现在支撑在 // deno-lint-ignore
和 // deno-lint-ignore-file
指令中供给额外的解释:
// deno-lint-ignore-file -- This file is autogenerated, no need to lint it.
var __global$ = globalThis || (typeof window !== "undefined" ? window : self);
var cu=Object.create;var R=Object.defineProperty;var lu=Object.getOwnPropertyDescriptor;var iu=Object.getOwnPropertyNames;var nu=Object.getPrototypeOf...
// deno-lint-ignore no-empty -- I really need this fn have no body
export function noop() {}
对不安稳特性处理的改变
咱们正在改善咱们处理不安稳特性的办法。--unstable
标志虽然有用,但有点不够准确,一起激活全部不安稳特性。在 Deno 1.38 中,咱们引入了更细粒度的标志,使您更精密地控制特定的不安稳特性,例如 --unstable-webgpu
启用了新的 WebGPU API。根据此,Deno 1.40 标志着广泛的 --unstable
标志进入弃用阶段的开始,为其在 Deno 2 中的移除做好准备。
此外,咱们在 deno check
和 LSP 中改善了与不安稳 API 相关的类型检查。现在,在类型检查期间主动包括安稳和不安稳 API 的类型定义。这消除了访问不安稳 API 类型定义时有必要指定 --unstable
的需求。但是,在运转程序时记住启用特定的不安稳特性标志。省略这些标志仍将导致过错,确保您知道正在运用的不安稳特性。
这一改变简化了开发,供给了对 Deno 特性集的更明晰和更精密的控制。
感谢咱们的奉献者!
没有咱们社区的协助,咱们无法构建 Deno!不管是在咱们的社区 Discord 服务器 中回答问题还是 陈述过错,咱们对您的支撑感到非常感激。特别感谢以下人士对 Deno 1.40 的奉献:Anwesh,Dean Srebnik,Joel Walker,Jovi De Croock,Julien Cayzac,Jrme Benoit,Kenta Moriuchi,Kitson Kelly,Lino Le Van,Raashid Anwar,cions,king8fisher,nokazn,林炳权。
想成为 Deno 奉献者吗?在这里检查咱们的奉献文档,咱们期望下次在名单上见到您。
信不信由你,上面列出的改变依然不能告诉您 1.40 中的全部变得更好了什么。您能够在 GitHub 上检查 Deno 1.40 合并的全部拉取请求的完整列表。
感谢您了解咱们的 1.40 版别,并期望您喜爱运用 Deno 构建!