前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Deno: 你并不总是需要NodeJS

Deno: 你并不总是需要NodeJS

作者头像
腾讯专有云
发布2022-06-24 18:13:30
7340
发布2022-06-24 18:13:30
举报
文章被收录于专栏:腾讯专有云

回顾

Node

包管理复杂

众所周知,Node 包管理很复杂,包之间又有可能互相依赖, 互相引用。且存在多个版本安装混乱的问题。

这时候就又需要借助 yarn.lock 之类的工具进行管理。并且根据 yarn 官方文档说明,yarn 会忽略依赖包内的 yarn.lock,仅支持 top-level 的 yarn.lock。所以可能会导致你的 node_modules 里面充斥着各种版本,各种重复的包。

权限风险

由于引用的包都已经安装至 node_modules,并且 node 运行时无法进行任何的权限控制。导致有可能第三方包在运行的时候,会有隐私风险。比如你只是想读取本地的文件,可是它一边扫描你运行的文件,一边通过网络请求将你本地的数据抓取上传,或者修改删除。

require 需要处理多种情况

Y 目录下 require(X) 时:

  1. 如果 X 是内置模块,加载该模块;
  2. 如果 X/ 开头,设置 Y 为文件系统的根部 (root);
  3. X./ , / , ../ 开头时,加载该文件或者加载该目录;
  4. 否则加载 node_modules 目录下的模块: LOAD_NODE_MODULES(X, dirname(Y))

用一幅图来开涮一下 node_modules

处理逻辑采用回调函数

