脚手架设计

参考项目 G:\webpack-learn\my-cli

1. 为什么需要脚手架

脚手架 提供 创建项目, 项目运行, 项目框架, 项目打包, 项目发布,等一系列能力,提升研发效率, 简化复杂流程

2. 当在命令行里输入vue create app发生了什么

会找到vue对应的可执行文件, 然后执行.

  1. 如果是苹果系统会执行which vue, 找到对应文件后执行.
  2. 如果是window, 用where vue, 他会找到对应文件. 找到对应文件vue.js后, 第一行会有一个#!/usr/bin/env node,表示该文件是由node执行的, 然后再找node的可执行文件 比如C:\Program Files\nodejs\node.exe. 再用node.exe执行vue.js.
  3. 找到这些文件后,会把vue后面的字段当做参数,传入可执行文件中. 启动.
  4. 可执行文件的例子
    1. node_modules/.bin/webpack-cli.cmd
    2. C:\Program Files\Git\bin\bash.exe (很多.exe格式)
    3. package.json里有bin属性
{
    "bin": {
        "my-app": "./bin/my-app"
    },
}
  1. 启动文件的方式
    默认.js文件是没法启动的, 需要告诉系统启动方式, 在文件开头添加#!/usr/bin/env node, 效果就是在命令行输入/usr/bin/env node console.log(123), 命令行就知道用node启动了.
  2. 操作系统window只能执行二进制文件, 比如node.exe. 而vue.js就需要node解析成二进制再执行

脚手架执行流程

  • 在终端输入vue create app
  • 终端解析出vue命令
  • 终端在环境变量中找到vue命令
  • 终端根据vue命令链接到实际文件vue.js
  • 终端查看vue.js第一行,#!/usr/bin/env node,确实是用node作为执行程序
  • 终端执行命令 /usr/bin/env node vue.js
  • vue.js解析后续参数create app,并执行文件

3. 创建脚手架

  1. 创建npm项目
  2. 配置package.json的bin属性
    "bin": {
        "imooc-ls": "./bin/imooc-ls.js"
    },
  1. 在bin/imooc-ls.js文件开头加上 #!/usr/bin/env node
  2. 编写imooc-ls.js, 比如console.log(123)
  3. 执行命令npm link, 将imooc-ls变成全局命令, 此时在全局的终端都可以使用imooc-ls命令了
    1. 由于imooc-ls是用node执行的命令, npm link会在C:\Program Files\nodejs文件夹中,会生成关于imooc-ls的命令文件imooc-ls.cmd
    2. 地址C:\Program Files\nodejs\node_modules\imooc-ls是一个软链接,指向我们真实的文件地址.
    3. 执行imooc-ls时,是先执行C:\Program Files\nodejs\imooc-ls.cmd(二进制文件),这个文件会启用node执行imooc-ls.js
  4. npm public将脚手架发布到npm服务器.

4. imooc-ls.js 命令文件开发

  1. 获取命令参数用process.argv获取
// process.argv: ['node根目录地址', 'imooc-ls目录地址', '命令参数1', '命令参数2', ...]
/* 执行"imooc-ls -all"
[
  'C:\\Program Files\\nodejs\\node.exe',
  'C:\\Program Files\\nodejs\\node_modules\\imooc-ls\\bin\\index.js',
  '-all'
]
*/
console.log(process.argv);
//  执行 node bin/index.js  -a   
// [
//   'C:\\Program Files\\nodejs\\node.exe',
//   'C:\\Program Files\\nodejs\\node_modules\\imooc-ls\\bin\\index.js',
//   '-a'
// ]

imooc-ls -anode bin/index.js -a, 效果是一样的

  1. 获取命令终端的工作目录

输入命令行的地方的工作目录 process.cwd()

4. unix系统

Unix系统包括linux, MacOs.
ls -l获取到文件权限

// 文件权限
drwxr-xr-x      5       sam         staff       160         Apr         4       13:58  bin
-rw-r--r--      1       sam         staff       260         Apr         4       13:58  package.json

文件权限drwxr-xr-x

  • d: directory目录, -表示文件
  • r: read 读取权限,表示文件是否可读
  • w: write 写入权限,是否可修改
  • x: execute 执行权限,
    • 如果是文件夹,是否可进入,
    • 如果是文件,是否可执行.
  • rwxr-xr-x: 三个权限为一组,u|g|o, rwx(user当前用户权限)|r-x(group用户所在分组权限)|r-x(other其他用户权限)

unix使用32位二进制数存储文件类型和权限

在unix中万物都是文件, 文档,目录, 键盘, 监视器, 硬盘,网络通信都是文件. 是文件,就有一套文件属性.
这些文件属性是用一个32位的二进制数保存的

// 32位的2进制数.
0000 0000 0000 0000

0000(文件类型), 000(特殊权限), 000(用户权限), 000(分组权限), 000(其他权限)

前4位0000: 文件类型, 可以表示16种文件类型. 0001表示file普通文件, 0100表示directory,目录

