维护8年的前端开源项目长啥样?

49,160 阅读6分钟

今天用了下自己的开源小工具 Pxer 来下载了些图片,临近年终,简单算算,这个开源项目从 2014年6月 至今已经有了 8年半 的历史了,也收获了超过 900 颗 Star

8年半前,那是 jQuery 和 BootStarp 大行其道的时代,前端主流的编程思想也与现在大相庭径

在这8年半间,我持续更新我的开源项目 Pxer,也不断的引入一些新的前端时髦的东西,但是历史包袱大家懂得都懂,不是那么好彻底抛弃的。不过另一方面,我们也可以通过这些“历史包袱”来简单窥探一下前端发展的冰山一角

所以今天来大家简单读读代码,看看8年前的思维方式,对比对比现在的主流解决方案来更好的理解——为什么现在的主流方案是这个样?

简单的背景介绍

Pxer 是一个工具,会在 Pixiv.net 这个网站额外生成一个 UI 面板来提供一些额外功能。类似于,在B站添加一个按钮让你能够直接下载视频和封面(B站不提供的功能)

image.png

运行方式

浏览器书签

Pxer 的第一版的发布代码长这样,是在百度贴吧发布的

image.png

怎么样?是不是看不懂要要怎么用?

这里就要提到一个浏览器非常有趣的特性了:

当你存书签时,不仅仅可以存 http: 打头的书签,你还可以存 javascript: 打头的书签,然后点击书签,你就能运行这段代码了。

不信你试试存下面的代码为书签,然后点击书签

javascript: alert('Hello Peanut Pie')

油猴 Greasemonkey

存书签的方式你可能觉得太麻烦了,确实,也有人是这么想的,因此有了“油猴”浏览器扩展(Greasemonkey / Tampermonkey)

油猴是一个浏览器插件,你可以安装JS脚本进油猴,然后油猴会根据域名,来自动的帮你运行你的 JavaScript 代码

因此,现在 Pxer 的安装代码大概是长这样的:

// ==UserScript==
// @name           Pxer
// @include        https://www.pixiv.net*
// ==/UserScript==
javascript: void(function() {

window['PXER_URL'] = 'https://pxer-app.pea3nut.org/';

// add enter point script in page
document.documentElement.appendChild(
    document.createElement('script')
).src = PXER_URL + 'launcher.js?' + (+new Date);

}());