代码语言:javascript
复制
const fs = require('fs');
fs.readFile('README.md', (err, data) => {
    if (err) { // error handling }
    else { // data handling }
});

总结

  • 不修改 npm 源的情况下,为中心化组件库。
  • 使用回调进行逻辑处理。
  • 无法控制第三方库进行的读取,网络权限。
  • require 处理复杂。
  • 无法直接运行 typescript。
  • Version>13.2.0 后, 支持 ES modules,之前使用CommonJS。

介绍

Deno 是一个可以运行 JavaScript,Typescript 的执行环境。前者能力由V8引擎提供,后者由 Rust 语言创造。

因为 Rust 支持 WebAssembly,所以可以直接使用 wasm 库和代码。

Deno

  1. Deno 使用 Rust 启动。
  2. 因为 V8 由 C++ 编写,所以通过 Rust 去执行 C++ 代码来初始化 V8 对象。这一部分使用 Rust FFI 调用 rusty_v8 执行。
  3. 这样 Deno 就可以执行 JavaScript 代码了。
  4. 运行 ts 的时候, 会通过内置的 tsc 和 swc 进行预编译,并且提供一份缓存。
  5. Tokio 提供事件处理。

Deno的包管理

提供三种方式引入资源文件

代码语言:javascript
复制
// 从 URL 导入
import XXXX from "https://cdn.bootcdn.net/abc.js";
// 从相对路径导入
import * as Service from "./service.js";
// 从绝对路径导入
import X from "/index.js";

在 Node 当中的一些引用语法,在 Deno 当中并不得到支持。

代码语言:javascript
复制
// 模块类的引入方法
import x from "x";
// 不标明根目录的路径
~~import x from "x/index.js";~~  // 通过[import maps](https://deno.land/manual/linking_to_external_code/import_maps)可以解决这样的引用
~~~~// 没有标明文件后缀
import index from "./index";
代码语言:javascript
复制
// import maps来解决相对路径引用问题
{
  "imports": {
    "fmt/": "https://deno.land/std@0.141.0/fmt/"
  }
}

import { red } from "fmt/colors.ts";

console.log(red("hello world"));

deno run --import-map=import_map.json color.ts

Deno的权限控制

  • -allow-env= 允许环境访问,例如读取和设置环境变量。
  • -allow-hrtime 允许高精度时间,高精度时间能够在计时攻击和特征识别中使用。
  • -allow-net= 允许网络访问。您可以指定一系列用逗号分隔的域名,来提供域名白名单。
  • -allow-ffi 允许加载动态的依赖,注意,也不在沙箱中运行. 谨慎使用, 并且该 API 并不稳定。
  • -allow-read= 允许读取文件系统。您可以指定一系列用逗号分隔的目录或文件,来提供文件系统白名单。
  • -allow-run= 允许运行子进程。请注意,子进程不在沙箱中运行,因此没有与 deno 进程相同的安全限制,请谨慎使用。
  • -allow-write= 允许写入文件系统。您可以指定一系列用逗号分隔的目录或文件,来提供文件系统白名单。
  • A, --allow-all 允许所有权限,这将禁用所有安全限制

Deno 支持 Promise 进行逻辑处理

代码语言:javascript
复制
// read-file.ts - Deno
try {
    const data = await Deno.readFile('README.md');
    // Handle the data
} catch (e) {
    // Handle the error
}

从上述代码可以看到,Deno 支持 top-level await,意味着你可以不依赖 async function 直接使用 await 语法。

内置命令

  • bundle Bundle module and dependencies into single file
  • cache Cache the dependencies
  • compile UNSTABLE: Compile the script into a self contained executable
  • completions Generate shell completions
  • coverage Print coverage reports
  • doc Show documentation for a module
  • eval Eval script
  • fmt Format source files
  • help Prints this message or the help of the given subcommand(s)
  • info Show info about cache or info related to source file
  • install Install script as an executable
  • lint Lint source files
  • lsp Start the language server
  • repl Read Eval Print Loop
  • run Run a JavaScript or TypeScript program
  • test Run tests
  • types Print runtime TypeScript declarations
  • uninstall Uninstall a script previously installed with deno install
  • upgrade Upgrade deno executable to given version

总结

  • 不断扩充的组件库。
  • 原生支持 promise 进行逻辑处理。
  • 原生支持 typescript。
  • 原生支持 ES modules。
  • 允许进行文件系统,网络访问等权限控制,用来执行沙盒代码。
  • 可编译为一个可执行文件。
  • 兼容浏览器 API,比如支持 window 对象。

与我们

业务结合

代码语言:javascript
复制
import {
  emptyDir,
  emptyDirSync,
  ensureDirSync,
  ensureFileSync,
} from "https://deno.land/std@0.132.0/fs/mod.ts";

if(!Deno?.args?.[0]) {
  console.error("请输入TED文件目录");
  Deno.exit(1);
}

const tedPath = Deno.args[0]

for await(const f of Deno.readDir(tedPath)) {
  if(f.isFile) continue;
  if(f.name.includes("a-b-c")) {
      for await(const y of Deno.readDir(`${tedPath}/${f.name}`)) {
          if(y.isFile) continue;
          if(y.name.includes("c-d")){
              ensureFileSync(`${tedPath}/${f.name}/${y.name}/TCE/sync.sh`);
              const text = await Deno.readTextFile("./sync.sh");
              const s = await Deno.writeTextFile(`${tedPath}/${f.name}/${y.name}/TCE/sync.sh`, text);
          }
      }
  }
}

deno run --allow-read --allow-write test.ts /path

我们使用了 typescript 脚本,进行了 ted 项目的批量修改。

疑问

Q:组件库支持情况?

A:支持主流库, 如 lodash,i18next,billboardjs 等,官方也提供了安装地址,https://deno.land/x

Q:如果贡献,使用第三方库?

A:自行开发第三方组件很简单,只需要上传到托管 js 的服务器,或者直接放在 github 即可。也可以在官方发布组件。

Q:能否使用 node_modues?

A:不能直接使用 node_modules,但是有一些组件库做了层级适配,可以间接使用。

Q:既然都在使用远程依赖的文件,如果文件被篡改怎么办?是否安全?

A:官方给的解决方案是,使用 cache 的 lock 功能,将文件锁定 deno cache --lock=lock.json --lock-write src/deps.ts

实现一个

简单

单HTTPweb server

代码语言:javascript
复制
// handler.ts
export function handler(req: Request): Response {
  return new Response("Hello, World!");
}

// entry.ts

import { handler } from './handler.ts';
import { serve } from "https://deno.land/std@0.141.0/http/server.ts";

serve(handler, { port: 4242 });

deno run --allow-net ./entry.ts

Web

框架

架介绍

在 deno 中也有对应的 web 框架,叫做oak,使用方法基本上和 KOA 是一致的,官网文档也说明了,是受到 KOA 启发而做的。

代码语言:javascript
复制
import { Application } from "https://deno.land/x/oak/mod.ts";

const app = new Application();

// Logger
app.use(async (ctx, next) => {
  await next();
  const rt = ctx.response.headers.get("X-Response-Time");
  console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`);
});

// Timing
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.response.headers.set("X-Response-Time", `${ms}ms`);
});

// Hello World!
app.use((ctx) => {
  ctx.response.body = "Hello World!";
});

await app.listen({ port: 8000 });

进行

react 渲染

Deno 默认支持 jsx,tsx的语法,使用它就可以创建一个基于 Deno 的 react app 了。

它采用了和 npm 方式完全不同的模块管理。

可以从它的模板依赖代码看到,它完全采用的是远程的代码。

代码语言:javascript
复制
import { serve } from "https://deno.land/std@0.140.0/http/server.ts";
import { h, ssr, tw } from "https://crux.land/nanossr@0.0.1";

const Hello = (props) => (
  <div class={tw`bg-white flex h-screen`}>
    <h1 class={tw`text-5xl text-gray-600 m-auto mt-20`}>
      Hello {props.name}!
    </h1>
  </div>
);

await serve((req) => {
  const url = new URL(req.url);
  const name = url.searchParams.get("name") ?? "world";
  return ssr(() => <Hello name={name} />);
});

总结

受限文章长度,deno 的事件处理,在 Rust 当中也可以作为独立的应用使用,以及如何和 wasm 结合使用都没有展开来说。

简单来说,deno 是一个轻量,自由的库。笔者总结的适用场景可以是:

  1. 脚本文件。
  2. 做一个 data mock server。
  3. 前端的监控或者是自动化测试脚本编写工具。

当然作为一个还在不断发展的库,deno 还有更多的可能性,笔者期待与各位有更多的探讨。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯专有云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档