前端工程化系列-第一章-脚本世界

648 阅读4分钟

Npm

常用命令

  • npm init --初始化工程
  • npm run --运行脚本
  • npm install --安装项目依赖
  • npm update --升级项目依赖
  • npm bin --查看bin文件目录
  • npm link --将工程软链接到全局
  • npm publish --发布工程
  • npm deprecate --废弃包
  • npm help --帮助命令

npm scripts

内部变量

需求: 输出 the package is xxx@xxx.xxx 答案: $npm_package_* eg:

  • $npm_package_name --输出package.json 中 name的值
  • $npm_package_version --输出package.json 中 version的值
  • $npm_package_other --输出package.json 中 other的值(other为自定义变量)

参数

需求: 对npm scripts 二次包装过的命令传参 答案: 利用--透传参数 -- eg:

    "scripts": {
        "serve": "serve ./build",
        "serve": "npm run serve -- -p 80",  // 使用 '--' 进行二次包装
    }

脚本钩子

  • preinstall --用户执行npm install 命令之前执行
  • postinstall --用户执行npm install 命令安装结束之后执行
  • preuninstall --卸载一个模块前执行
  • postuninstall --卸载一个模块后执行
  • prelink --link模块之后执行
  • postlink --link模块之后执行
  • pretest --运行 npm test 命令前执行
  • posttest --运行 npm test 命令后执行

通过 pre 和 post 规则,还可以自定义的添加钩子函数

eg: 自动化发版

    #/usr/bin/env node
    const semver = require('semver')
    const packageInfo = require('../package.json')
    const fs = require('fs')
    const targetVersion = semver.inc(packageInfo.version) // 使用semver工具,将版本+1
    packageInfo.version = targetVersion
    // Other operating...

只要在npm publish,就可以执行版本号自动叠加

Bash

Shell是什么

  • shell 不仅仅是命令行,也可以是GUI
  • shell 是操作系统和用户交互的 '接口'
  • 一般来说,我们说的shell都是 Unix Shell, 可以认为是CLI

命令(Command)是什么

  • 命令的本质是一个程序
  • 这些程序具有发起系统调用(System Call)的能力
  • 编写的Shell 脚本, 其实是在编排这些程序的执行
  • Shell语法需要Shell语法解释器负责解释一行行的语句

Shell常见解释器

  • bash (linux, unix)
  • sh ( linux, unix)
  • zsh ( linux, unix; mac 推荐)
  • cmd (windows)
  • PowerShell (windows)
  • WSL (Windows Subsystem of Linux)

bash常用命令

  • vi/vim (cli世界中编辑器王者)
  • touch
  • cd
  • ls
  • mv
  • cp
  • rm-rf
  • mkdir
  • rmdir
  • cat
  • head -n
  • tail -n
  • ps
  • lsof
  • top
  • kill
  • grep
  • awk ...

bash编程基础

全局变量

    COURSE=ENGINERING 
    export COURSE=ENGINERING

局部变量

    local COURSE=ENGINERING 

环境变量

  • PATH 指定命令搜搜路径
  • HOME 指定用户的主工作目录
  • HISTSiZE 指保存历史命令记录条数
  • LOGNAME 指当前用户登录名
  • HOSTNAME 指主机名称
  • SHELL 指当前用户使用的哪种shell
  • LANG/LANGUAGE 语言设置相关的环境变量
  • MAIL 指当前用户邮件存放目录

eg:(打开命令终端,在环境变量前面加上 '$')

    echo $PATH

变量基本类型

  • STRING
    STR=abcd
    STR="hello world"
  • Number
    NUM=$[ 1 + 1 ]
    NUM=$(( 1 + 1 ))
  • Array
    ARR=(hello world)
    ARR=(1 2 3)
    ARR[1]=0

组合

使用 $变量名方式

    STR=abc
    NSTR="hello world $STR"  \
    echo $NSTR # 输出 hello world abc

    NUM=$(( 1 + 1 ))
    SEQ=[1 $NUM 3 4 5]
    echo $SEQ # 输出 1 2 3 4 5

