Deno: 你并不总是需要NodeJS
ztj100 2024-11-17 18:13 35 浏览 0 评论
作者:binxiong,CSIG云产一研发工作室Tech Lead
回顾Node
包管理复杂
Node包管理很复杂, 包之间又有可能互相依赖, 互相引用. 且存在多个版本安装混乱的问题.
这时候就又需要借助yarn.lock之类的工具进行管理. 并且根据yarn官方文档说明, yarn会忽略依赖包内的yarn.lock, 仅支持top-level的yarn.lock . 所以可能会导致你的node_modules里面充斥着各种版本, 各种重复的包.
权限风险
由于引用的包都已经安装至node_modules, 并且node运行时无法进行任何的权限控制. 导致有可能第三方包在运行的时候, 会有隐私风险. 比如你只是想读取本地的文件, 可是它一边扫描你运行的文件, 一边通过网络请求将你本地的数据抓取上传, 或者修改删除.
require需要处理多种情况
在 Y 目录下 require(X) 时:
- 如果 X 是内置模块,加载该模块;
- 如果 X 以 / 开头,设置 Y 为文件系统的根部 (root);
- 当 X 以 ./ , / , ../ 开头时,加载该文件或者加载该目录;
- 否则加载 node_modules 目录下的模块: LOAD_NODE_MODULES(X, dirname(Y))
用一幅图来开涮一下node_modules
处理逻辑采用回调函数
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架构
- Deno使用Rust启动
- 因为V8由C++编写, 所以通过Rust去执行C++代码来初始化V8对象. 这一部分使用Rust FFI调用rusty_v8执行
- 这样Deno就可以执行JavaScript代码了
- 运行ts的时候, 会通过内置的tsc和swc进行预编译, 并且提供一份缓存.
- Tokio提供事件处理
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的权限控制
- -allow-env= 允许环境访问,例如读取和设置环境变量。
- -allow-hrtime 允许高精度时间,高精度时间能够在计时攻击和特征识别中使用。
- -allow-net= 允许网络访问。您可以指定一系列用逗号分隔的域名,来提供域名白名单。
- -allow-ffi 允许加载动态的依赖, 注意, 也不在沙箱中运行. 谨慎使用, 并且该API并不稳定.
- -allow-read= 允许读取文件系统。您可以指定一系列用逗号分隔的目录或文件,来提供文件系统白名单。
- -allow-run= 允许运行子进程。请注意,子进程不在沙箱中运行,因此没有与 deno 进程相同的安全限制,请谨慎使用。
- -allow-write= 允许写入文件系统。您可以指定一系列用逗号分隔的目录或文件,来提供文件系统白名单。
- A, --allow-all 允许所有权限,这将禁用所有安全限制
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语法.
内置命令
- 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对象
与我们的业务结合
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项目的批量修改.
一些疑问
组件库支持情况?
支持主流库, 如lodash, i18next, billboardjs等, 官方也提供了安装地址, https://deno.land/x
如果贡献, 使用第三方库?
自行开发第三方组件很简单, 只需要上传到托管js的服务器, 或者直接放在github即可. 也可以在官方发布组件.
能否使用node_modues?
不能直接使用node_modules, 但是有一些组件库做了层级适配, 可以间接使用
既然都在使用远程依赖的文件, 如果文件被篡改怎么办? 是否安全?
官方给的解决方案是, 使用cache的lock功能, 将文件锁定deno cache --lock=lock.json --lock-write src/deps.ts
实现一个简单HTTP web 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是一个轻量, 自由的库. 我总结的适用场景可以是, 1. 脚本文件, 2. 做一个 data mock server, 3. 前端的监控或者是自动化测试脚本编写工具.
当然作为一个还在不断发展的库, deno还有更多的可能性, 我这里只是总结了几种场景.
相关推荐
- Jquery 详细用法
-
1、jQuery介绍(1)jQuery是什么?是一个js框架,其主要思想是利用jQuery提供的选择器查找要操作的节点,然后将找到的节点封装成一个jQuery对象。封装成jQuery对象的目的有...
- 前端开发79条知识点汇总
-
1.css禁用鼠标事件2.get/post的理解和他们之间的区别http超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。HTTP的工作方式是客户机与服务器之间的请求-应答协议。...
- js基础面试题92-130道题目
-
92.说说你对作用域链的理解参考答案:作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的。...
- Web前端必备基础知识点,百万网友:牛逼
-
1、Web中的常见攻击方式1.SQL注入------常见的安全性问题。解决方案:前端页面需要校验用户的输入数据(限制用户输入的类型、范围、格式、长度),不能只靠后端去校验用户数据。一来可以提高后端处理...
- 事件——《JS高级程序设计》
-
一、事件流1.事件流描述的是从页面中接收事件的顺序2.事件冒泡(eventbubble):事件从开始时由最具体的元素(就是嵌套最深的那个节点)开始,逐级向上传播到较为不具体的节点(就是Docu...
- 前端开发中79条不可忽视的知识点汇总
-
过往一些不足的地方,通过博客,好好总结一下。1.css禁用鼠标事件...
- Chrome 开发工具之Network
-
经常会听到比如"为什么我的js代码没执行啊?","我明明发送了请求,为什么反应?","我这个网站怎么加载的这么慢?"这类的问题,那么问题既然存在,就需要去解决它,需要解决它,首先我们得找对导致问题的原...
- 轻量级 React.js 虚拟美化滚动条组件RScroll
-
前几天有给大家分享一个Vue自定义滚动条组件VScroll。今天再分享一个最新开发的ReactPC端模拟滚动条组件RScroll。...
- 一文解读JavaScript事件对象和表单对象
-
前言相信做网站对JavaScript再熟悉不过了,它是一门脚本语言,不同于Python的是,它是一门浏览器脚本语言,而Python则是服务器脚本语言,我们不光要会Python,还要会JavaScrip...
- Python函数参数黑科技:*args与**kwargs深度解析
-
90%的Python程序员不知道,可变参数设计竟能决定函数的灵活性和扩展性!掌握这些技巧,让你的函数适应任何场景!一、函数参数设计的三大进阶技巧...
- 深入理解Python3密码学:详解PyCrypto库加密、解密与数字签名
-
在现代计算领域,信息安全逐渐成为焦点话题。密码学,作为信息保护的关键技术之一,允许我们加密(保密)和解密(解密)数据。...
- 阿里Nacos惊爆安全漏洞,火速升级!(附修复建议)
-
前言好,我是threedr3am,我发现nacos最新版本1.4.1对于User-Agent绕过安全漏洞的serverIdentitykey-value修复机制,依然存在绕过问题,在nacos开启了...
- Python模块:zoneinfo时区支持详解
-
一、知识导图二、知识讲解(一)zoneinfo模块概述...
- Golang开发的一些注意事项(一)
-
1.channel关闭后读的问题当channel关闭之后再去读取它,虽然不会引发panic,但会直接得到零值,而且ok的值为false。packagemainimport"...
- Python鼠标与键盘自动化指南:从入门到进阶——键盘篇
-
`pynput`是一个用于控制和监控鼠标和键盘的Python库...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)