likes
comments
collection
share

让全世界的前端开发者在一起工作

作者站长头像
站长
· 阅读数 19

在上一篇文章 关于下一代前端代码构建技术的设想 我提到了未来前端代码将以服务的形式在网络中分发,如果能够做到这一点,那么意味着不同企业不同经验的前端开发者都可以将他们的前端代码进行封装,通过服务化的方式提供给任何一个人,这不禁让我想到或许在未来全世界的前端开发者可以在一起工作,不分国界公司,按照自己的能力和经验共同构建更好的网络世界。

事实上这并不是一个新鲜玩意,从某种意义上看,NPM 和 GitHub 一定程度上实现了这个伟大理想的一部分,让顶尖的前端开发者在一起工作,不过受到 NPM 使用上的门槛限制,90% 以上的开发者只能作为 NPM 的使用者而存在,而非贡献者,但整个网络世界中构成的前端代码 99% 都是由这些使用 NPM 的开发者来编写的,顶尖开发者们开发的 NPM 包作为前端代码的基础设施而存在,从第一个 NPM 发布到现在,庞大的 NPM 生态帮助我们更好的开发应用程序,但随着前端技术趋于成熟,有价值的 NPM 包正在趋于饱和,大多数开发者可能已经数年未曾更换所使用的的基础 NPM 包了。基于 NPM 分享代码的方式对于整个前端生态来说,贡献正在逐渐降低,

事实上前端开发者一直在尝试用各种技术来分享应用层的代码,而不仅仅是基础设施,在一定规模的企业内,都会搭建自己的私有 NPM 库,通过私有 NPM 库来分享企业内部的代码,但是根据我多年使用私有 NPM 的经验,随着时间推移,大多数私有 NPM 库中 90%以上的代码都是无效的,核心问题在于,NPM 对于代码的更新有很高的要求,大多数应用层代码要符合语义化版本的要求,可以说几乎是不可能的,无论是实施成本还是对于开发者以及相关团队的要求都无法落地。

相对稳定,能够符合语义化版本的代码在企业内占比其实是比较低的,这个占比相当于基础设施代码在整个网络世界中的占比。我们编写的大部分代码依然是应用层代码,是为了满足人们对数字生活的需要而生产的代码,其特征就是高度变化且不稳定的。

如果你有多年的前端开发经验,那么回顾下 jQuery 时代,网络上有非常多的所见即所得的前端代码以 jQuery 插件的形式进行分发,确切说这可能是前端应用层代码分享的一个黄金时代,随着 jQuery 退出主流的开发库,我们很少再看到网络上有如此之多形形色色的前端组件了,逐步被基于某种 UI 框架的组件库所替代,个性被共性所取代。进入工程化时代后,前端开发者们主要聚焦在基础设施上,对于应用层代码的讨论逐步沉淀了 codepen 这样的创意平台上。

即便在 NPM 生态如此发达的今天,我们依然需要编写大量的应用层代码,甚至基于一些基础 NPM 包进行扩展,但我们很难将这些代码再以 NPM 包的形式重新分发出去。主要是因为将现有应用层代码重新封装成 NPM 的成本通常都比复用这些代码的价值要高得多。

“将应用层代码封装成 NPM 这件事怎么看都是得不偿失”

如何低成本的封装和分发应用层代码

无论是前端代码的服务化还是让更多的前端开发者能够分享自己的代码,都回避不了的一个问题就是,如何用极低的成本在现有的技术体系上分发我们的应用层代码?

这里的低成本主要体现在几乎为 0 的学习和认知成本,回想一下 JavaScript 的光荣发展历史,之所以有如此多的开发者选择 JavaScript 作为开发语言,低门槛和灵活性是首要原因,那么假设存在这种分发技术,也应该具有这两个特征,较低的使用门槛,较高的灵活性。

为此我设计了一个技术原型,我管他叫 rdecojs, rdecojs 的灵感来源于 webpack 的 mf,简单理解,你可以将 rdecojs 看成是一个不捆绑构建系统的 mf 库。下面我来解释下整个技术原型的使用流程,这中间我需要用到 CDN 托管的平台,我用的是 surge.

首先,我需要封装一段代码,并将其构建出来,例如我需要封装一个自定义的 deepmerge 方法,但我又不想完全重写,我打算在 deepmerge 这个 NPM 包上进行应用逻辑的扩展。

import deepmerge from 'deepmerge'
import { create } from '@rdecojs/core'

create('myModule', () => ({
  myDeepmerge(base, config, resolve) {
    resolve(
      deepmerge(base, config, {
        arrayMerge(target, source) {
          return source
        },
      })
    )
  },
}))

和原始的 deepmerge 相比,我增加了对 array 的逻辑处理,采用覆盖来决定如何合并 array,这是一段很小的个性化逻辑,通常在我们自己项目里能够很好的运转,但有一天你加入了其他项目组,然后发现也需要用到相同逻辑的 deepmerge 版本,你会怎么做?

可能对于有自我追求的人来说,将原有的方法抽象出来,然后构建一个 NPM 包用来管理这些 utils,嗯听起来不错,但事实上我知道大概率你会使用 CV 大法。

没错和这段逻辑的价值相比,提炼到 NPM 库实在是太笨重了,而且未必是一个好主意,日后对于这个 NPM 的维护可能会成为你或者团队的重大负担,你们得小心的进行语义化的管理,严格代码的提交和审核,事实上这是一个有进取心的软件工程团队会努力的方向,但别忘了,大多数开发者只是为了工作需要,这样笨重而严格的方式大多数人来说太麻烦了,而且即便是那些工程能力极强的团队也不可能对这种应用层的代码进行如此复杂的管理,但是需求和场景是天然存在的,CV 大法,终究不是一个好主意,至少你会为此脸红,所以别急,上述代码中我们已经完成了对这个方法的封装,并且通过构建工具构建出了一个 UMD 库,然后我们将它上传到 surge 上得到一个可访问的 CDN 地址

    project: /Users/LYN/Documents/works/rdecojs/packages/demo/dist
     domain: rdecojs.surge.sh
     upload: [====================] 100% eta: 0.0s (5 files, 294167 bytes)
        CDN: [====================] 100%
 encryption: *.surge.sh, surge.sh (245 days)
         IP: 138.197.235.123

通过上传到 surge 现在我们能直接在浏览器里加载这个脚本了。

<script src="https://rdecojs.surge.sh/index.49f960bf.js"></script>

做完这些然后你就可以调用你封装好的这个方法了

import { imc } from '@rdecojs/core'

imc('myModule')
  .myDeepmerge({ a: [1, 23] }, { b: [0] })
  .then((res) => {
    console.log(res)
  })

OK, 这就是整个技术原型的全部,无论你使用什么构建工具,你只要确保包含 create 的代码被正确的构建,那么后续步骤就仅仅是上传 CDN,然后在浏览器中加载它,最后你不用关心脚本的加载和执行顺序,在你需要用到他的时候通过 imc 调用他即可。

基于这个技术原型,前端开发者无论身处何处,都可以随时将代码封装并分享到 CDN 上,未来或许我们可以基于这样的一种技术原型,构建一个前端开发者的协作平台,每个人都可以随时分享自己的代码供他人使用,或许某一天我也能让其他国家的前端开发者来帮助我一起完成工作呢?如果可以,又何尝不可呢?

文章中技术原型 @rdecojs/core 的 GitHub 地址 github.com/kinop112365…

文章中的示例代码是实际可用的,当然你也可以自己尝试上传测试代码,通过 surge,surge 官方网站: surge.sh