如何开发了一个前端库 or 框架?

程序源代码

共 8969字,需浏览 18分钟

 · 2023-06-20

前端发展速度已经远远超出了我们的预计范围,前端基于 JS 的框架/库更是层出不穷。

那么框架与库有什么区别呢?库更多是一个封装好的特定的集合,提供给开发者使用,而且是特定于某一方面的集合(方法和函数),库没有控制权,控制权在使用者手中,在库中查询需要的功能在自己的应用中使用,我们可以从封装的角度理解库;框架顾名思义就是一套架构,会基于自身的特点向用户提供一套相当于叫完整的解决方案,而且控制权的在框架本身,使用者要找框架所规定的某种规范进行开发。

我们尝试举个例子:你想烹饪一条鱼,这时你需要一些原料,比如油、盐、醋、葱、香料以及烹饪工具等,同时鱼也是你需要的主要材料,当你聚齐所有材料时,再经过烹饪就得到成品;现在我们进行对比,其中油、盐、醋、葱、香料以及烹饪工具和鱼其实就是库,组合到一起就成了框架,成品就是最终开发好的应用,或者这样能是你更好里的理解框架与库之间的区别。

我们熟知的 React,它就是一个库,官网称是一个用于构建用户界面的 JavaScript 库。刚接触 React 的时候,在 JS 文件 中写 HTML 语法 觉得很奇妙,后来就觉得自己可不可以也搞一个库来锻炼下自己的能力呢!于是在业余时间自己通过各种摸索搞了一个迷你版 JSX,但是在数据驱动层面上遇到了一些问题,几天的辗转反侧,自己终于想明白了。我为什么先要做一个仿 React 的库呢?我能不能换一种方式来实现这种类 JSX 语法呢!我们知道 ES6 语法中有模板字符串,你可以在里面写 HTML 标签,并且在字符串中可以嵌入变量。找到了开发方向,我就开始搜索各种资料,正式进入开发库的过程。这个过程是非常痛苦的,但庆幸的是库的开发都是我一个人参与的,我可以按照我的想法去做,去完善它。

我将这个库命名为 Strve.js,为什么会这样命名呢?它其实是字符串(String)与 视图(View)的名称缩写拼接而成。它实现了在 JS 字符串中写 HTML 标签,并且可以嵌入变量,达到了数据驱动视图的效果。并且你可以灵活地分离代码块,提高工作效率。到这里你会觉得这有什么难的,使用 innerHTML 也可以实现类似的效果。效果是一样的,但是在一定场景下 DOM 性能是不同的。Strve.js 另一个定位就是一个轻量级的 MVVM 框架,你只需要关心数据操作,其他事情由 Strve.js 内部的 Virtual DOM 来处理,这也是目前优化 DOM 性能的一种常用手段。

最终,功夫不负有心人。在 2021 年 11 月 3 日发布了第一个版本 1.0.4,然后接下来就是不断地更新迭代,让它的生态更加完善,更加符合一个库或者框架的要求。中途也遇到过架构重新搭建等等情况,到目前为止,Strve.js 最新版本是 5.1.1,发布时间为 2023 年 1 月 1 日。

下面我来详细介绍下 Strve.js。

文档

Strve.js 文档是基于 VitePress 搭建,分别部署到 Github 和 Gitee 上。

  • Github 中文网址:https://maomincoding.github.io/strve-doc/zh

  • Gitee 中文网址:https://maomincoding.gitee.io/strve-doc/zh


下面,将根据文档内容分成几大模块,分享我设计这个库时的心得体会

开始

首先,我们进入开始页。尝试学习一样新的技术,最简单的就是做一个小的案例。通过这些简单的案例来进一步学习它的用法,因为往往这些最简单之处最能体现出它的核心用途。

你可以通过两种方式去使用它,一种是 ES Modules,另一种是UMD。我们先分别列举两种方式,然后统一讲一下代码结构。

现代浏览器大多都已原生支持 ES 模块。因此我们可以像这样通过 CDN 以及原生 ES 模块使用 Strve.js:

html>
<html lang="en">
 <head>
  <meta charset="UTF-8" />
  <title>Strve.jstitle>
 head>

 <body>
  <script type="module">
   import {
    h,
    setData,
    createApp,
   } from 'https://cdn.jsdelivr.net/npm/strve-js@5.1.1/dist/strve.full-esm.js';

   const state = {
    count0,
   };

   function add({
    setData(() => {
     state.count++;
    });
   }

   function App({
    return h`
      ${state.count}
      ${add}
>Add 
    `
;
   }

   const app = createApp(App);
   app.mount('#app');
  script>
 body>
html>

UMD 叫做通用模块定义规范(Universal Module Definition)。也是随着大前端的趋势所诞生,它可以通过运行时或者编译时让同一个代码模块在使用 CommonJs、CMD 甚至是 AMD 的项目中运行。未来同一个 JavaScript 包运行在浏览器端、服务区端甚至是 APP 端都只需要遵守同一个写法就行了。

你也可以选择使用