资讯专栏INFORMATION COLUMN

构建一个用于创建组件库的项目脚手架工具(类 Vue-cli3)

CompileYouth / 896人阅读

摘要:比如一个模板用于创建的组件库,一个模板用于创建的组件库,还有一个模板用于创建的工具函数类库。

缘起

最近公司内部想搭建一个私有的 npm 仓库,用于将平时用到次数相当频繁的工具或者组件独立出来,方便多带带管理,随着项目的规模变大,数量变多,单纯的复制粘粘无疑在优雅以及实用性上都无法满足我们的需求,所以进一步模块化是必然的。

但是一个组件库的建立其实是一个非常麻烦的过程,基础 webpack 的配置不用多说,接着你还要配合增加一些 es-lint 之类的工具来规范化团队成员的代码。在开发过程中,你自然需要一个目录来承载使用示例,方便 dev 这个组件,随后呢,你还得建立一个打包规范,发布到私有 npm 仓库中。

如此一来,必然大大降低我们的积极性,所以不如创建一个用于建立模块包的脚手架工具,方便我们项目的初始化。

tips:最终成品在底部

私有 NPM

这里简单提及一下 私有 npm 的搭建。

npm i verdaccio -g
pm2 start verdaccio

推荐配合 nrm 使用 快速切换仓库地址

verdaccio github

还整个意大利名,属实洋气。

工具

在进入正题之前,我先介绍一些要点和工具,有了这写关键点,写起来其实就相当简单了。

npm bin

大家有没有想过一些全局安装的工具,他是如何做到在命令行里面自由调用的呢?

事实上这个东西是 npm 提供的链接功能

// package.json
{
  "name": "lucky-for-you",
  "bin": {
    "lucky": "bin/lucky"
  }
}

当这样的一个模块被发布之后,一旦有人使用 -g 参数全局安装

sudo npm i luck-for-you -g

/usr/local/bin/lucky -> /usr/local/lib/node_modules/luckytiger-package-cli/bin/lucky # npm 帮你进行链接

npm 事实上会帮你进行一次链接,链接到你操作系统的 Path 之中,从而但你敲出 Lucky 这个命令的时候,能从 path 中成功找到对应的程序

另外一点就是用于链接执行的文件 一般在开头都要加上如下内容,让 bash 能够正确识别该文件应该如何执行

#!/usr/bin/env node
// 意味使用 node 运行该文件
// next script
Commander.js

tj 大神的作品,可以方便的书写命令行工具。能够自动生成帮助命令

const program = require("commander");

program.version("0.0.1").usage(" [options]");

program
  .command("create ")
  .description("创建一个全新的 npm 组件模块")
  .action((name, cmd) => {
    const options = cleanArgs(cmd);
    require("../lib/create")(name, options);
  });

// 用户未输入完整命令 输出帮助
if (!process.argv.slice(2).length) {
  program.outputHelp();
}

program.parse(process.argv);

Commander.js github

inquirer

事实上当我第一次使用 vue-cli3.0 的时候,里面的命令行表单真是非常惊艳,翻了 vue-cli3 的源码 找到了这款工具,用于命令行的表单。能够更加直观的配置选项。

inquirer
  .prompt([
    {
      type: "list",
      name: "template",
      message: "template: 请选择项目起始模板",
      choices: [
        {
          key: "1",
          name: "JavaScript Library - 适用于普通 JS 库",
          value: "js-lib",
        },
        {
          key: "2",
          name: "Vue-components - 适用于 Vue 组件库",
          value: "vue-component",
        },
      ],
    },
    {
      type: "input",
      name: "author",
      message: "author: 请输入你的名字",
      validate: function(value) {
        return !!value;
      },
    },
    {
      type: "input",
      name: "desc",
      message: "desc: 请输入项目描述",
      validate: function(value) {
        return !!value;
      },
    },
    {
      type: "confirm",
      name: "confirm",
      message: "confirm: 完成配置了?",
      default: false,
    },
  ])
  .then(answers => {
    console.log(answers.template);
    console.log(answers.author);
    console.log(answers.desc);
  });

