写个自己的脚手架

167 阅读2分钟

一、基础脚手架思路

流程图-导出.png

文件夹结构

 project-cli           
    ├─ templates  // 自己定义的模板文件夹        
    │  ├─ 模板1     
    │  └─ 模板2
    ├─ bin     
    │  ├─ cli.js  // 处理逻辑入口   
    ├─ lib    
    │  ├─ create.js  
    ├─ package-lock.json  
    └─ package.json   

👉使用 :

  1. npm i my-app-cli
  2. wow create <appName>

二、Summary

1. ESM 和 CMJ 中 __dirname __filname获取方式不一样

ES moduleCommon Js
文件夹地址__filename1. import.meta 模块信息
2. import.meta.url 基于 file:// 协议的 绝对路径
3. 用 url 方法中的fileURLToPath(import.meta.url) 转化得到
文件地址__dirname4. 多一步 path.dirname() 把3中的值放入

image.png

__filename 是执行文件的地址 带文件后缀
cwd 是生成文件的根目录

2. ejs用法

  • <% %>流程控制标签
  • <%= %>输出标签(原文输出 HTML 标签)
  • <%- %>输出标签(HTML 会被浏览器解析)
  1. 直接+拼接
  2. 模板字符串
  3. ejs 优点:让js和html具有分开编写代码的功能pro版。会忽略所有代码 直接找到<% %>的地方开始替换。 所以ejs模板可单独放到html中。js里获取路径读取文件中的<% 就可以替换并输出

渲染方法:

  • ejs.render(str, data, options)
  • ejs.renderFile(路径,填充的内容)
import ejs from 'ejs'
let result = ejs.render('这是一个水果 <%= fruit %>', {fruit:'apple'})
-------------------------------------------------------------------
// targetURL存在模板的路径 ;answers要替换成的数据;data返回的数据
ejs.renderFile(targetURL, answers).then(data => {
    fs.writeFileSync(path.join(cwdUrl,file),data)
})

3. bin

  • 工具包处的package.json
{
  "bin": {
    "fast-template": "./bin/cli.js"  
    // key作为使用方的node_modules下的bin的名字。value是执行的代码的路径
  },
}

  • 使用方 package.json 中配置
{
    "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview", 
    "app-cli":"app-cli",
    "project-cli":"fast-template" 
    // 前面是执行的快捷短语如yarn run project-cli ,value是去bin中找的包
  },
}

4. commander

自定义命令指令的工具

  • <> 必填, [] 选填
  • - 缩写, -- 全称
  • command('指令名称 <必填参数>') 在命令后面传入的参数会被传入到 action 的回调函数以及 program.argv 数组中
  • .option('-f, --force' , 'description')
    • 参数1:自定义标志 '短标,长标志' 标志后可选加<>或者[]
    • 参数2:描述(可略)
    • 参数3:默认值(可略)
  • .action((name,options)=>{}) 执行command后的回调
  • .on('监听内容',()=>{}) 监听执行后面的回调

基本流程:

  1. 安装commander npm install commander --save
  2. package.json中定义好bin:{"wow": "./bin/cli.js"}
  3. 编写如下代码
    #! /usr/bin/env node
    
    import { program } from 'commander'
    
    program
      // 定义命令和参数
      .command('create <app-name>')
      .description('create a new project')
      .option('-f, --force', 'overwrite target directory if it exist')
      .action((name, option) => {
        // 打印执行结果
        console.log('name:',name, 'options:',options)
        console.log(process.args);
      })
    
    program
       // 配置版本号信息
      .version(`v1.1`)
      .usage('<command> [option]')
    
    // 解析用户执行命令传入参数
    program.parse(process.argv);
    
  4. npm link
  5. bin中的key名字当做指令执行

image.png

5. fs-extra

fs模块的pro版,增加了对promise的支持
npm install fs-extra --save

6. chalk

终端增加颜色 npm install chalk

// 文本样式
console.log("project name is " + chalk.bold(name))

// 颜色
console.log("project name is " + chalk.green(name))

// 背景色
console.log("project name is " + chalk.bgRed(name))

// 使用RGB颜色输出
console.log("project name is " + chalk.rgb(4, 156, 219).underline(name));
console.log("project name is " + chalk.hex('#049CDB').bold(name));
console.log("project name is " + chalk.bgHex('#049CDB').bold(name))
    

7. node常用

  • let stat = fs.statSync() 可以获取文件信息
  • stat.isDirectory() 判断是否是文件夹
  • fs.mkdirSync(fileNamePath) 创建文件夹
  • fs.writeFileSync() 写文件内容
  • Path.resolve()/ 作为根目录拼接 转为绝对路径。若没有 / 会自动加当前目录
  • Path.join() 连接
  • path.relative(from,to) 返回from到to两个块之间的相对路径