咱们好,这里是咱们的林语冰。

Deno 团队非常鸡冻地官宣 Deno 1.4 正式发布,这是 Deno 开展的一个里程碑。Deno 1.4 包括增强 Deno 体会的功用,引入了用于高档日期和时间操作的强壮 Temporal API,并选用最新的装修器语法来完结更具表现力的代码。除了这些进步之外,咱们还施行了一系列弃用、安稳和删去,旨在简化 Deno 的功用,并为 Deno 2 未雨绸缪。

以下是 Deno 1.4 新增功用的概述:

  • Temporal API
  • import.meta.filename/.dirname
  • 装修器
  • deno.json 中更精简的 imports
  • 弃用、安稳和移除的功用
  • Web API:rejectionhandled 事情
  • WebGPU 窗口/“自带窗口”
  • Node 相关 API 更新
  • LSP 改善
  • 颜值更高的调试
  • deno lint 更新
  • 改变咱们处理不安稳功用的办法

Deno 1.4 支撑 JS 最新的 Temporal API

免责声明

本文属所以语冰的直男翻译了属所以,略有修改,仅供粉丝参阅。英文原味版请传送 Deno 1.40: Temporal API

Temporal API

Temporal API 旨在处理与 JS 中现有 Date 方针相关的某些缺陷和复杂性。

Temporal 提案已被一切主流 JS 引擎活跃完结,咱们非常鸡冻地宣布 Temporal 现在能够在 Deno 中经过 --unstable-temporal 标志运用。

const birthday = Temporal.PlainMonthDay.from('12-15')
const birthdayIn2030 = birthday.toPlainDate({ year: 2030 })
console.log(birthdayIn2030.toString())
// 2030-12-15
console.log('day of week', birthdayIn2030.dayOfWeek)
// 7

Temporal API 不太可能发生更改,咱们的方针是在 Deno 2 中安稳它。咱们鼓舞咱们深度学习 Temporal API 的文档。

import.meta.filename/.dirname

Deno 现在支撑 import.meta.filenameimport.meta.dirname 特点。

这些特点映射了 CJS 模块体系中的 __filename__dirname 特点:

  • import.meta.filename 供给当时模块文件的绝对途径
  • import.meta.dirname 供给包括当时模块文件的目录的绝对途径

这两个特点都知道操作体系特定的途径分隔符,并为当时渠道供给正确的分隔符:

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

这些特点能且仅能用于本地模块,即从文件体系加载的模块,而且用于长途模块会得到 undefined,比方从 http://https:// 导入的模块。

装修器

Deno 现在支撑 TC39 第 3 阶段装修器提案,该提案很快将在一切浏览器中完结。

装修器是一种扩展 JS 类的提案,在转译器环境中被开发者广泛选用,对规范化有着广泛的兴趣。五年多来,TC39 一直在迭代装修器提案。本文档根据一切曩昔提案的元素描绘了装修器的新提案。

装修器功用在 .ts/.jsx/.tsx 文件中可用。对纯 JS 的支撑正在等候 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()

假如咱们依靠旧的“实验性 TS 装修器”,咱们依然能够经过以下装备运用它们:

