npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

niuke-cli

v1.0.0

Published

## ✨ 介绍 一个能够快速生成react/vue项目的脚手架

Downloads

2

Readme

create-react-practice

✨ 介绍

一个能够快速生成react/vue项目的脚手架

📦 安装

npm i create-react-practice -g   // 记得全局安装

🔨 使用

rp-cli create [project-name]

效果展示

脚手架.gif

为什么要搭建脚手架

当我们需要重新创建一个项目时,可能需要重新去新建目录然后去创建文件,然后一步步去搭建起来我们所需要的项目环境,这无疑是一份非常投入产出比非常低的工作,我们可以把这份工作交给脚手架来做

初始化项目配置

首先效果肯定是实现像create-react-app或者是vue-cli等脚手架的效果

//直接在termial输入create-react-app [project-name] 然后就能拉取到文件(模板)了

create-react-app react-demo

然后使用npm init -y初始化新项目

获取版本号

这里我们需要参考实现用命令行输入指令能输出的功能,这里就需要用到bin, 我们这里新建一个bin文件夹,并在下面新建一个index.js文件 也新建一个src文件,下面新建一个main.js文件

// package.json
{
  "name": "create-react-practice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "rp-cli": "./bin/index.js",  // 这里我起的脚手架名字就叫rp-cli,你们可以自己起
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

// bin/index.js

#! /usr/bin/env node  //这行命令是告诉bin用什么环境执行代码,这里用node执行代码
require('../src/main.js');

// src/main.js
console.log('hello world');

执行一下命令npm link && rp-cli,命令行已经打印出来了,有感觉了!

image.png

看别的脚手架都有看版本号的功能,我们也实现一个

// src/main.js

//需要安装一个command npm i command --save-dev
const program = require("commander");

const { version } = require("./constants");
program.version(version).parse(process.argv);

image.png

create获取项目并拉取模板

配置指令命令

接下来就是实现拉取模板文件下来的功能, 新建create.js,我们先从github上拉取对应的github 仓库,这里我新建了一个新的github组织,fp-cli,里面放置了两个模板项目,分别是react-template和vue-template

// src/constants.js
const { version } = require('../package.json');

// 存储模版的位置
const downloadDirectory = `${process.env[process.platform === 'darwin' ? 'HOME' : 'USERPROFILE']}/.template`;

module.exports = {
    version
};
// src/main.js
const program = require("commander");
const path = require("path");

const mapActions = {
  create: {
    alias: "c",
    description: "create a project",
    examples: ["rp-cli create <project-name>"],
  },
  config: {
    alias: "conf",
    description: "config project variable",
    examples: ["rp-cli config set <k><v>", "rp-cli config get <k>"],
  },
  "*": {
    alias: "",
    description: "command not found",
    examples: [],
  },
};

// 配置命令
Reflect.ownKeys(mapActions).forEach((action) => {
  program
    .command(action) // 配置命令的名字
    .alias(mapActions[action].alias) // 命令的别名
    .description(mapActions[action].description) // 命令对应的描述
    .action(() => {
      // 访问不到对应的命令 就打印找不到命令
      if (action === "*") {
        console.log(mapActions[action].description);
      } else {
        // 截取命令
        // fp-cli create xxx // [node,fp-cli,create,xxx]
        require(path.resolve(__dirname, action))(...process.argv.slice(3));
      }
    });
});

// 监听用户的help事件
program.on("--help", () => {
  console.log("\nExamples:");
  Reflect.ownKeys(mapActions).forEach((action) => {
    mapActions[action].examples.forEach((example) => {
      console.log(`${example}`);
    });
  });
});

const { version } = require("./constants");
program.version(version).parse(process.argv);

下载模板

create.js的代码有点多,大概实现就是command和inquirer实现命令行的输出和选择,donwloadGitRepo去github上拉取对应的模板,ncp起到一个拷贝文件到本地效果

// /src/create.js

const axios = require("axios");
const ora = require("ora");
const Inquirer = require("inquirer");
const { promisify } = require("util");  //promisify让其支持es6语法
let downloadGitRepo = require("download-git-repo");
downloadGitRepo = promisify(downloadGitRepo);
let ncp = require("ncp");
ncp = promisify(ncp);

const { downloadDirectory } = require("./constants");
const path = require("path");

const waitFnloading =
  (fn, message) =>
  async (...args) => {
    const spinner = ora(message);
    spinner.start();
    const result = await fn(...args);
    spinner.succeed();
    return result;
  };

const fetchRepoList = async () => {
  const { data } = await axios.get("https://api.github.com/orgs/rp-cli/repos");
  return data;
};

const fetchTagList = async (repo) => {
  const { data } = await axios.get(
    `https://api.github.com/repos/rp-cli/${repo}/tags`
  );
  return data;
};

// 拼接下载的路径
const download = async (repo, tag) => {
  let api = `rp-cli/${repo}`;
  if (tag) {
    api += `#${tag}`;
  }
  const dest = `${downloadDirectory}/${repo}`;
  await downloadGitRepo(api, dest);
  return dest;
};

module.exports = async (projectName) => {
  // 1. 获取项目的模版
  let repos = await waitFnloading(fetchRepoList, "fetching template ....")();
  repos = repos.map((item) => item.name);
  // 在获取之前 显示loading 关闭loading
  // 选择模版 inquirer
  const { repo } = await Inquirer.prompt({
    name: "repo", // 获取选择后的结果
    type: "list", // 什么方式显示在命令行
    message: "please choise a template to create project", // 提示信息
    choices: repos, // 选择的数据
  });
  // 2. 获取项目的版本号
  let tag;
  let tags = await waitFnloading(fetchTagList, "fetching template ....")(repo);
  tags = tags.map((item) => item.name);
  // 如果有版本号则获取,否则不获取
  if (tags.length) {
    const res = await Inquirer.prompt({
      name: "tag",
      type: "list",
      message: "please choise tags to create project",
      choices: tags,
    });
    tag = res.tag;
  }
  // 3. 下载到对应的模板,最重要的一步
  const result = await waitFnloading(download, "download template...")(
    repo,
    tag
  );
  await ncp(result, path.resolve(projectName));
};

这里我们已经可以实现和开头一样拉取文件的效果了,棒棒 脚手架.gif

发布脚手架

最后发布一下脚手架,其实就和发布npm包一样,这里就不多赘叙啦