前端架构: 从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 来执行
  • 可见,软链接是可以嵌套的,基于此可以给当前脚手架起别名

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【好玩AI】【Prompt】情人节了,用GPT写个【骂醒恋爱脑】的机器人跟自己对话吧

情人节了,让我们用GPT写个【骂醒恋爱脑】的机器人跟自己对话吧。 通过本文,你能学到: 1. 如何零代码搭建一个自己的机器人Bot 2. 骂醒恋爱脑的高级Prompt 通过本文,你还能得到: 恋爱脑可能被骂醒 为了白嫖,…

Linux下的多线程

前面学习了进程、文件等概念,接下里为大家引入线程的概念 多线程 线程是什么?为什么要有线程?线程的优缺点Linux线程操作线程创建线程等待线程终止线程分离 线程间的私有和共享数据理解线程库和线程id深刻理解Linux多线程(重点&a…

【selenium】

selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的。Selenium可以直接调用浏览器,它支持所有主流的浏览器。其本质是通过驱动浏览器,完成模拟浏览器操作,比如挑战,输入,点击等。 下载与打…

算法刷题:快乐数

快乐数 .习题链接题目题目解析初始值算法原理我的答案 . 习题链接 快乐数 题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1…

【C语言】解析刘谦春晚魔术《守岁共此时》

今年的春晚上刘谦表演了魔术《守岁共此时》,台上台下积极互动(尤其是小尼),十分的有趣。刘谦老师的魔术不仅仅是他的高超手法,还有这背后的严谨逻辑,下面我们来用C语言来解析魔术吧。 源代码 #define _CRT…

单页404源码

<!doctype html> <html> <head> <meta charset"utf-8"> <title>简约 404错误页</title><link rel"shortcut icon" href"./favicon.png"><style> import url("https://fonts.googleapis.co…

SVD奇异值分解

一、奇异值 奇异值&#xff08;Singular Values&#xff09;是线性代数中矩阵的重要性质之一&#xff0c;与奇异值分解&#xff08;SVD&#xff09;密切相关。让我们来更详细地了解一下奇异值的概念&#xff1a; 定义&#xff1a; 对于一个矩阵 ( A )&#xff0c;它的奇异值是…

夜天之书 #95 GreptimeDB 社群观察报告

GreptimeDB 是格睿科技&#xff08;Greptime&#xff09;公司研发的一款开源时序数据库&#xff0c;其源代码[1]在 GitHub 平台公开发布。 https://github.com/GreptimeTeam/greptimedb 我从 2022 年开始知道有 GreptimeDB 这个项目。2023 年&#xff0c;我注意到他们的 Commun…

Blazor OIDC 单点登录授权实例5 - 独立SSR App (net8 webapp ) 端授权

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor OIDC 单点登录授权实例2-登录信息组件wasmBlazor OIDC 单点登录授权实例3-服务端管理组件Blazor OIDC 单点登录授权实例4 …

在线问诊系统设计与实现的经验总结与整理

随着互联网技术的快速发展&#xff0c;在线问诊服务作为一种新兴的医疗服务模式&#xff0c;正逐渐受到人们的关注和使用。本文将介绍在线问诊系统的设计原则和关键组件&#xff0c;以及如何实现一个安全、高效和可扩展的在线医疗服务平台。 内容&#xff1a; 1. 引言 - 在…

团队配置管理规范浅见

在一段时间的工作过程中配置管理工作确实对我们的生产活动产生了巨大的工作量&#xff0c;现在就这个工作来进行梳理一下。 本文主要分为两部分&#xff1a; 1、借用软件系统分析师的配置管理部分内容来介绍配置管理的工作&#xff08;原谅时间精力有限&#xff0c;原文基本已…

Qt窗口坐标体系

通过以上代码可以看出Qt的坐标体系。 以左上角为原点&#xff08;0,0&#xff09;&#xff0c;以向右的方向为x轴的正方向&#xff0c;以向下方向为y轴的正方向。 对于嵌套窗口&#xff0c;其坐标是相对于父窗口来说的。顶层窗口的父窗口就是屏幕。

day 20(补2.5)

fread 函数&#xff1a; 今日练习 C语言面试题5道~ 1. static 有什么用途&#xff1f;&#xff08;请至少说明两种&#xff09; 1) 限制变量的作用域 2) 设置变量的存储域 2. 引用与指针有什么区别&#xff1f; 1) 引用必须被初始化&#xff0c;指针不必。 2) 引用初始…

【Java程序设计】【C00266】基于Springboot的超市进存销管理系统(有论文)

【Java程序设计】【C00266】基于Springboot的超市进存销管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的超市进销存系统 本系统分为登录注册模块、管理员功能模块以及员工功能模块。 登录注册模块&#…

《Linux 简易速速上手小册》第8章: 安全性与加固(2024 最新版)

文章目录 8.1 防火墙与安全策略8.1.1 重点基础知识8.1.2 重点案例&#xff1a;配置 iptables 以保护 Web 服务器8.1.3 拓展案例 1&#xff1a;使用 firewalld 配置动态防御区域8.1.4 拓展案例 2&#xff1a;配置 ufw 以简化管理 8.2 SSH 安全最佳实践8.2.1 重点基础知识8.2.2 重…

JAVA设计模式之命令模式详解

命令模式 1 命令模式介绍 命令模式(command pattern)的定义: 命令模式将请求&#xff08;命令&#xff09;封装为一个对象&#xff0c;这样可以使用不同的请求参数化其他对象&#xff08;将不同请求依赖注入到其他对象并且能够支持请求&#xff08;命令&#xff09;的排队执行…

STM32 寄存器操作 GPIO 与中断

一、如何使用stm32寄存器点灯&#xff1f; 1.1 寄存器映射表 寄存器本质就是一个开关&#xff0c;当我们把芯片寄存器配置指定的状态时即可使用芯片的硬件能力。 寄存器映射表则是开关的地址说明。对于我们希望点亮 GPIO_B 的一个灯来说&#xff0c;需要关注以下的两个寄存器…

【C语言期末项目-通讯录】-升级可动态申请内存版(手把手详细过程,期末评分A+的项目,答辩辅助神博文,建议三连点赞收藏)

目录 ​编辑 前言&#xff1a; 1.项目功能需求分析 2.文件框架说明 3.程序主框架实现 4.创建联系人结构体类型和通讯录结构体类型 4.1创建通讯录 5.程序功能实现--封装功能函数实现不同功能 5.1通讯录初始化 5.2增加联系人 5.3显示所有联系人的信息 5.4删除指定…

【Java EE初阶十二】网络编程TCP/IP协议(二)

1. 关于TCP 1.1 TCP 的socket api tcp的socket api和U大片的socket api差异很大&#xff0c;但是和前面所讲的文件操作很密切的联系 下面主要讲解两个关键的类&#xff1a; 1、ServerSocket&#xff1a;给服务器使用的类&#xff0c;使用这个类来绑定端口号 2、Socket&#xf…

【图论】【树形dp】【深度优先搜索】2538. 最大价值和与最小价值和的差值

作者推荐 【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目 本文涉及知识点 深度优先搜索 LeetCode2538. 最大价值和与最小价值和的差值 给你一个 n 个节点的无向无根图&#xff0c;节点编号为 0 到 n - 1 。给你一个整数 n 和一个长度为 n - 1 的二维整数…