{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

粉丝请注意:Deno 1.4 被砍掉后发现了一个 bug,TS 的 experimentalDecorators 在 LSP 中依然翻开。请及时升级到 Deno 1.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.4 中,这答应咱们从 npm 导入 preactpreact/hooks

此前,Deno 认为 deno.json 中的 imports 字段只是惯例导入映射。现在,咱们预处理 deno.json 中的 imports 字段,并将右侧带有 npm: 前缀的一切条目扩展为内部导入映射中咱们用于解析的两个条目。

弃用、安稳和删去的功用

当咱们为 Deno 2 未雨绸缪时,咱们致力于改善运转时,一起确保从 Deno 1 的平稳过渡。尽管大多数 Deno 1 代码将坚持兼容,但咱们正在简化某些 API,确保渠道的长期健康。

弃刻苦用

咱们引入了弃刻苦用来逐步淘汰旧版 API,并供给警告来辅助咱们进行搬迁:

  • window:全局变量 window 在 JS 生态体系中常常运用,用于测验代码是否在浏览器中运转。运用 globalThisself 替代是一个简单粗犷的修正方案。现在还没有针对此弃用的运转时警告,但在发动此版别时它会显示在 deno lint 中。
  • Deno.run():这是破旧的且简单犯错的子流程 API。尔后,咱们引入了愈加通用Deno.Command API,该 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.readAll()Deno.readAllSync()
    • Deno.writeAll()Deno.writeAllSync()
    • Deno.Buffer
  • Deno.FsWatcher.return():为了与其他异步迭代器坚持共同,咱们不赞成运用显式关闭办法。
  • Deno.customInspect:为了鼓舞运用与浏览器兼容的代码,咱们已切换到 Symbol.for("Deno.customInspect")

在 Deno 2 中,咱们删去了“资源 id”(resource ids)的概念。资源 ID 是对套接字、文件或 JS 外部管理的其他资源的整数引证。它们类似于文件描绘符。然而大多数用户不会直接触摸这些,咱们想开端引入原生 JS 方针的资源引证。因此,咱们将弃用这些 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 中删去:

  • Deno.Conn.rid
  • Deno.FsWatcher.rid
  • Deno.TcpConn.rid
  • Deno.TlsConn.rid
  • Deno.UnixConn.rid
  • Deno.Listener.rid

现在已弃用从文件加载证书,推荐阅览:

  • Deno.ListenTlsOptions.certFile:请运用 Deno.ListenTlsOptions.certDeno.readTextFile 替代。
  • Deno.ListenTlsOptions.keyFile:请运用 Deno.ListenTlsOptions.keyDeno.readTextFile 替代。
  • Deno.ConnectTlsOptions.certFile:请运用 Deno.ConnectTlsOptions.certDeno.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()

移除

最后,不安稳的 Deno.upgradeHttp API 已被删去。这个 API 简单犯错而且简单被误用。咱们鼓舞每个人运用 Deno.serve()Deno.upgradeWebsocket()

Web API:rejectionhandled 事情

咱们添加了对 rejectionhandled 事情的支撑,每逢 .catch() 处理程序附加到已被回绝的 Promise 时就会触发该事情。此外,当且仅当咱们有一个调用 event.preventDefault()unhandledrejection 事情侦听器时,才会发出此事情,否则 Promise 会被回绝,而且进程将因过错而退出。

globalThis.addEventListener('unhandledrejection', event => {
  // 调用 preventDefault 防止进程退出。
  event.preventDefault()
  console.log('unhandledrejection', event.reason)
})
globalThis.addEventListener('rejectionhandled', event => {
  console.log('Promise 实例被回绝之后会被添加一个 .catch 句柄', event.reason)
})
// 创立一个被回绝的 Promise
const a = Promise.reject(new Error('boom!'))
// 定时器之后附加一个 .catch 句柄
setTimeout(async () => {
  a.catch(() => console.log('将 catch 句柄添加给 Promise 实例'))
}, 10)

WebGPU 窗口/“自带窗口”

咱们引入了一个新的不安稳的 Deno.UnsafeWindowSurface API 来处理 Deno 中的窗口问题。咱们的方针是为 WebGPU 供给窗口处理方案,而无需链接到 X11 等本机窗口体系。

这是一个初级 API,可供 FFI 窗口库运用,比方 sdl2 glfwraylib 等来创立运用本机窗口和显示句柄的 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()
/* 回来一个 Deno.UnsafeWindowSurface */
const surface = win.windowSurface()
/* 回来一个 a WebGPU GPUCanvasContext */
const context = surface.getContext('webgpu')
context.configure({
  /* ... */
})
for (const event of win.events()) {
  if (event.type == EventType.Quit) break
  // 正弦波
  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 运转。

Node 相关 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 API 中的若干过错:

  • Windows 上的 child_process.ChildProcess.send()
  • crypto.createDeciperiv() 现在支撑 aes-192-ecbaes-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 改善

自 Deno 1.39 以来,咱们加强了与 TS 言语服务 API 的嵌入式实例的集成,完结了明显的功用提高和某些过错修正。因为更智能的项目状况同步和缓存,Rust 和 TS 阻隔之间的数据交换愈加高效且频率更低。

jsxImportSource 编译器选项的用户的日子质量提高:保存包括的 deno.json 文件时,会主动缓存指定的长途资源。这是必要的,因为与未缓存的导入不同,因为缺少资源而发生的确诊是含糊的,而且没有指出问题的原因,无论是从用户的视点还是从言语服务器的快速修正生成器的视点。

主动导入完结会愈加共同。因为 TS 阻隔中更好的状况保存,某些完结解析会静静犯错的状况已得到修正。带有子途径的导入映射 NPM 阐明符已正确替换为预期的别号。

颜值更高的调试

deno lintdeno doc 有一个新的调试打印机。咱们将在行将发布的版别中将此扩展到其他子指令。

Deno 1.4 支撑 JS 最新的 Temporal API

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 :此文件主动生成,无需 lint
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...

改变咱们处理不安稳功用的办法

咱们正在改善管理不安稳功用的办法。--unstable 标志尽管有用,但有些不精确,会一起激活一切不安稳的功用。在 Deno 1.38 中,咱们引入了更细粒度的标志,这样咱们能够更好地控制特定的不安稳功用,比方 --unstable-webgpu 发动新的 WebGPU API。在此根底上,Deno 1.4 标志着广泛的 --unstable 标志弃用阶段的开端,为 Deno 2 中删去它奠定了根底。

此外,咱们还改善了 deno check 和 LSP 中不安稳 API 的类型查看。现在,在类型查看期间会主动包括安稳和不安稳 API 的类型界说。这样就无需指定 --unstable 来访问不安稳的 API 类型界说。可是,请记住在运转程序时启用特定的不安稳功用标志。无视这些标志依然会导致过错,请确保自己了解正在运用的不安稳功用。

这一改变简化了开发,为 Deno 功用集的运用供给了更多的清晰度和控制力。

本期论题是 —— 你了解 JS 最新的 Temporal API 吗?

欢迎在本文下方自由言论,文明同享。谢谢咱们的点赞,掰掰~

《前端猫猫教》每日 9 点半更新,坚持阅览,自律打卡,每天一次,进步一点

Deno 1.4 支撑 JS 最新的 Temporal API