zoukankan      html  css  js  c++  java
  • 关于zhen-cli的介绍

    开发目的

    • 首先是方便自己快速创建项目工程的初始化模板;
    • 其次真正实现日常维护的工程模板价值;
    • 再次实现一个脚手架同时管理两种技术栈的目的:管理vue技术栈和react技术栈。

    zhen-cli是一个脚手架。其功能类似vue-cli,相当于vue-cli的简化版,但功能又不全是vue-cli的子集。

    目前发布在npm上的版本1.0.14实现的功能:

    • 项目工程、版本号以及作者可以自定义;
    • 可以选择是否安装vuex;
    • 可以同时生成react技术栈的项目初始化工程模板。 最后这点算是区别于vue-cli的。

    工作原理

    整体工作流程如下。

    整体上,zhen-cli是一个nodejs的应用,归属于命令行工具应用。

    依赖的主要功能库:

    • commander 负责命令行输入和参数解解析

    以下是对想要注册命令的定义。

    #!/usr/bin/env node

    // commander是终端命令行命令注册库
    // #!/usr/bin/env node 这行代表的是按照node的环境处理
    const program = require("commander");
    program
      .version(require("../package").version)
      .usage("<command> [options]")
      .option('--no-sauce', 'Remove sauce')
      .command("vue", "generate a new vue project from a template") // 注册vue命令
      .command("react", "generate a new react project from a template") // 注意react命令
    program.parse(process.argv); // 去掉后不管作用
    • download-git-repo 负责下载gitlab或者github的仓库代码
       const download = require("download-git-repo"); // 下载github下的仓库

        /**
         * 从模板仓库下载模板,并生成项目
         *
         * @param {String} template
         */
        function downloadAndGenerate(template) {
            const spinner = ora("模板下载中,请稍等···");
            spinner.start();

            // 如果存在本地模板,先删除
            if (exists(tmp)) rm(tmp);
            download(template, tmp, {
                clone: false
            }, err => {
                spinner.stop();
                if (err) {
                    logger.fatal("模板" + template + "下载失败" + ": " + err.message.trim());
                }
                // 生产项目方法 核心方法
                // name为文件名 tmp数临时目录 生成的项目的目录
                generate(name, tmp, to, err => {
                    if (err) logger.fatal(err);
                    logger.success('"%s" 创建成功.', name);
                });
            });
        }
    }
    • metalsmith 串行执行各个方法直到下载项目依赖

    读取文件之后链式调用中间件方法。

    // Read all the files in a source directory.
    // Invoke a series of plugins that manipulate the files.
    // Write the results to a destination directory!
      const metalsmith = Metalsmith(path.join(src, "template"));
      // metalsmith.metadata() 这个默认是{}
      // console.log(metalsmith.metadata(), 'metalsmith.metadata()')
      const data = Object.assign(metalsmith.metadata(), {
        destDirName: name,
        inPlace: dest === process.cwd(),
        noEscape: true
      });

      // 将模板中自定义的helper注册到handlebars中。
      // helper实际就是模板可以自动获取到helper中的数据
      // opts.helpers &&
      //   Object.keys(opts.helpers).map(key => {
      //     Handlebars.registerHelper(key, opts.helpers[key]);
      //   });

      // 给metalsmith绑定插件,1.收集用户交互信息 2. 过滤需要渲染的文件 3. 渲染文件
      // metalsmith Read all the files in a source directory.
      // 将数据咋转为以路径为key的键值对形式
      // 输出到一个指定的目录
      metalsmith
        .use(askQuestions(opts.prompts))
        .use(filterFiles(opts.filters))
        .use(renderTemplateFiles)
        .clean(false)
        .source(".")
        .destination(dest)
        .build(err => {
          done(err);
          console.log(' 正在下载依赖... ')
          executeCommand('npm install', path.join(process.cwd(), name)).then(()=>{
            logMessage(opts.completeMessage, data);
          })
        });
    • handlebars 负责渲染字符串为文件
    const Handlebars = require("handlebars");
    const async = require("async");  // async这是一个异步处理的库
    // 这里是用的handlebars模板 也可以使用ejs模板语法
    const render = require("consolidate").handlebars.render; //Template engine consolidation library. 模板引擎库 有多种模板渲染引擎

     const metalsmithMetadata = metalsmith.metadata();
      // metalsmithMetadata是meta里面的数据
      // console.log(metalsmithMetadata, 'metalsmithMetadata')
      async.each(
        keys,
        (file, next) => {
          const str = files[file].contents.toString();
          // 如果文件中没有模板语法,则不对该文件进行渲染,直接输出文件内容。
          if (!/{{([^{}]+)}}/g.test(str) || file.indexOf('.vue') > -1) {
            return next();
          }
          // 使用数据对象对模板进行渲染
          render(str, metalsmithMetadata, (err, res) => {
            if (err) {
              err.message = `[${file}] ${err.message}`;
              return next(err);
            }
            files[file].contents = Buffer.from(res);
            next();
          });
        },
        done
      );
    • inquirer 负责用户与命令行交互
    inquirer
        .prompt([
          {
            type: prompt.type,
            name: key,
            message: prompt.message || key,
            default: promptDefault,
            choices: prompt.choices || [],
            validate: prompt.validate || (() => true)
          }
        ])
        .then(answers => {
          if (Array.isArray(answers[key])) {
            data[key] = {};
            answers[key].forEach(multiChoiceAnswer => {
              data[key][multiChoiceAnswer] = true;
            });
          } else if (typeof answers[key] === "string") {
            data[key] = answers[key].replace(/"/g, '\"');
          } else {
            data[key] = answers[key];
          }
          done();
        })
        .catch(done);

    使用方法

    执行命令npm i -g zhen-cli 安装

    使用zhen vue/react project-name 创建项目

    如果想研究源代码可以直接查看node modules里面的zhen-cli

    后续工作

    后续将继续优化原始模板。尤其react模板目前比较简单,后期将做出更加针对性的优化方案。

    我站在山顶看风景!下面是我的家乡!
  • 相关阅读:
    zBrow发布倒计时:对不起,让大家久等了
    《zBrow的资本论》
    zBrow智能浏览器
    zspt界面截图
    电商领域,唯一的“发明”级国家专利。
    zBrow界面截图截图
    zBrow多开界面截图
    网页滚动条样式
    关于margin参数解读
    JAVA的抽象类和抽象方法
  • 原文地址:https://www.cnblogs.com/zhensg123/p/15459100.html
Copyright © 2011-2022 走看看