最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 自己动手写个简单的脚手架工具

    正文概述 掘金(月荷风影)   2021-01-28   547

    本文是从我们公司的需求为出发点,编写一个简单的脚手架工具。

    首先,让我们分析需求:目前公司的项目比较多,分属于不同的客户,每个项目都是独立部署的,但是项目的前端框架基本分为三种:

    • 以 app 为载体的 内嵌 H5 页面: vue 全家桶 + vant ui
    • admin 后台管理系统:vue 全家桶 + element ui
    • admin 后台管理系统: react + ant design

    本文不涉及具体前端项目框架的实现,只解决创建项目时,根据业务的需求,使用脚手架工具生成简单的项目模板。

    创建项目

    mkdir gt-cli
    cd gt-cli
    npm init
    

    package.json

    {
      "name": "gt-cli",
      "version": "1.0.0",
      "description": "",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "bin": {
        "gt": "bin/gt.js"
      },
      "url": "",
      "email": "",
      "author": "Iris Mei",
      "repository": {
        "type": "git",
        "url": ""
      },
      "license": "ISC",
      "dependencies": {
        "chalk": "^4.1.0",
        "commander": "^7.0.0",
        "inquirer": "^7.3.3",
        "log-symbols": "^4.0.0"
      }
    }
    

    安装依赖

    npm install
    

    chalk: 处理命令行输出文字的样式(颜色、背景色)

    commander:node命令行解决方案

    inquirer:node 命令行交互(信息录入、选择、信息确认等......)

    log-symbols: 打印日志图标,如: √,×

    目录结构

    ┌─── gt-cli

    │├── bin文件夹

    │    ├─ gt.js 

    │├── command文件夹

    │    ├─ init.js 

    │├── node_module文件夹

    │├── .gitignore 

    │├── package.json 

    │├── README.md

    │├── template.json 

    gt.js: 入口文件

    init.js: 初始化项目逻辑代码

    template.json: 不同项目模板的描述和git仓库地址

    开始coding

    首先,在template.json 中 配置不同项目模板的名称、描述、仓库地址:

    {    
        "vue-admin": {        
            "gitUrl": "git 仓库地址",        
            "name": "admin system(vue + element)"    
        },    
        "vue-web": {        
            "gitUrl": "git 仓库地址",        
            "name": "web H5 (vue + vint)"    
        },    
        "react-admin": {        
            "gitUrl": "git 仓库地址",        
            "name": "admin system(react + ant design)"    
        }
    }
    

    在gt.js 中,针对不同的命令执行不同的操作,除了查看版本号,使用帮助以外,现在仅有初始化项目操作,使用 gt init <projectName> 初始化项目模板。

    #!/usr/bin/env node --harmony
    'use strict'
    // 终端图标
    const symbols = require('log-symbols')
    // 终端命令行美化
    const chalk = require('chalk')
    // node命令行解决方案
    const program = require('commander')
    
    // cli 版本
    program
        .version(require('../package.json').version)
    
    // 使用说明
    program
        .usage('<command>')
    
    // 初始化一个项目 命令:gt init <projectName> || gt i <projectName>
    program
        .command('init')                        // 命令
        .description('init a new project')      // 描述
        .alias('i')                             // 命令别名
        .action(() => {                         // 命令执行的操作
             // 如果参数中没有项目名称,退出命令行
             if (program.args.length < 2) {
                console.log(symbols.error, chalk.red('Please input the project name, for example: gt init vue-app'))
                process.exit()
            }
            require('../command/init')(program.args[1])
        })
    
    // 处理非法命令
    program
        .arguments('<command>')
        .action(cmd => {
        // 输出帮助信息
        console.log(symbols.error, chalk.bgRed(`Unknown command: ${cmd}.`));
        program.help()
      });
    
    // 命令行参数解析
    program
        .parse(process.argv)
    
    // 命令行没有参数时,执行help命令!
    program.args.length && program.help()
    

    init.js 用来处理初始化项目的逻辑:用户录入项目信息,选择模板,脚手架从git仓库拉取项目模板,然后安装依赖。完整代码:

    'use strict'
    // 执行复杂的命令行命令
    const exec = require('child_process').exec
    // 终端图标
    const symbols = require('log-symbols')
    // 响应用户命令行交互
    const inquirer = require('inquirer')
    // 终端命令行美化
    const chalk = require('chalk')
    // 模板类型
    const projectTpl = require('../template.json')
    
    module.exports = async (name) => {
            // 项目需要录入的信息
            const promptList = [{
                type: 'input',
                message: `project name(default: ${name}): `,
                name: 'projectName',
                default: name
            }, {
                type: 'input',
                message: `The project description: `,
                name: 'description',
            }, {
                type: 'list',
                message: 'please choose a project template: ',
                name: 'projectType',
                choices: Object.keys(projectTpl),
                filter: function (val) {
                    return projectTpl[val];
                }
            }];
            let answers = await inquirer.prompt(promptList)
            // 确认项目信息
            let confirm = await inquirer.prompt([{
                type: 'confirm',
                message: `Please confirm the project infomation: \n project name: ${answers.projectName} \n project description: ${answers.description} \n project template: ${answers.projectType.name} \n are you sure? `,
                name: 'isSure',
                default: ''
            }])
            // 如果没有确认项目信息,退出命令行
            if (!confirm.isSure) {
                console.log(chalk.bgYellow('The process already exited.'))
                process.exit()
            }
            // 拉取项目模板,使用master分支
            const cmd = `git clone ${answers.projectType.gitUrl} ${answers.projectName} `  
          // 开始初始化项目
            console.log('The project start cloning......')
    
            exec(cmd, (error) => {
                if (error) {
                    console.log(symbols.error, chalk.red(error))
                    process.exit()
                }
                console.log(symbols.success, chalk.green('git clone is successed!'))
    
                console.log('\n npm install......')
    
                exec(`cd ${answers.projectName} && npm install`, (error) => {
                    if (error) {
                        console.log(symbols.error, chalk.red(error))
                        console.log(symbols.error, chalk.red(`please npm install again or use cnpm install`))
                        process.exit()
                    }
                    console.log(symbols.success, chalk.green('Generation completed!'))
                    process.exit()
                })
            })}
    

    本地调试

    在package.json 同级目录中执行 npm link ,创建本地npm模块的链接。

    执行后显示下面的信息,说明link 成功:

    audited 39 packages in 1.408s
    
    6 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    
    C:\Users\你的用户名\AppData\Roaming\npm\gt -> C:\Users\你的用户名\AppData\Roaming\npm\node_modules\gt-cli\bin\gt.jsC:\Users\你的用户名\AppData\Roaming\npm\node_modules\gt-cli -> C:\Users\你的用户名\Desktop\workspace\gt-cli
    

    现在可以试试用自己写的脚手架创建一个空项目模板了,在终端中执行:gt init <项目名称>

    然后根据提示,输入项目信息:

    ? project name(default: demo):  (demo)
    
    ? The project description:  A test project
    
    ? please choose a project template:  (Use arrow keys)
    > vue-admin
      vue-web
      react-admin
    
    ? Please confirm the project infomation:
     project name: demo
     project description: A test project
     project template: admin system(vue + vue router + vuex)
     are you sure?  (Y/n) Yes
    
    The project start cloning......
    √ git clone is successed!
    
     npm install......
    C:\Users\iris.mei\Desktop\test process.cwd
    √ Generation completed!
    

    自己动手写个简单的脚手架工具

    需要取消link时,在 C:\Users\你的用户名\AppData\Roaming\npm\node_modules 目录中执行npm unlink <模块名称> :

    自己动手写个简单的脚手架工具

    写在最后

    一个简单的脚手架写完了,还有很多可以优化的点:

    • 方法封装
    • 项目目录验证
    • 目录名称验证
    • ......

    我先抛个砖,以后有空再优化 ~~

    最后,部分代码借鉴其他大佬的博客,向大佬学习~~

    文中如有不妥之处,欢迎指正~~


    起源地下载网 » 自己动手写个简单的脚手架工具

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元