回顾
Node
包管理复杂
众所周知,Node 包管理很复杂,包之间又有可能互相依赖, 互相引用。且存在多个版本安装混乱的问题。
这时候就又需要借助 yarn.lock 之类的工具进行管理。并且根据 yarn 官方文档说明,yarn 会忽略依赖包内的 yarn.lock,仅支持 top-level 的 yarn.lock。所以可能会导致你的 node_modules 里面充斥着各种版本,各种重复的包。
权限风险
由于引用的包都已经安装至 node_modules,并且 node 运行时无法进行任何的权限控制。导致有可能第三方包在运行的时候,会有隐私风险。比如你只是想读取本地的文件,可是它一边扫描你运行的文件,一边通过网络请求将你本地的数据抓取上传,或者修改删除。
require 需要处理多种情况
在 Y 目录下 require(X) 时:
用一幅图来开涮一下 node_modules
处理逻辑采用回调函数
const fs = require('fs');
fs.readFile('README.md', (err, data) => {
if (err) { // error handling }
else { // data handling }
});
总结
背
景
介绍
Deno 是一个可以运行 JavaScript,Typescript 的执行环境。前者能力由V8引擎提供,后者由 Rust 语言创造。
因为 Rust 支持 WebAssembly,所以可以直接使用 wasm 库和代码。
Deno
架
构
Deno的包管理
提供三种方式引入资源文件
// 从 URL 导入
import XXXX from "https://cdn.bootcdn.net/abc.js";
// 从相对路径导入
import * as Service from "./service.js";
// 从绝对路径导入
import X from "/index.js";
在 Node 当中的一些引用语法,在 Deno 当中并不得到支持。
// 模块类的引入方法
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";
// 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的权限控制
Deno 支持 Promise 进行逻辑处理
// 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 语法。
内置命令
总结
与我们
的
业务结合
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
// 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 启发而做的。
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 方式完全不同的模块管理。
可以从它的模板依赖代码看到,它完全采用的是远程的代码。
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 是一个轻量,自由的库。笔者总结的适用场景可以是:
当然作为一个还在不断发展的库,deno 还有更多的可能性,笔者期待与各位有更多的探讨。