详解前端脚手架原理及为什么要开发前端脚手架?

965 阅读6分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第9篇文章,点击查看活动详情

环境变量

在学习脚手架之前,首先要知道什么是环境变量。

环境变量的作用

你可能有个疑问,我们在Shell命令行中输入一个命令,Shell是如何知道去哪找到这个命令所对对应的执行文件,然后去执行它?

这通常是通过环境变量 PATH 来进行搜索的,熟悉Window的同学可能知道有这么一个叫PATH的环境变量。这个环境变量保存了Shell中执行的命令所对应的可执行文件的路径。

那环境变量存放在哪里呢?我们可以通过echo $PATH来查看:

image.png

可以看到环境变量 PATH 有好几个路径,当我们在终端输入一个命令的时候,电脑就会依次按照 PATH 中设定的路径来到目录中去查找,如果存在同名的环境变量,则执行先找到的那个。

这里面的文件都是一些链接文档,它们链接到真正执行的文件。

image.png

如何添加环境变量

现在你安装了mongodb的文件,在/usr/local/mongodb/bin路径下,一般你需要进入到这个路径才能启动mongodb,但是每次都要进入到这个文件太麻烦了,我能不能在任何地方输入mongodb都能启动程序呢?

通过设置环境变量即可完成,也就是把/usr/local/mongodb/bin路径添加到PATH上就行了,当你在命令行输入mongodb时,操作系统会从PATH上找到对应的路径,然后执行可执行文件。

vi .bash_profile 
// 输入: 
export PATH=$PATH://usr/local/mongodb/bin ($PATH代表已经存在的路径,它可以放前面或者后面) 
// 立即生效 
source .bash_profile

【注意】vi .bash_profile 表示在用户主目录下设置,针对当前特定的用户起作用的环境变量。你也可以设置系统目录下的profile文件,那么将会对所有用户都生效。

什么是脚手架?

脚手架本质

脚手架本质就是一个操作系统的客户端。比如node, 它在window系统下的可执行文件就是node.exe

下面以Vue的脚手架来说明前端脚手架是如何运作的。

vue create vue-test

上面的命令由三部分组成:

  • 主命令: vue
  • command: create
  • command的参数:vue-test

它表示创建了一个名叫vue-test的项目,以上是最简单的脚手架命令,实际情况往往更加复杂,比如: 当已经有了一个叫vue-test的项目,我们需要覆盖原有的项目,此时我们可以输入:

vue create vue-test --force

这里的--force 叫做 option,用来辅助脚手架确认在特定场景下用户的选择(可以理解为配置)。

还有一种场景是通过vue create 创建项目的时候,会执行npm intall来安装依赖,但是我们想用淘宝源来安装:

vue create vue-test -r https://registry.npmmirror.org

这里的 -r 也叫做 option,它与 --force 不同的是它使用 -,并且使用简写,这里的 -r 也可以替换成 --registry

-r https://registry.npm.taobao.org 后面的 https://registry.npm.taobao.org 成为 option 的 param,其实 --force 可以理解为:--force true,简写为:--force 或 -f

这么配置项是怎么知道的呢?其实我们输入下面的命令就可以看到 vue create 支持的所有 options:

vue create --help

脚手架的执行过程

5fda202309d65fff16991502.jpeg

当输入vue create vue-test-app时,操作系统会去环境变量PATH中查找Vue对应的可执行文件路径(相当于执行which vue),发现它对应的路径是/***/.nvm/versions/node/v16.14.0/bin/vue,然后这个bin/vue是一个链接文档,它链接到lib/node_modules/@vue/cli/bin/vue.js。也就是最后执行的文件就是这个vue.js

脚手架的执行原理如下:

  • 在终端输入 vue create vue-test-app
  • 终端解析出 vue 命令
  • 终端在环境变量中找到 vue 命令
  • 终端根据 vue 命令链接到实际文件 vue.js
  • 终端利用 node 执行 vue.js
  • vue.js 解析 command / options
  • vue.js 执行 command
  • 执行完毕,退出执行

