2018年,我曾经在deno发布不久写过一篇《Deno不是下一代Node.js!》的文章,正好最近有一些研究,站在2021年再来看看deno。
无疑,deno改变了大家的对包管理的看法。本身deno够小,试错成本低,它确确实实引领了一个潮流方向。这个改进虽说不算新,但反响确实很好,大概是天下人苦npm(npm开玩笑的说法是:你怕吗)久已,用法简单,高效,甚至是衍生出很多关于cdn for JavaScript modules的思考。
下面,我们就一起看一下吧。
缘起
我们做了一个imove的开源项目,iMove 是一个逻辑可复用的,面向函数的,流程可视化的 JavaScript 工具库。
目前已经支持的特性
-
流程可视化: 上手简单,绘图方便,逻辑表达更直观,易于理解
-
逻辑复用: iMove 节点支持复用,单节点支持参数配置
-
灵活可扩展: 仅需写一个函数,节点可扩展,支持插件集成
-
多语言编译: 无语言编译出码限制(例: 支持 JavaScript, Java 编译出码)
使用界面如下
其实,直白点讲,就是将运营配置的一套玩法给开发用。每个节点都是函数,可视化,可配置,可组装,可导出代码,做的是很克制的。基于x6图形和json协议,可以说是以最小的投入成本拿到最大的效果,从定位上看,还是相当精准的。我们自己在业务中使用落地,无论体验还是效果,也是非常好的。
最近为了开源,小伙伴提了2个优化点:
-
双击图形,可以编辑函数,这样操作更方便。已经做完了。
-
在这个界面上做到节点或流程可测试。确实会有这个问题,如果节点可测,功能上会更加实用。
第二点,我是非常认可这的。但问题来了,如何实现呢?
每个节点的代码等价于一个 js 文件,因此你不用担心全局变量的命名污染问题,甚至可以 import 现有的 npm 包,但最后必须 export 出一个函数。需要注意的是,由于 iMove 天生支持节点代码的异步调用,因此 export 出的函数默认是一个 promise。
举例,就拿 是否登录
这个分支节点为例,我们来看下节点代码该如何编写:
import fetch from 'node-fetch'; export default async function (ctx) { return fetch('/api/isLogin') .then(res => res.json()) .then(res => { const {success, data: {isLogin} = {}} = res; return success && isLogin; }).catch(err => { console.log('fetch /api/isLogin failed, the err is:', err); return false; }); }
引申出
-
这是esm,基于es module的主流写法。
-
支持外部包导入,不然很难能够应对复杂场景。
类似的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:
const ImportHttpWebpackPlugin = require('import-http/webpack') module.exports = { plugins: [new ImportHttpWebpackPlugin()] }
然后就可以在代码直接使用了:
import React from 'https://unpkg.com/react' import Vue from 'https://unpkg.com/vue' 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: ESM loaders下一步计划 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的新的托管方式。
它的原理图。
以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.
// Set options as a parameter, environment variable, or rc file. require = require("esm")(module/*, options*/) module.exports = require("./main.js")
这是本地的做法,如果变成http import,这件事儿本地是不需要做的,把这些都交给cdn类的服务来做更合适。事实上,pika.dev/skypack.dev/jspm.io都已经做了这件事儿。
借助 http://jspm.io(或其他类似服务)来将 commonjs 转换为兼容的 esm 格式。
import cheerio from "https://dev.jspm.io/npm:cheerio/index.js";
引申一下,2个问题。
-
国内还没有类似的服务,既然有cnpm,会不会有类似的服务呢?我想会有人做的。
-
传统CDN厂商下一步也会朝着这个方向走的,要么收购,要么自建。这其实是很好的生意。一方面满足开发者的诉求,另一方面也能够为传统CDN厂商提供增量业务。它也是新基建的组成部分。
总结
deno是一个很好的创新,上面讲的import-http,esm.run或模块转化服务,可以说都是deno探索间接或直接作用的结果。
但如果说想替代Node,目前的这些特性和性能提升,还不足以替代node。Node社区在node 4之后接纳es特性之后还是很与时俱进的,cjs和esm处理曾经也很及时。那么既然时机已成熟,今天node拥抱http import还会远吗?
少抱怨,多思考,未来更美好
全文完,Node Party是纯社区技术交流,欢迎转发
如果想参与评论,请点击阅读原文链接,进入国内最专业的cnode论坛
原文链接:https://blog.csdn.net/hIZ255enyGT1O4b8/article/details/112165402?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165934458816782246424718%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165934458816782246424718&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-11-112165402-null-null.nonecase&utm_term=%E8%87%AA%E5%BB%BAcdn
原创文章,作者:优速盾-小U,如若转载,请注明出处:https://www.cdnb.net/bbs/archives/6731