还有很多的表单类型,我这里几个最简单的 list + input + confirm 就足够了。

inquire github

开始构建

现在开始分享我的构建流程。由于代码量比较大,挨个文件帖出来没有什么必要,所以我这里只做简单介绍,具体的可以查看我的 github项目。

我把我的 cli 工具大致分为两部分 template模板 + 创建器
z
创建器的主要功能是吸收用户的可选项,基于模板进行复制+渲染。Vue-cli3.0对于这部分操作会更加复杂,他把模板里面具体的功能都抽象成了一个 Plugin,可以按需组建模板,对于面向普遍大众当然是更好的。

但是我这个项目因为是公司内部用,所以不太需要太过泛化的设计,一个模板直接解决一个问题,简化模型就可以了。比如一个模板用于创建 Vue 的组件库,一个模板用于创建 React 的组件库,还有一个模板用于创建JavaScript 的工具函数类库。

如此一来我们的 template模板 创建器在一定程度上可以做到解耦,也就是说日后需要更多类型的模板,不需要修改创建器部分的代码。

目录结构
├── README.md
├── bin
│   └── lucky #主程序
├── lib
│   ├── copy.js #复制
│   └── create.js #主创建器
├── package-lock.json
├── package.json
├── templates
│   ├── config.js #模板配置 解耦
│   ├── js-lib #预设模板1
│   └── vue-component #预设模板2
├── utils # 工具目录
│   └── dir.js
package.json
{
  "name": "luckytiger-package-cli",
  "version": "1.1.14",
  "description": "package-cli",
  "bin": {
    "lucky": "bin/lucky"
  },
  "scripts": {
    "lucky": "node bin/lucky",
    "bootstarp": "cnpm i && cd ./templates/js-lib/ &&  cnpm i   && cd ../vue-component/ && cnpm i  ",
    "dev:js-lib": "cd templates/js-lib  && npm run dev",
    "dev:vue-component": "cd templates/vue-component && npm run dev",
    "dev:create": "rm -rf test-app && node bin/lucky create test-app",
    "clear": "sudo rm -rf node_modules && sudo rm -rf templates/js-lib/node_modules && sudo rm -rf templates/vue-component/node_modules"
  },
  "author": "zhangzhengyi",
  "license": "ISC",
  "dependencies": {
    "chalk": "^2.4.2",
    "commander": "^2.20.0",
    "ejs": "^2.6.2",
    "inquirer": "^6.4.1",
    "validate-npm-package-name": "^3.0.0"
  }
}

配置了一些脚本 方便快速 DEV 模板的效果。

这样运行

npm run dev:js-lib

就能查看和开发 js-lib 这个模板

主程序
bin/lucky
#!/usr/bin/env node

const program = require("commander")

program.version("0.0.1").usage(" [options]")

program
  .command("create ")
  .description("创建一个全新的 npm 组件模块")
  .action((name, cmd) => {
    const options = cleanArgs(cmd)
    require("../lib/create")(name, options)
  })

if (!process.argv.slice(2).length) {
  program.outputHelp()
}

program.parse(process.argv)

// commander passes the Command object itself as options,
// extract only actual options into a fresh object.
function cleanArgs(cmd) {
  const args = {}
  cmd.options.forEach(o => {
    const key = camelize(o.long.replace(/^--/, ""))
    // if an option is not present and Command has a method with the same name
    // it should not be copied
    if (typeof cmd[key] !== "function" && typeof cmd[key] !== "undefined") {
      args[key] = cmd[key]
    }
  })
  return args
}

这个文件主要是做一下基本的命令设置 利用了 commander这个库

如果用户调用了创建命令,就会转发给 lib/create.js 处理

主创建器
lib/cerate.js
const path = require("path")
const inquirer = require("inquirer")
const validateProjectName = require("validate-npm-package-name")
const chalk = require("chalk")
const copy = require("./copy")
const fs = require("fs")
const dir = require("../utils/dir")
const templates = require("../templates/config")

