6

2021再看Deno

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ%3D%3D&%3Bmid=2650418629&%3Bidx=1&%3Bsn=3271ad66fbf152535d074fb27920040f
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

UBVzemq.gif!mobile

2018年,我曾经在deno发布不久写过一篇《Deno不是下一代Node.js!》的文章,正好最近有一些研究,站在2021年再来看看deno。

无疑,deno改变了大家的对包管理的看法。本身deno够小,试错成本低,它确确实实引领了一个潮流方向。这个改进虽说不算新,但反响确实很好,大概是天下人苦npm(npm开玩笑的说法是:你怕吗)久已,用法简单,高效,甚至是衍生出很多关于CDN for JavaScript modules的思考。

uemaUr7.jpg!mobile

下面,我们就一起看一下吧。

缘起

我们做了一个imove的开源项目,iMove 是一个逻辑可复用的,面向函数的,流程可视化的 JavaScript 工具库。

目前已经支持的特性:

  • 流程可视化: 上手简单,绘图方便,逻辑表达更直观,易于理解

  • 逻辑复用: iMove 节点支持复用,单节点支持参数配置

  • 灵活可扩展: 仅需写一个函数,节点可扩展,支持插件集成

  • 多语言编译: 无语言编译出码限制(例: 支持 JavaScript, Java 编译出码)

使用界面如下:

f2ANvye.png!mobile

其实,直白点讲,就是将运营配置的一套玩法给开发用。每个节点都是函数,可视化,可配置,可组装,可导出代码,做的是很克制的。基于x6图形和json协议,可以说是以最小的投入成本拿到最大的效果,从定位上看,还是相当精准的。我们自己在业务中使用落地,无论体验还是效果,也是非常好的。

最近为了开源,小伙伴提了2个优化点:

  1. 双击图形,可以编辑函数,这样操作更方便。已经做完了。

  2. 在这个界面上做到节点或流程可测试。确实会有这个问题,如果节点可测,功能上会更加实用。

第二点,我是非常认可这的。但问题来了,如何实现呢?

每个节点的代码等价于一个 js 文件,因此你不用担心全局变量的命名污染问题,甚至可以 import 现有的 npm 包,但最后必须 export 出一个函数。需要注意的是,由于 iMove 天生支持节点代码的异步调用,因此 export 出的函数默认是一个 promise。

举例,就拿 是否登录 这个分支节点为例,我们来看下节点代码该如何编写:

  1. import fetch from 'node-fetch';

  2. exportdefault async function(ctx){

  3. return fetch('/api/isLogin')

  4. .then(res => res.json())

  5. .then(res =>{

  6. const{success, data:{isLogin}={}}= res;

  7. return success && isLogin;

  8. }).catch(err =>{

  9. console.log('fetch /api/isLogin failed, the err is:', err);

  10. returnfalse;

  11. });

  12. }

引申出:

  1. 这是esm,基于es module的主流写法。

  2. 支持外部包导入,不然很难能够应对复杂场景。

类似的jsbin,或codepen,或codesandbox,可以使用webpack的off-line插件实现,也可以采用webide初始化安装模块来实现,但这并不是好的方式。imove是要兼容浏览器和node的,直接运行,不需要本地安装npm包,也能够在node里完美运行。这就导致,我们必须要往http import方向思考问题。System.js就是一个极好的选择。

import-http

如果你去看deno链接外部代码文档(https://deno.land/manual/linkingtoexternal_code),它的做法是通过--allow-net参数选项,可以让deno 的runtime可以下载imports并将其缓存在磁盘上。

这其实只是缓存在系统目录中,比如mac上是$HOME/Library/Caches/deno。其实并没有啥本质提升。

通过代码地址来引用代码,确实是很爽的一件事儿。

No more node_modules bloat, no dependency to install.

在node世界里,也有人实现了类似的机制,即https://github.com/egoist/import-http。它是通过webpack/rollup编译时处理的。

看具体用法

先配置webpack.config.js:

  1. constImportHttpWebpackPlugin=require('import-http/webpack')

  2. module.exports ={

  3. plugins:[newImportHttpWebpackPlugin()]

  4. }

然后就可以在代码直接使用了:

  1. importReactfrom'https://unpkg.com/react'

  2. importVuefrom'https://unpkg.com/vue'

  3. console.log(React,Vue)

原理: 通过webpack的compiler.resolverFactory.hooks.resolver解析import-http-resolver,即import里带有http和https的。 然后通过fileModuleCache和httpCache对下载的内容进行缓存。

其实,Node.js做这事儿也是很简单的。只要在https://github.com/nodejs/node/tree/master/lib/internal/modules/esm目录里,实现下载和缓存就可以解决。可是,历史包袱过重,想做到no filesystem imports of any kind from https sources,还是有一段路要走的。不过这块,也是大家能够参与贡献Node.js源码的很好的点。

  • module:ES Mloaders 下一步计划

    https://github.com/nodejs/node/issues/36396

  • 官方工作组 https://github.com/nodejs/modules

支持第三方ESM loader也快了,大家拭目以待吧,用法类似于下面的

node-dev --experimental-loader ts-node/esm/transpile-only ./index.ts

esm.run

国外还有一个服务,名为esm.run,它的定位是:”A New-Age CDN for JavaScript modules“。这话说的已经相当直接了,它就是重新定义基于CDN的JavaScript modules的新的托管方式。

它的原理图。

Jve6jq3.png!mobile

以npm和github作为源,同步到亚马逊s3上,继而代理到各种CDN,为用户提供服务。

cjs to esm

很早就有了cjs转esm的工具。比如https://github.com/standard-things/esm,自己实现大量polyfill,过渡态,尝试还行,早晚还是要回归到内核中的。

The brilliantly simple, babel-less, bundle-less ECMAScript module loader.
  1. // Set options as a parameter, environment variable, or rc file.

  2. require=require("esm")(module/*, options*/)

  3. module.exports =require("./main.js")

这是 本地的做法,如果变成http import,这件事儿本地是不需要做的,把这些都交给cdn类的服务来做更合适。 事实上,pika.dev/skypack.dev/jspm.io都已经做了这件事儿。

借助 http://jspm.io(或其他类似服务)来将 commonjs 转换为兼容的 esm 格式。

  1. import cheerio from"https://dev.jspm.io/npm:cheerio/index.js";

引申一下,2个问题。
  1. 国内还没有类似的服务,既然有cnpm,会不会有类似的服务呢?我想会有人做的。

  2. 传统CDN厂商下一步也会朝着这个方向走的,要么收购,要么自建。这其实是很好的生意。一方面满足开发者的诉求,另一方面也能够为传统CDN厂商提供增量业务。它也是新基建的组成部分。

总结

deno是一个很好的创新,上面讲的import-http,esm.run或模块转化服务,可以说都是deno探索间接或直接作用的结果。

但如果说想替代Node,目前的这些特性和性能提升,还不足以替代node。Node社区在node 4之后接纳es特性之后还是很与时俱进的,cjs和esm处理曾经也很及时。那么既然时机已成熟,今天node拥抱http import还会远吗?

✿    拓展阅读

3Qjmuyq.png!mobile

uy22Ura.png!mobile

zeIzYjJ.png!mobile

作者| 狼叔

编辑| 橙子君

出品| 阿里巴巴新零售淘系技术

veE3IrM.jpg!mobile

u2IBfaQ.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK