当前位置: 首页 > news >正文

前端架构: 从vue-cli探究脚手架原理

从使用角度理解什么是脚手架

  • 脚手架本质是一个操作系统的客户端
    • 在终端中去执行一个命令,这个命令本身它就是一个客户端
    • 我们其实可以把脚手架理解为操作系统的一个客户端
    • 通过命令去执行它的时候,这个命令往往是这样的一个构造,如下
  • 比如:要创建一个vue的项目的时候, $ vue create vue-test-app
    • 上面这条命令由3个部分组成
      • 主命令: vue
      • command: create
        • 这个 command 是子命令,实际上它向脚手架(主命令)发送一个请求
        • 这个请求,让我们的脚手架帮我们完成一个动作,完成这个动作,就是create创建项目
      • command的param: vue-test-app
        • 建什么项目呢?看这第三个参数,在command后面,又加了一个空格,输入了一个参数
    • 这个命令输入完以后,脚手架会给我们一定的反馈, 比如说会让我们做一些选择,或者会帮我们执行一些操作等等
    • 它表示创建一个vue项目,项目名称为 vue-test-app
  • 以上是一个较为简单的脚手架命令,但实际场景往往更复杂,比如:
    • 当前目录已经有文件了,我们需要覆盖当前目录下的文件,强制进行安装 vue 项目,此时我们就可以输入
    • $ vue create vue-test-app --force
      • --force 叫做 option, 用来辅助脚手架确认在特定场景下用户的选择(可以理解为配置)
      • 如果加入了 --force,就等于告诉脚手架创建项目的时候,可以强制进行覆盖
      • 如果没加 --force, 那么脚手架的执行就会中断。因为你没有强制覆盖,而我当前又有文件,所以我就会中断
      • 其实 --force 可以理解为 --force true, 简写为:--force-f
  • 还有一种场景, 通过 vue create 创建项目时,会自动执行 npm install 帮用户安装依赖
    • 如果我们使用淘宝源来安装,就可以输入命令 vue create vue-test-app --force -r https://registry.npm.taobao.org
    • 这里的 -r 也是 option, 它与 --force 不同的是它使用 -,并且使用简写
    • 这里 -r 也可替换成 --registry,同时,我们可以通过 vue create --help 来查看其他可用命令
    • -r https://registry.npm.taobao.org 后面的 https://registry.npm.taobao.org 成为 option的param

脚手架原理

  • 我们需要理解输入了 $ vue create vue-test-app 之后,为什么会发生一系列的事情

  • 我们先要理解整个 vue 脚手架的体系,如下图

  • 通过 $ which vue 可看到 /usr/local/bin/vue, 这里的vue其实是一个软连接
    • 参考:vue -> …/…/…/Users/xxx/.config/yarn/global/node_modules/.bin/vue
    • 前面的 vue 其实执行的就是后面路径里的vue命令
  • 程序员在终端中输入 $ vue create vue-test-app
  • 终端解析出 vue 命令
  • 终端在环境变量中找到 vue 命令
  • 终端根据 vue 命令链接到实际文件 vue.js
  • 终端利用 node 执行 vue.js
  • vue.js 解析 commond / options
  • vue.js 执行 commond
  • 执行完毕,退出