这里的文件类型是由 1所在的位置表示的,
1. 0001, 1在第四位,就是file普通文件
2. 0100, 1在第二位,就是目录.
用1所在位置记录值,是因为, 二进制程序有专门的位运算符&, 可以用来快速判断 当前用户是否有某权限.

unix系统文件mode含义
unix系统文件mode含义.png

unix系统文件的mode各个位的含义
unix系统文件的mode各个位的含义.png

32位操作系统的位

  • 8位二进制: 00000000 可以表示0-255
  • 16位二进制: 00000000 00000000 可以表示 0-65535
  • 32位二进制: 00000000 00000000 00000000 00000000 可以表示 0-4294976295

操作系统的文件是由二进制数组成的. 是可以直接执行的机器语言.机器语言直接翻译成人类语言就是汇编. 形如

00110000 
00001000 
00000010 
01110000
00000010
00000100
00100100
00000000

8位操作系统: 每一个汇编,由一个8位2进制数表示,也就是有256个汇编语言.
16位操作系统: 每一个汇编语言有两个8位2进制表示, 可以有65526个汇编.
32位操作系统: 每一个汇编语言有4个8位2进制表示, 可以有4294976296个汇编. 但是 不是每一个值的格式都是4个8位二进制.

比如32位操作系统的系统文件类型权限,就是用16位的2进制数表示的. 00000000 00000000足够表示所有的系统类型.

获取系统文件类型和权限

// file: package.json, bin
const stat = fs.statSync(file);

console.log(
    file, // 文件路径
    stat.mode, // 描述文件类型和模式的位字段, 转成二进制数, 查看文件类型和权限
    stat.isDirectory(), // 是否是文件夹
    stat.isFile()); // 是否是文件
// package.json:  mode: 33206, false, true
// bin: mode 16877 true, false

fs.statSync(file)的返回值里有 mode: 描述文件类型和模式的位字段, 转成二进制数, 查看文件类型和权限
比如: bin文件夹的mode: 16822, 转成二进制 1000001 11101101,(第一位的0被省略了,自己加上即可)
01000001 11101101 转换成查看用户权限的格式
0100 000 111 101 101
文件类型 特殊权限 用户权限 用户所在分组权限 其他权限
文件类型(前4位): 0100: 表示文件夹
特殊权限: 000表示特殊权限, 在ls的输出里不展示.
用户权限: 111(rwx)(read wirte execute)
翻译成ls输出的格式就是
bin: drwxr-xr-x
package.json: -rw-rw-rw-

位运算符 &

文件权限的计算方式
下面的 mode是 33188, S_IXUSR: 64
"&" 是一个位运算符,表示按位与操作。它将两个数字的二进制表示进行逐位比较,如果两个相应的二进制位都为1,则该位的结果为1,否则为0。
比如下面的 mode & fs.constants.S_IXUSR;

// 当前用户是否有执行权限.
const canUserExecute = mode & fs.constants.S_IXUSR;
// S_IXUSR : 64  =>  1 000 000
// mode: 33188 =>  10000001 10100100
// 进行位的对比 都不相同所以是 0.
1000 000  110 100 100
          001 000 000

fs.constants.S_IXUSR

S_IRUSR: S: 表示system系统文件, I: is是否, R: read阅读权限, USR: user用户. 当前用户的系统文件是否有执行权限

用户阅读常量 S_IRUSR: 0000 0001 0000 0000 => 256
用户修改常量 S_IWUSR: 0000 0000 1000 0000 => 128
用户执行常量 S_IXUSR: 0000 0000 0100 0000 => 64

这些常量共同特点是用2个8位二进制保存的话, 所有二进制位都只有一个1,
文件的mode转成2个8位二进制, 如果有对应位置的1,那就有这个权限, 没有对应位置的1,就没有对应权限.

所以用 mode & fs.constants.S_IXUSR 可以用来判断当前文件是否有此权限. 这个计算方式也是设计好的一环.

mode

mode: 33188 的这个值不是随便取的, 也不是顺序排的. 而是现有二进制,再转成10进制的.
mode的二进制: 1000 000 110 100 100 这里面的16个位, 每一个位都表示一种权限或类型. 比如最开头的1表示文件夹, 第二个1表示用户的读取权限.
是先根据当前文件的各种权限生成了这个16位的2进制,再为了存储方便,转成10进制,33188,保存在了mode里.

uid, gid

uid: userId 用户id, 可以获取用户名userName
gid: groupId, 用户所在组id, 可以获取用户所在组名groupName

ls -l

结果

drwxr-xr-x 2 root root 4096 Sep 22 15:08 a
-rw-r--r-- 1 root root 1010 Sep 22 16:52 auth.js

结果解析

drwxr-xr-x    2                   root      root             4096      Sep 22 15:08  a
//文件权限    文件夹下的文件数量    创建人    创建人所在分组     文件大小   修改时间      文件名

posted on 2024-11-27 19:55  下辈子当座桥-李飞  阅读(35)  评论(0)    收藏  举报