zoukankan      html  css  js  c++  java
  • 创建简单的npm脚手架

    前言

    vue-cli, webpack-cli 等脚手架是不是用起来爱不释手?自己写了个模版每次来回复制粘贴代码是不是很难维护?如果你是对前端、Node操作有一定的了解,同时也存在以上疑问,那就请尽情阅读尝试吧!

    本篇文章按照al-block-cli举例, al-block-cli是一个基于vueelementUI而集成的一个开发模版,可安装进行使用

    依赖

    1. Commander.js 命令行工具
    2. download-git-repo git仓库代码下载
    3. chalk 命令行输出样式美化
    4. Inquirer.js 命令行交互
    5. ora命令行加载中效果

    根据上方的依赖插件即可以看出,其实脚手架就是一个利用终端命令将仓库中的代码拉取到本地的工具所以还没有模版代码的同学赶紧去创建个

    项目准备

    初始化

    $ npm init
    

    根据提示完成初始化搭建,如果不清楚如何配置可以直接回车

    安装依赖

    $ npm install commander download-git-repo chalk inquirer ora --save
    

    构建结构

    创建bincommands文件夹以及配置文件templates.json。bin文件夹为可执行命令入口目录,commands则负责编写一些命令交互

    最终目录结构

    - al-block-cli
    | - bin
    | - commands
    | - node_modules
    | - package.json
    | - templates.json
    

    编写代码

    配置文件

    输入默认需要的配置,如这里需要github 的仓库地址和命令行的名称

    {
      "init": {
        "name": "init",
        "path": "Alisdon/al-block-template"
      }
    }
    

    入口文件

    新建al-block-cli文件,并在其第一行加入

    #! /usr/bin/env node
    

    此行为了防止操作系统用户没有将node装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找node的安装路径,再调用对应路径下的解释器程序完成操作。

    #!/usr/bin/env node
    
    process.env.NODE_PATH = __dirname + '/../node_modules/';
    
    const program = require('commander');
    
    program
      .version(require('../package').version);
    
    program
      .usage('<command>');
    
    program.command('init')
      .description('create a new project')
      .alias('i')
      .action(() => {
        require('../commands/init')
      });
    
    program.parse(process.argv);
    
    if(!program.args.length){
      program.help()
    }
    

    命令交互

    新建init.js文件表示命令init

    const { prompt } = require('inquirer');
    const program = require('commander');
    const chalk = require('chalk');
    const download = require('download-git-repo');
    const ora = require('ora');
    const fs = require('fs');
    
    const option =  program.parse(process.argv).args[0];
    const question = [
      {
        type: 'input',
        name: 'name',
        message: 'Project name',
        default: typeof option === 'string' ? option : 'al-block-template',
        filter (val) {
          return val.trim()
        },
        validate (val) {
          const validate = (val.trim().split(" ")).length === 1;
          return validate || 'Project name is not allowed to have spaces ';
        },
        transformer (val) {
          return val;
        }
      },
      {
        type: 'input',
        name: 'description',
        message: 'Project description',
        default: 'Vue project',
        validate () {
          return true;
        },
        transformer(val) {
          return val;
        }
      },
      {
        type: 'input',
        name: 'author',
        message: 'Author',
        default: '',
        validate () {
          return true;
        },
        transformer(val) {
          return val;
        }
      }
    ];
    
    module.exports = prompt(question).then(({name, description, author}) => {
      const gitPlace = require('../templates').init.path;
      const projectName = name;
      const spinner = ora('Downloading please wait...');
    
      spinner.start();
      download(`${gitPlace}`, `./${projectName}`, (err) => {
        if (err) {
          console.log(chalk.red(err));
          process.exit()
        }
    
        fs.readFile(`./${projectName}/package.json`, 'utf8', function (err, data) {
          if(err) {
            spinner.stop();
            console.error(err);
            return;
          }
    
          const packageJson = JSON.parse(data);
          packageJson.name = name;
          packageJson.description = description;
          packageJson.author = author;
    
          fs.writeFile(`./${projectName}/package.json`, JSON.stringify(packageJson, null, 2), 'utf8', function (err) {
            if(err) {
              spinner.stop();
              console.error(err);
            } else {
              spinner.stop();
              console.log(chalk.green('project init successfully!'))
              console.log(`
                ${chalk.yellow(`cd ${name}`)}
                ${chalk.yellow('npm install')}
                ${chalk.yellow('npm run dev')}
              `);
            }
          });
        });
      })
    });
    
    

    测试发布

    测试

    至此,一个简单的脚手架(壳)就已经完成了,为了查看在编写过程中是否出错,我们现在本地进行测试

    $ node bin/al-block-cli
    

    如果没有报错,出现了熟悉的命令行,那就说明成功了

    发布

    发布之前我们需要做个小调整,观察其他脚手架工具他们都是以自己独特的key值进行搭建,对此我们可以在package.json里面配置bin对象

    "bin": {
    	"al-block-cli": "bin/al-block-cli"
    }
    

    这里需要注意bin/后面的al-block-cli,这个路径是由入口文件的路径确定,如果你是建的al-block-cli.js则此处应该配置bin/al-block-cli.js,本篇是创建的没有后缀名的文件

    修改后生成的最终package.json

    {
      "name": "al-block-cli",
      "version": "1.0.0",
      "description": "al-block-cli",
      "keywords": [
        "vue",
        "al-block",
        "al-block-cli"
      ],
      "scripts": {
        "test": "echo "Error: no test specified" && exit 1"
      },
      "bin": {
        "al-block-cli": "bin/al-block-cli"
      },
      "preferGlobal": true,
      "author": "Alisdon [920124512@qq.com]",
      "license": "MIT",
      "dependencies": {
        "chalk": "^2.4.1",
        "commander": "^2.19.0",
        "download-git-repo": "^1.1.0",
        "inquirer": "^6.2.1",
        "ora": "^3.0.0"
      }
    }
    

    对比文件内容,如果没有问题我们就开始发布了

    $ npm login
    $ npm publish
    
  • 相关阅读:
    OpenCV学习笔记(一)
    scrapy学习笔记一
    Mac上使用selenium自动运行chrome
    【js Utils】web前端工具帮助类kikyoUtils
    【jq 分享】伪微信分享
    【Winform 动图】winform窗体显示动图
    【 Base<T> 】IBaseDao 和 IBaseService 通用 基类 实现
    【js 是否手机】JavaScript判读当前是否是手机端
    【Spring helper】在controller和service间添加业务处理helper类
    【 spring resources 】maven项目resources文件夹,配置文件的spring加载方式
  • 原文地址:https://www.cnblogs.com/mmzs/p/10219377.html
Copyright © 2011-2022 走看看