脚手架的实现原理

要搞清楚脚手架的实现原理,从三个问题着手:

  1. 为什么全局安装 @vue/cli 后会添加的命令为 vue
  2. 全局安装 @vue/cli 时发生了什么?
  3. 执行 vue 命令时发生了什么?为什么 vue 指向一个 js 文件,我们却可以直接通过 vue 命令去执行它?
  4. 如何为node脚手架命令建立别名?

第一个问题

我们知道执行vue create **的时候,会找到真正的执行文件vue.js,这vue.js所在的工程目录中,有一个package.json文件:

image.png

这个package.json里面有个bin字段,是key/value的形式,当全局安装@vue/cli之后,node就会在自己的bin文件夹下配置一个叫vue(即,key)的软链接。这就可以回答第一个问题了。

第二个问题

当全局安装的时候,包被安装在node文件下面的lib/node_modules文件中,当包被下载完成后node会去解析package.json的bin字段,如果有bin字段,那么就会在node的bin目录下创建一个软连接

第三个问题

当我们输入vue 命令的时候,其实跟输入which vue是等价的:

5fda206309ec25b223221949.jpeg

vue.js的开头会有一行这样的代码:

#!/usr/bin/env node 

它表示从环境变量中找到node,然后用node来执行vue.js脚本。

用node执行文件还有另一种写法:

#! /usr/bin/node 

这种写法是不从环境变量中查找node,直接从/usr/bin/目录下查找node,但是不同用户安装导致/usr/bin/下没有node,所以,推荐使用第一种写法。

第四个问题

通过上面的了解,我们它们都是通过软链接的形式来执行命令的,既然要命名一个别名,当然也可以使用软链接。

比如imooc是一个链接到***/test.js的文件,那么我们可以再建立一个软链接到imooc上:

ls -s ./imooc imooc2

为什么要开发一个前端脚手架

目前我所在的公司要开始一个前端项目时,都会直接copy上一个项目的模板,然后进行增删操作,最后就得到了现在项目的模板。

如果你是个人开发者,这还能原谅。如果是一个几千人的公司还进行这种操作就显得很low,最主要的缺点是浪费时间。如果通过拷贝的方式创建一个模板花费1小时,大型公司一般都有上千个项目,那就是浪费了数千个小时了。

另外,各个团队使用的技术栈都不一样,使用的模板也不一样,因此需要有一个地方能对这些模板汇总,当你需要的时候直接选择你要的模板即可。因此,大型公司都会有一个通用的脚手架。

现在思考下,当你创建一个前端项目时,需要这个前端模板包含哪些功能呢?

  • 通用功能:http请求方法封装,工具方法,组件库,埋点等功能
  • 代码格式:统一代码格式 eslint + prettier
  • git操作:提交规范,git hooks 设置(保证提交到仓库中的代码是符合规范)
  • 构建与发布:依赖安装与构建,资源上传cdn,域名绑定等

上面列出了一个前端模板应该具有的通用功能,可以根据项目特点进行增删。

当你通过脚手架下载到这样的一个模板框架时,就极大提高开发效率,而不用从头开始搭建框架,而且它保证了一定的代码质量。

脚手架核心价值

将研发过程:

  • 自动化:项目重复代码拷贝/git操作/发布上线操作
  • 标准化:项目创建/git flow/发布流程/回滚流程
  • 数据化:研发过程系统化、数据化,使得研发过程可量化

问题:jenkins、travis等自动化构建工具已经比较成熟了,为什么还需要自研脚手架?

  • 不满足需求:jenkins、travis通常在git hooks中触发,需要在服务端执行,无法覆盖研发人员本地的功能,如:创建项目自动化、本地git操作自动化等
  • 定制复杂:jenkins、travis定制过程需要开发插件,其过程较为复杂,需要使用Java语言,对前端同学不够友好