从应用角度开发

  • 以 vue-cli 为例开发一个脚手架

    • 比如:/Users/johnny/.config/yarn/global/node_modules/@vue/cli
  • 其目录结构

    LICENSE
    README.md
    bin
    lib
    node_modules
    package.json
    
  • 需要开发一个 npm 项目,该项目中应包含一个 bin/vue.js 文件,并将这个项目发布到 npm

  • 将 npm 项目安装到 node 的 lib/node_modules,或者如: /…/yarn/global/node_modules

  • 在 node 的 bin 目录下配置 vue 软链接指向 lib/node_modules

  • 在执行vue命令的时候,就可以找到 vue.js 进行执行,这样一个板顶关系,在package.json中

    {"bin": {"vue": "bin/vue.js"}
    }
    
  • 这个就是 vue 和 vue.js 之间的绑定关系

  • 这就是为什么全局安装 @vue/cli 后会添加的命令为 vue

  • $ npm i -g @vue/cli 全局安装 @vue/cli 时发生了什么?

    • 在安装时,会把当前npm包下载到 lib/node_modules
      • 或者如: /…/yarn/global/node_modules 下
    • 之后解析 package.json 中的 bin 属性
    • 创建一个软连接 /usr/local/bin/vue 指向 /../yarn/global/node_modules/@vue/cli/bin/vue.js
  • 执行vue命令时,发生了什么?为何 vue 指向了 js 文件,却可以通过 vue 命令执行它

    • 操作系统,会根据 $ which vue 中的 vue 路径找到 vue执行文件,如果 vue 命令不存在,会报出 command not found 的提示
    • 这个vue执行路径其实是一个软链接,通过这个软连接找到真实的 vue地址,对应的就是 上述 /…/bin/vue.js
    • 这个 vue.js 是一个 js文件,即使有执行权限,也不可直接执行,需要一个 node 的解释器,就是类似 node /…/bin/vue.js
    • 但是很明显,在执行vue命令时,并没有冠以 node 的前缀,直接进入 /…/yarn/global/node_modules/@vue/cli/bin/vue.js
    • 可看到,最顶部有一个声明 #!/usr/bin/env node 这个声明可以直接让 xx.js 文件直接在操作系统执行
    • 意思是,告诉操作系统,在直接调用这个文件的时候,到环境变量中去找 node 命令,类似的,如果是个python文件,将node修改成 python
    • /usr/bin/env 会列出所有环境变量,在这个环境变量列表中找到 node 命令
    • 通过 node 命令来执行这个 js 文件
    • 因此,任何js文件,只要在文件顶部加上这个声明,即可 直接执行 (这里限制在 unix 系统)
    • 此时, ./xx.js 等价于 node xx.js
    • 注意,#!/usr/bin/env node 这样写的好处是
      • 无需关注每一个电脑环境下的node路径
      • 这个也可替换成具体的node路径也是一样的,但是会非常的麻烦,而且换个环境可能就不能用了
      • 所以,还是采用这种方式来处理
  • 现在我们想要用 mycommand (这个是我们自定义脚手架随意举例) 指向 xx.js,就可以通过创建软链接的方式来处理

    • 进入到 /usr/local/bin 目录
    • 创建软链接 $ ln -s /../xx.js mycommand
      • 注意,这里的 /…/xx.js 是当前脚本的路径,替换成自己的即可
    • 可看到当前目录下有一个 imooc 的文件
    • 此时,在系统内任意位置,只需要执行 mycommand 即可运行 xx.js
  • 这个就是我们自定义的脚手架 mycommand 的基本设定

最后,描述一下脚手架命令执行的一个整个过程

脚手架的本质是操作系统上的一个客户端

  • 可以发现脚手架执行起来的过程和前端开发的应用是非常不一样的
  • 其实它和web应用从本质上来讲,没有关系
  • 它们的联系仅仅是脚手架和开发的web应用都是通过 js 这个语言来进行编写的
  • 但其实脚手架它其实是操作系统当中的一种机制
  • 执行脚手架的时候,它其实是被作为一个操作系统上的可执行文件来进行执行的
  • 所以可以说我们开发的脚手架就是操作系统上的一个客户端
  • 我们的脚手架它本质执行起来时候,是依靠 node 这个命令
  • node 是一个操作系统客户端,而我们的 xx.js 仅仅是node的一个参数
  • 换句话说,仅仅是把一个参数注到 node 当中,类似的可以这样 node -e console.log(1) 这样也可以执行
  • 也就是说脚手架是操作系统的客户端,其本质并不是说 xx.js 是一个客户端,而是node本身它是一个客户端
  • 在windows中,node 是 node.exe
  • 在mac中,node 是 node* (*代表可执行文件)
  • 当去执行 node xx.js 的时候,其实是把 xx.js 中的代码变成一个字符串传入到node中
  • 然后 node 对这些字符串进行解析,把它当成一个可执行程序进行执行
  • 这些逻辑全部是预设好的,预设好的逻辑就存放在这个node的可执行文件当中
  • 所以脚手架是客户端,其本质是因为node本身就是客户端