运算

  • 数学运算符
  NUM = $(6 + 2 ) # 8
  NUM = $(6 - 2 ) # 4
  NUM = $(6 * 2 ) # 12
  NUM = $(6 / 2 ) # 3
  • 条件语句

    • if then
        if condition1
        then 
            comman1
        elif condition2
            command2
        else 
            commandN
        fi
    
    • case
        case $VAR in 
            condition1)
                command1
                ;;
            condition2)
                command2
                ;;
            *)
                echo command3
                ;;
        esac
    
    • 比较符 -z var # 检查变量var是否为空 -d file # 检查file是否存在并且是一个目录 -e file # 检查file是否存在 -f file # 检查file是否存在并且是一个文件 -r file # 检查file是否存在并且可读 -s file # 检查file是否存在并且不是空 -w file # 检查file是否存在并且可写 -x file # 检查file是否存在并且可执行 -O file # 检查file是否存在并且属于当前用户 -G file # 检查file是否存在并且其默认组与当前组相同 file1 -nt file2 #检查file1是否比file2新 file1 -ot file2 #检查file1是否比file2旧
  • 循环语句

    • for循环
        # method 1
        for index in 1 2 3 4 5; do
            echo "index=$index"
        done
        
        # method 2
        for ((i=0; i<5; i++)); do
            echo $i
        done
    
    • while
        while(( $i<=10)) do 
            echo $i
        done
    
  • 函数

    • 函数的定义
        function custom_echo() 
        {
            local prefix = "input is"
            if [ -z $1 ]; then  # $n 用来获取第n个参数
                echo "no input"
            else 
                echo "$prefix $1"
            fi
            return 0
        }
    
    • 函数的调用与返回值
        custom_echo abc  # input is abc
        echo $?  # 0  查看上一次函数调用结果
    
    • 其他特殊变量
      • $# 传递到脚本或函数的参数个数
      • $* 以一个单字符串显示所有向脚本传递的参数
      • $$ 脚本运行的当前进程ID号
      • $! 后台运行的最后一个进程的ID号
      • $- 显示Shell使用的当前选项, 与set命令功能相同
      • $? 显示最后命令退出状态。 0表示没有错误, 其他任何值表明有错误
  • 重定向

        command > file      # 将输出重定向到file
        command < file      # 将输入重定向到file
        command << file      # 将输出重定向到file的部分内容
        command >> file      # 将输出以追加的方式重定向到file
    
  • 交互式程序

    • echo
        echo "xxx"      # 打印并换行
        echo -n "xxx"   # 打印且不换行
    
    • read
        read var        # 读取输入,存入变量var
        read -n 1 var   # 读取输入的第一个字符,存入变量var
    

    eg 分两次录入姓、名,最后输出两次录入结果

        echo "input firstName"; \
        read firstName; \
        echo "input lastName"; \
        read lastName; \
        echo "$firstName $lastName";
    

    效果展示

Node CLI

常用第三方工具

在下方文章中有使用过下面部分工具的,可做部分参考: 前端工程化-自定义脚手架

  • commander --用来处理命令的工具
    • 链式调用
    • 更好的参数处理
    • autohelp(自动生成help帮助命令)
  • inquirer.js --交互式工具
  • chalk --带颜色样式的log输出
  • shelljs --执行shell命令工具
    • 对bash命令提供了跨平台的封装
    • 可以同步的获得命令结果
  • execa --处理子进程工具
    • 结果promise化
    • 跨平台支持Shebang (Shebang就是脚手架前面的指定环境代码)
    • 获取进程结束信号
    • 优雅退出
    • 更好的支持windows

拆解CLI设计-以脚手架为例

需求描述

设计一个脚手架CLI, 根据命令提示选择不同的模板,安装指定的参数在指定的路径生成一个样本工程

拆解需求

  1. 参数的输入, 结果的输出
  2. 模板在哪里维护?
  3. 如果获取模板?
  4. 如何根据模板和参数生成工程?

细化工具

  1. 参数的输入,结果的输出 -- commanderjs, inquirerjs, chalk
  2. 模板维护 -- git仓库维护模板
  3. 如何获取 -- git clone, 使用 execa或shelljs调用
  4. 如何生成工程 -- 模板引擎, 例如 handerbars

通用脚手架框架

  • plop
  • yeoman-generator
  • Schemetics -- 革命性的新一代脚手架

如果做到更好

  • 粒度更细
  • 保证动作命令的原子性
  • 脚手架直接的自由组合

扩展阅读

  • ink -- 用react开发cli应用
  • oclif -- 架构层面的cli框架