(完整代码见 pxer-app.pea3nut.org/pxer.user.j…

读一读代码,你就会大概猜到油猴是如何工作的——当用户打开https://www.pixiv.net*的网站时,自动运行上面的代码,然后 Pxer 的操作界面就出现了!

目前油猴也是当前 Pxer 的推荐安装方式,你可以在 Pxer 的官网来找到详细的步骤说明

浏览器扩展 Extension

现在有一个更好的实现方式——浏览器扩展。这样能获得更好的性能和权限,但是8年前的浏览器扩展有个致命的问题:

——各家浏览器的扩展接口大相庭径(而且 Chrome 的扩展商店上架还要钱!)

这个问题在今天得到了缓解:Mozilla 推出了一个浏览器扩展规范——WebExtensions

目前 Edge、Firefox 的扩展是完全遵从这个规范的。同时,这个规范也与 Chrome 的扩展接口非常类似,因此你可以基于 WebExtensions 接口来开发扩展,然后非常简单去兼容全部浏览器——但是这在8年前是不可能的!

Pxer 并没有赶上这个好时候,而时至今日的我也没有勇气去开坑,把 Pxer 从油猴的方式迁移到 WebExtensions 的方式

项目打包

依赖次序

当你的项目大起来,你迫切的需要一个工具来帮助你组织依赖——你也不想有一个几万行JS文件吧?

核心诉求就是:文件加载的先后次序问题。那么 Pxer 是如何解决的呢?要知道,8年前可没这么好用的 Webpack 给你用。那时 Webpack 刚刚发布 1.0.0 版本不久,用户和中文资料有多少大家懂得都懂

下面是 2017 年的 Pxer 主 App 目录

image.png

github.com/FoXZilla/Px…

什么?你问文件中间的数字是干嘛的?当然是确定文件加载顺序了~

简单来说,我写了个脚本,会先自动找数字最小的文件,比如PxerEvent.-1.class.js就会被先加载,然后不带数字的默认是0,然后加载PxerFilter.class.js,然后是PxerThread.1.class.js,以此类推

生产编译

而编译部分就更加简单粗暴了,直接按次序Fs.readFileSync(把文件读到内存)后Fs.writeFileSync(把内存内容直接写入成文件)

var fileList =[];
for(let array of PxerUtility.getAllFile(Join(__dirname,'../src/app/class/'))){
    fileList.push(...array);
};
Fs.writeFileSync(
    Join(__dirname,'../dist/pxer-core.js'),
    Buffer.concat(fileList.map(path=>Fs.readFileSync(path)))
);

github.com/FoXZilla/Px…

然后就可以把这个“生成出来的大文件”丢到生产环境给用户使用了~

开发编译

但是此时依旧有个问题,我总不能改一行代码然后先打包才能看效果吧?这也太麻烦了?Webpack 还有 dev-server 呢~

Pxer 也有!

下面是 Pxer 在开发阶段的编译后的代码

// 要加载的文件
const appClass =[
    [
        "src/app/class/PxerData.-1.js",
        "src/app/class/PxerEvent.-1.class.js"
    ],
    [
        "src/app/class/PxerFilter.class.js",
        "src/app/class/PxerHtmlParser.class.js",
        "src/app/class/PxerPrinter.class.js"
    ],
    [
        "src/app/class/PxerThread.1.class.js"
    ],
    [
        "src/app/class/PxerThreadManager.2.class.js"
    ],
    [
        "src/app/class/PxerApp.3.class.js"
    ]
];


// 过程化载入文件
var Flow = Promise.resolve();


// 加载pxer-app

// 加载无关紧要的资源
Flow = Flow.then(() => execPromise(linkResource, createResource));
// 加载pxer-app class
Flow = Flow.then(() => execPromise(appClass, createScript));
// 加载UI JavaScript
Flow = Flow.then(() => execPromise(viewScripts, createScript));

上面的文件是自动生成的,脚本会:

  1. 读取目录里的文件
  2. 根据文件中的数字(PxerThreadManager .2. class.js)排序,分组
  3. 拉起一个 Http Server,然后将源文件(未打包之前)加载进浏览器

这样一来,当我改动磁盘上的文件,不需要重新编译打包,直接刷新浏览器页面就能看到自己的改动了~

对比 Webpack

Pxer 项目在 build/ 目录有9个文件来承担各种打包编译的工作,这些逻辑全都是我原创的,但是你会发现历史真是惊人的相似——我几乎是实现了一个简易版的 Webpack

打包步骤Webpack 的实现我的实现
确定依赖次序require/import 语句文件名中的数字比大小
生产编译用 loaders 读文件,然后根据配置生成文件按序读取所有文件,合并成一个大文件
开发编译webpack-dev-server拉起一个 Http Server,然后编译一个能动态加载代码的文件

当然,Webpack 还有一个非常好用的功能——热加载 Hot Load,可以不刷新浏览器的加载新文件,这个功能 Pxer 的编译系统是没有的

要是我早出生5年...

后记

现在读读8年前自己写的东西——诡异的 Code Style、用读文件的方式来编译打包、用functionName.prototype['xxx'] = function () {} 来构建类。一股浓浓的“屎山”味儿扑鼻而来

但是要知道,这些东西在8年前,可是时髦到不行~!

关于作者与转载

这里是【花生派】,一只喜欢写东西的程序员。我常常在黑夜中注视着自己的瞳孔,与自己独处,写下一段又一段的文字

如果你对我感兴趣,可以在这里找到我:

本文可随意转载,转载时需满足以下要求:

  1. 请保持原文转载,不得做任何改动
  2. 转载时请告诉我下。比如说在我的文章下留言,或给我发邮件626954412#qq.com均可,能让我知道就ok。不用等我回复,打完招呼后直接转就行
  3. 不要转载到知乎、掘金,我会自己投