async function create(projectName, options) {
  const cwd = options.cwd || process.cwd()
  const inCurrent = projectName === "."
  const name = inCurrent ? path.relative("../", cwd) : projectName
  const targetDir = path.resolve(cwd, projectName || ".")

  const result = validateProjectName(name)
  if (!result.validForNewPackages) {
    console.error(chalk.red(`无效的项目名: "${name}"`))
    result.errors &&
      result.errors.forEach(err => {
        console.error(chalk.red.dim("Error: " + err))
      })
    result.warnings &&
      result.warnings.forEach(warn => {
        console.error(chalk.red.dim("Warning: " + warn))
      })
    return
  }

  if (!dir.isDir(targetDir)) {
    fs.mkdirSync(targetDir)
  } else {
    console.error(chalk.red(`该目录下已经存在该文件夹 请删除或者修改项目名`))
    return
  }

  const answers = await inquirer.prompt([
    {
      type: "list",
      name: "template",
      message: "template: 请选择项目模板",
      choices: templates.map((v, i) => ({
        key: i,
        name: v.name,
        value: v.dir
      }))
    },
    {
      type: "input",
      name: "author",
      message: "author: 请输入你的名字",
      validate: function(value) {
        return !!value
      }
    },
    {
      type: "input",
      name: "desc",
      message: "desc: 请输入项目描述",
      validate: function(value) {
        return !!value
      }
    },
    {
      type: "confirm",
      name: "confirm",
      message: "confirm: 完成配置了?",
      default: false
    }
  ])

  // 启动复制流程
  const sourceDir = path.resolve(__dirname, "..", "templates", answers.template)
  console.log(chalk.blue(`           
               
                                           
                       
                 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105566.html

相关文章

  • Vue项目构建

    摘要:什么是读音,类似于是一套用于构建用户界面的渐进式框架。的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。 什么是vue.js Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化...

    LittleLiByte 评论0 收藏0
  • Vue.js 2.0 轻松入门(一)

    摘要:的官方下载地址点我进入的官方下载地址下载电脑系统对应文件,然后进行安装,安装成功之后通过命令行工具进入安装目录。注系统命令行工具通过开始菜单输入打开,系统为终端。 showImg(https://segmentfault.com/img/bVPL6q?w=200&h=200); Vue — 渐进式 JavaScript 框架 介绍 Vue.js 是什么 vue.js 是一套构建用户界面...

    617035918 评论0 收藏0
  • Vue.js 2.0 轻松入门(一)

    摘要:的官方下载地址点我进入的官方下载地址下载电脑系统对应文件,然后进行安装,安装成功之后通过命令行工具进入安装目录。注系统命令行工具通过开始菜单输入打开,系统为终端。 showImg(https://segmentfault.com/img/bVPL6q?w=200&h=200); Vue — 渐进式 JavaScript 框架 介绍 Vue.js 是什么 vue.js 是一套构建用户界面...

    mmy123456 评论0 收藏0
  • Vue.js 2.0 轻松入门(一)

    摘要:的官方下载地址点我进入的官方下载地址下载电脑系统对应文件,然后进行安装,安装成功之后通过命令行工具进入安装目录。注系统命令行工具通过开始菜单输入打开,系统为终端。 showImg(https://segmentfault.com/img/bVPL6q?w=200&h=200); Vue — 渐进式 JavaScript 框架 介绍 Vue.js 是什么 vue.js 是一套构建用户界面...

    red_bricks 评论0 收藏0
  • 基于vue-cli3.0的项目工程重新构建空白版,拿来即用

    摘要:写在前面使用框架开发时,很多人会选择官方提供的脚手架,最新的已经更新到完全无配置,只需下载就能方便的使用构建的项目工程,但基础的并不能满足正常的项目开发,在开发中我们需要根据自己的习惯和业务功能而添加些基础功能。 写在前面 使用vue框架开发时,很多人会选择vue官方提供的cli脚手架,最新的cli已经更新到3.0完全无配置,只需下载就能方便的使用vuecli构建的项目工程,但基础的c...

    xingpingz 评论0 收藏0

发表评论

0条评论

CompileYouth

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<