脚手架和在PC上面安装的其他应用或者软件的区别

  • 本质来说没有区别,在操作系统上安装了软件,windows上都是 exe 后缀?
  • 在 macos 上面都是可执行文件,所以本质没有区别
  • 它们的区别仅仅是安装的一些软件会提供一个GUI,像当前终端一样,它会提供一个GUI
  • 而我们的 node 并没有提供 GUI
  • 我们的node是直接通过命令行的方式传入参数来进行执行,仅仅是这样的一个差别
  • 如果想在 nodejs 当中去展示GUI有可能吗?
    • 完全可能我们只需要去调用操作系统的GUI绘制API就可以绘制出窗口来
    • 所以脚手架本质它其实就是个客户端。但注意, 不是我们编写的代码是客户端,而是node本身是客户端

为 node 脚手架创建别名

  • 方式 1,就是通过编写一个软链接,其本身会链接到我们自己编写的一个代码文件上
  • 方式 2,现在继续想给 mycommand 添加一个别名或者对其进行修改
    • 进入到 /usr/local/bin 目录
    • 执行 ln -s ./mycommand mycommand1 这样就可以通过 mycommand1 来执行
  • 可见,软链接是可以嵌套的,基于此可以给当前脚手架起别名

相关文章:

  • 学习笔记:正则表达式
  • [大厂实践] Netflix容器平台内核panic可观察性实践
  • 网络原理-TCP/IP(1)
  • opencv中使用cuda加速图像处理
  • 故障诊断 | 一文解决,TCN时间卷积神经网络模型的故障诊断(Matlab)
  • 假期刷题打卡--Day26
  • kafka 文件存储机制
  • nextcloud 优化扩展
  • 基于YOLOv8算法的照片角度分类项目实践
  • 第十三、十四个知识点:用javascript获取表单的内容并加密
  • 电子电器架构 —— 网关测试脚本分析
  • ASP.NET Core MVC 控制查询数据表后在视图显示
  • 传输频宽是啥?对网速影响有多大?
  • Java基于微信小程序的驾校报名小程序,附源码
  • 十分钟学会用springboot制作微信小程序富文本编辑器
  • MySQL数据库运维之数据恢复
  • Object.assign方法不能实现深复制
  • React Native移动开发实战-3-实现页面间的数据传递
  • Sass 快速入门教程
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 精彩代码 vue.js
  • 聊聊directory traversal attack
  • 面试遇到的一些题
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • # 透过事物看本质的能力怎么培养?
  • #if和#ifdef区别
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (补)B+树一些思想
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net通用权限框架B/S (三)--MODEL层(2)
  • @KafkaListener注解详解(一)| 常用参数详解
  • @RequestMapping-占位符映射
  • [CareerCup] 17.8 Contiguous Sequence with Largest Sum 连续子序列之和最大
  • [ICCV2017]Neural Person Search Machines
  • [LeetCode]-使用特殊算法的题目-2
  • [linux] C语言Linux系统编程进程基本概念
  • [Mybatis-Plus笔记] MybatisPlus-03-QueryWrapper条件构造器
  • [NOIP 2015]Day.1 T2 信息传递 【最小环】
  • [opencvsharp]C#基于Fast算法实现角点检测
  • [Real world Haskell] 中文翻译:前言
  • [Vulnhub]靶场 Red
  • [WeChall] No Escape (Exploit, PHP, MySQL)
  • [ZigBee] 16、Zigbee协议栈应用(二)——基于OSAL的无线控制LED闪烁分析(下)
  • [导入]SQL Server练习题2
  • [计算机通信网络]网桥与其作用机理举例详解
  • [蓝桥杯 2016 省 B] 交换瓶子
  • [力扣 Hot100]Day27 合并两个有序链表
  • [逆向工程] 二进制拆弹Binary Bombs 快乐拆弹 详解
  • [全文检索]Lucene基础入门.
  • [深度学习] 卷积神经网络“卷“在哪里?
  • [树状数组]JZOJ 4658 小Z调顺序