挑战21天手写前端框架 day4 框架的本质是命令行工具?

简介: 挑战21天手写前端框架 day4 框架的本质是命令行工具?

image.png



阅读本文需要 7 分钟,编写本文耗时 2.5 小时。


其实现代前端框架的本质就是一个使用 js 编写的 node 命令行工具(cli)

比如 umi、 react-script、vue-cli、ng、ionic 等,我们在使用他们进行项目开发的时候,都是使用如 umi dev 的命令去启动我们的开发服务,这里有两个关键字,“启动” 和 “服务”。

关于开发服务,我们会在明天的内容中说明,今天我先简单的介绍一下 cli 的开发过程。



使用 node 执行 js

新建一个 js 文件 src/index.js

console.log('Hello Malita!');
复制代码


在终端中执行 node src/index.js

Hello Malia!
复制代码

我们可以看到在控制态中打印了 Hello Malia!


使用命令

每次执行都要输入 node src/index.js 有些太长了,而且有时候文件名字取的复杂了,也很不好记忆,因此我们可以在 package.json 中增加使用脚本入口 scripts

"scripts": {
        "hello": "node src/index.js"
    },
复制代码


这样我们只需要在终端中使用 npm run hello 的命令,就相当于 node src/index.js

值得注意的是 hello 只是我们取的速记别名,你可以使用任意的别名,所以在使用 scripts 的时候,我们需要关注的是别名真正对应的脚本。


这个是在当前项目中有效的命令,那如果是不在当前项目中的命令,而是在第三方依赖中的命令的话,又该如何声明呢?


声明自己的命令

声明命令不是什么黑魔法,这就是 node 的用法说明,只要在 package.json 里面配置上 bin 属性就可以实现。

"bin": {
        "malita": "./bin/malita.js"
    },
复制代码


编写 bin/malita.js

注意开头要添加脚本的解释程序,比如我们这里使用的是 node

#!/usr/bin/env node
console.log('Hello Malia!')
复制代码


bin 中配置的 malita 就是我们提供给其他用户的命令速记符号。

这个“速记符”是提供给其他用户使用的,我们本地开发的时候,可以使用 package.jsonscripts 中的命令即可。


使用 link 调试

bin 声明的命令需要被安装到 node_modules.bin 目录下才能找到,比如我们在当前项目直接执行 malita 会提示我们 sh: malita: command not found

因此我们可以新建一个测试仓库,来关联测试。

$ mkdir examples/app
$ cd examples/app
$ npm init -y
$ npm link malita
$ npx malita
Hello Malia!
复制代码


npx 是 npm 自带的一个工具,它会自动查找当前依赖包中的可执行文件,如果没找到,就会找你全局安装的命令,如果还是没找到,那它就会从远程服务器上下载你需要的依赖。

如果你按上面的步骤执行,看到控制台有正确打印,说明你的配置都是正确的。这样你就可以继续阅读下面的内容了。


使用 pnpm monorepo 自动 link

平时开发测试都要手动 link 比较麻烦,有时候还容易忘记执行 link,而且由于 link 的绑定与你执行 link 的目录相关的。像我有个同名包,有多个版本的本地仓库,我经常忘记我当前 link 的哪个仓库。所以我们需要引入一种新的方式,来帮助我们自动执行 link,我们称之为 workspace


我们使用最近比较流行的 pnpm 来完成。

你可以通过命令安装 pnpm

curl -fsSL https://get.pnpm.io/install.sh | PNPM_VERSION=7.0.0-rc.2 sh -
复制代码


更多安装方法,请查看 pnpm 官网

新建配置文件 pnpm-workspace.yaml

packages:
  - 'packages/*'
  - 'examples/*'
复制代码


声明我们的 packagesexamples 下的包,都是我们的 workspace 。在这里面的所有子包,都可以被整个工作区中的其他包引用。 就算 npm 上不存在我们的子包,只要我们的工作区内存在,就不会出现找不到子包的问题。 还有一个好处就是不管 npm 上我们的子包是什么版本,开发的时候,我们都可以直接使用我们本地的代码。


不像单包管理那样,还要等子包修改完,编译构建上传到 npm 之后,我们再下载使用它。

新建 packages/malita 文件夹,将我们前面创建的 binsrcpackage.json 移动到这里面。


修改根目录下的 package.json ,增加 "private": true,

examples/app 中使用 malita

{
    "name": "@examples/app",
    "scripts": {
        "start": "malita"
    },
    "dependencies": {
        "malita": "workspace:*"
    }
}
复制代码


然后在根目录下执行安装,并启动用例,查看效果

$ pnpm i
// 等待安装完成
$ cd examples/app
$ pnpm start
Hello Malia!
复制代码


如果控制台成功打印,那说明你前面的步骤都正确执行了。

到此处,你应该要很清晰的知道,上面这个打印是如何被执行的,如果你有疑问或者疑惑,建议你再回头看看文章,或者在评论区讨论



编写帮助命令

前面讲了这么多,只是为了让读者清晰的知道整个代码逻辑是如何被执行的,从现在开始我们才真正的进入框架的开发工作中。

命令行开发毕竟不是我们的重点,所以这里我们使用一个 完成的 node 命令行解决方案 commander.js


commander

$ cd packages/malita/  
$ pnpm i commander
dependencies:
+ commander 9.1.0
复制代码


编写我们的入口文件 bin/malita.js

#!/usr/bin/env node
const {
    program
} = require('commander');
program
    .version(require('../package.json').version, '-v, -V', '输出当前框架的版本')
    .description('这是21天短文,挑战手写前端框架的产物框架')
    .usage('<command> [options]')
    .parse(process.argv)
复制代码


在用例中执行

$ cd examples/app
$ npx malita -V
0.0.1
复制代码


增加 help 命令

program.command('help')
    .alias('-h')
    .description('帮助命令')
    .action(function(name, other) {
        console.log(`
这是21天短文,挑战手写前端框架的产物框架 malita
支持的命令:
  version, -v,-V 输出当前框架的版本
  help,-h 输出帮助程序
Example call:
    $ malita <command> --help`)
    }).parse(process.argv);
复制代码


在用例中执行

$ cd examples/app
$ npx malita help
这是21天短文,挑战手写前端框架的产物框架 malita
支持的命令:
  version, -v,-V 输出当前框架的版本
  help,-h 输出帮助程序
Example call:
    $ malita <command> --help
复制代码


将新的框架版本发布到 npm 上

$ cd packages/malita 
$ npm publish
npm ERR! code E403
npm ERR! 403 403 Forbidden - PUT https://registry.npmjs.org/malita - You cannot publish over the previously published versions: 0.0.1.
复制代码


这个错误是说已经存在一个这个版本的包了,npm 上的包的每一次更新都需要对应一次版本号的提升,所以我们修改 packages/malita/package.json 中的 "version": "0.0.2", 之后再次执行发包

$ cd packages/malita 
$ npm publish
npm notice 
npm notice 📦  malita@0.0.2
npm notice === Tarball Contents === 
npm notice 705B bin/malita.js
npm notice 581B package.json 
npm notice 32B  src/index.js 
npm notice === Tarball Details === 
npm notice name:          malita                                  
npm notice version:       0.0.2                                   
npm notice filename:      malita-0.0.2.tgz                        
npm notice package size:  800 B                                   
npm notice unpacked size: 1.3 kB                                  
npm notice shasum:        60c926f7714570a9a5228179d5a3df383680bc70
npm notice integrity:     sha512-VifOKdtdspHlS[...]dyA+jFEwR9Nhw==
npm notice total files:   3                                       
npm notice 
+ malita@0.0.2
复制代码


到这里,你就成功的在 npm 上发布了一个拥有一个 help 命令的 cli 工具了,后续我们会完善它,使它成为一个基本可用的前端框架。


本篇文章旨在帮助你了解前端框架命令的执行流程,这在你遇到 Bug ,需要定位问题的时候,你就能有一个很清晰的定位步骤。 当你知道它是如何执行的,你甚至可以根据这个思路,去阅读你现在项目中所使用的前端框架的源码,比如 vue-cli 或者 umi。


今天的内容就到这里了,明天就会真正进入我们的框架开发工作中。前期我总共花了 4 天的篇幅来详细的说明了,编写框架的基础知识,有大部分的内容都属于常识性的知识点。 正所谓磨刀不误砍柴工,希望这些简单常识,对你有所帮助。


感谢观看,如果你有任何疑问,欢迎在评论区和我互动。


源码归档

目录
相关文章
|
9天前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
33 9
|
22天前
|
人工智能 前端开发 JavaScript
前端架构思考 :专注于多框架的并存可能并不是唯一的方向 — 探讨大模型时代前端的分层式微前端架构
随着前端技术的发展,微前端架构成为应对复杂大型应用的流行方案,允许多个团队使用不同技术栈并将其模块化集成。然而,这种设计在高交互性需求的应用中存在局限,如音视频处理、AI集成等。本文探讨了传统微前端架构的不足,并提出了一种新的分层式微前端架构,通过展示层与业务层的分离及基于功能的横向拆分,以更好地适应现代前端需求。
|
3天前
|
前端开发 JavaScript API
前端界的秘密武器:掌握这些框架,让你轻松秒杀99%的同行!
前端开发日新月异,掌握几个明星框架如React、Vue.js和Angular,不仅能让工作更得心应手,还能轻松超越同行。React以高效的虚拟DOM和组件化著称;Vue.js简洁易懂,灵活性高;Angular提供全面的解决方案,适合大型应用。此外,轻量级的Svelte也值得关注,其编译时处理设计提升了应用性能。掌握这些框架,结合深刻理解和灵活运用,助你在前端领域脱颖而出。
17 9
|
30天前
|
JavaScript 前端开发 API
Vue.js:现代前端开发的强大框架
【10月更文挑战第11天】Vue.js:现代前端开发的强大框架
64 41
|
14天前
|
前端开发 JavaScript
Bootstrap Web 前端 UI 框架
Bootstrap 是快速开发 Web 应用程序的前端工具包。
30 3
|
21天前
|
JavaScript 前端开发 测试技术
前端全栈之路Deno篇(五):如何快速创建 WebSocket 服务端应用 + 客户端应用 - 可能是2025最佳的Websocket全栈实时应用框架
本文介绍了如何使用Deno 2.0快速构建WebSocket全栈应用,包括服务端和客户端的创建。通过一个简单的代码示例,展示了Deno在WebSocket实现中的便捷与强大,无需额外依赖,即可轻松搭建具备基本功能的WebSocket应用。Deno 2.0被认为是最佳的WebSocket全栈应用JS运行时,适合全栈开发者学习和使用。
|
21天前
|
缓存 前端开发 JavaScript
前端serverless探索之组件单独部署时,利用rxjs实现业务状态与vue-react-angular等框架的响应式状态映射
本文深入探讨了如何将RxJS与Vue、React、Angular三大前端框架进行集成,通过抽象出辅助方法`useRx`和`pushPipe`,实现跨框架的状态管理。具体介绍了各框架的响应式机制,展示了如何将RxJS的Observable对象转化为框架的响应式数据,并通过示例代码演示了使用方法。此外,还讨论了全局状态源与WebComponent的部署优化,以及一些实践中的改进点。这些方法不仅简化了异步编程,还提升了代码的可读性和可维护性。
|
21天前
|
前端开发 JavaScript 中间件
前端全栈之路Deno篇(四):Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
Deno 是由 Node.js 创始人 Ryan Dahl 开发的新一代 JavaScript 和 TypeScript 运行时,旨在解决 Node.js 的设计缺陷,具备更强的安全性和内置的 TypeScript 支持。本文介绍了如何使用 Deno 内置的 `Deno.serve` 快速创建 HTTP 服务,并详细讲解了 Oak 框架的安装和使用方法,包括中间件、路由和静态文件服务等功能。Deno 和 Oak 的结合使得创建 RESTful API 变得高效且简便,非常适合快速开发和部署现代 Web 应用程序。
|
27天前
|
前端开发 JavaScript 开发者
qiankun(乾坤)微前端框架简介
qiankun(乾坤)微前端框架简介
78 1
|
1月前
|
前端开发 JavaScript 开发者
探索现代Web前端技术:React框架入门
【10月更文挑战第9天】 探索现代Web前端技术:React框架入门