基于node.js的cli工具,保姆级实现教程

介绍

基于nodejs的cli工具

实现教程

创建项目

新建一个文件夹,根目录下执行指令 npm init -y 自动创建package.json文件,初始化项目。
package.json中新增一条"type": "module" 配置引用的文件作为ES模块进行加载。package.json文件内容如下:

{
  "name": "zyf-cli",
  "version": "1.0.0",
  "description": "基于nodejs的cli工具",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git@gitee.com:wendZzoo/zyf-cli.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

根目录下新建index.js,作为入口文件。cli工具的整体的实现思路:

  1. 创建文件夹
  2. 创建入口文件
  3. 创建package.json
  4. 安装依赖

使用fs模块可以实现如上思路,index文件代码如下:

import fs from "fs";
fs.mkdirSync("./demo");
fs.writeFileSync("./demo/index.js", "index");
fs.writeFileSync("./demo/package.json", "package");
// 4 todo 安装依赖

如上代码实现了,在根目录下创建了一个demo文件夹,在demo中新建了index.js,写入index, 新增package.json写入package

这时候在根目录下执行指令node index.js 就可以发现自动新建了一个demo文件夹,修改package中操作指令 "test": "rm -rf ./demo && node index.js" 之后就可以直接使用npm run testyarn test 作为测试指令,这就是个cli工具的雏形。

ejs创建模板文件

demo中的index和package文件中写入的内容,需要是我们提前定义的好模板,方便用户使用时候可以直接看到生成好的代码。

这里使用ejs,ejs 官方文档

https://ejs.bootcss.com/

npm install esj 安装ejs

根目录下新建template文件夹,里面新建index.ejs, 安装vscode插件EJS language support可以让ejs代码高亮,这里就是最终想对用户展现的内容,代码如下:

const koa = require('koa')
<% if (static) { %>
    const Router = require('koa-router')
  <% } %>
<% if (static) { %>
    const serve = require('koa-static')
  <% } %>
    const app = new koa()
<% if (static) { %>
    app.use(serve(__dirname + "/static"))
<% } %>
<% if (router) { %>
    const router = new Router()
    router.get("/", (ctx) => {
        ctx.body = 'Hello, koa-setup-test'
    })
    app.use(router.routes())
<% } %>
    app.listen(8080, () => {
        console.log('open server localhost:8080')
    })

根目录下新建 createIndexTemplate.js 封装index文件的模板内容生成方法,读取index.ejs中内容,通过ejs的render方法将生成的代码写入demo下的index.js, 代码如下:

import ejs from 'ejs'
import fs from 'fs'
export default () => {
    const indexTemplate = fs.readFileSync("./template/index.ejs")
    const code = ejs.render(indexTemplate.toString(), {
        static: true,
        router: true
    })
    return code
};

改造一下index.js, 引入createIndexTemplate,代码如下:

import fs from "fs";
import createIndexTemplate from './createIndexTemplate.js'
fs.mkdirSync(getRootPath());
fs.writeFileSync(`${getRootPath()}/index.js`, createIndexTemplate());
fs.writeFileSync(`${getRootPath()}/package.json`, "package");
// 4 todo 安装依赖
function getRootPath() {
    return "./demo";
}

终端里执行指令yarn test, 查看demo下index内容,createIndexTemplate中修改static: false, router: true,再次执行指令,会发现demo下index内容有变化,koa-static相关代码不再显示。

相同的,改造一下demo下package.json里写入的代码。
template下新建package.ejs文件,代码如下:

{
    "name": "<%= packageName %>",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "type": "module",
    "scripts": {
      "test": "echo \"Error: no test specified \" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {
      "koa": "^2.13.1"
      <% if (middleware.router) { %>
        ,"koa-router": "^10.0.0"
      <% } %>
      <% if (middleware.static) { %>
        ,"koa-static": "^5.0.0"
      <% } %>
    }
}

新建createPackageTemplate.js, 代码如下:

import ejs from 'ejs'
import fs from 'fs'
export default (config) => {
    const packageTemplate = fs.readFileSync("./template/package.ejs")
    const code = ejs.render(packageTemplate.toString(), {
        packageName: config.packageName,
        middleware: config.middleware
    })
    return code
};

改造index, 修改内容如下:

import createPackageTemplate from "./createPackageTemplate.js";
const inputConfig = {
    packageName: "demo",
    port: 8080,
    middleware: {
        static: true,
        router: false,
    },
};
fs.writeFileSync(`${getRootPath()}/index.js`, createIndexTemplate(inputConfig));
fs.writeFileSync(`${getRootPath()}/package.json`, createPackageTemplate(inputConfig));
function getRootPath() {
    return path.resolve(process.cwd(), inputConfig.packageName)
}

抽离了输入的配置项inputConfig, 也要相应的修改一下createIndexTemplate中传入的参数

createIndexTemplate.js修改内容如下:

export default (config) => {
    const indexTemplate = fs.readFileSync("./template/index.ejs")
    const code = ejs.render(indexTemplate.toString(), {
        middleware: config.middleware
    })
    return code
};

那相应的也要修改一下中的传入参数,修改的内容如下:

const koa = require('koa')
<% if (middleware.static) { %>
    const Router = require('koa-router')
  <% } %>
<% if (middleware.static) { %>
    const serve = require('koa-static')
  <% } %>
    const app = new koa()
<% if (middleware.static) { %>
    app.use(serve(__dirname + "/static"))
<% } %>
<% if (middleware.router) { %>
    const router = new Router()
    router.get("/", (ctx) => {
        ctx.body = 'Hello, koa-setup-test'
    })
    app.use(router.routes())
<% } %>
    app.listen(8080, () => {
        console.log('open server localhost:8080')
    })

动态生成配置

通过inquirer插件交互式生成inputConfig

inquirer 文档:

https://www.npmjs.com/package/inquirer#documentation

npm install inquirer 安装inquirer

修改index.js,代码如下:

import fs from "fs";
import inquirer from "inquirer";
import createIndexTemplate from "./createIndexTemplate.js";
import createPackageTemplate from "./createPackageTemplate.js";
const r = await inquirer.prompt([
    /* Pass your questions in here */
    {
        type: "input",
        name: "packageName",
        message: "set package name",
        validate(val) {
            if (val) return true;
            return "please enter package name";
        },
    },
    {
        type: "input",
        name: "port",
        default() {
            return 8080;
        },
        message: "set port number",
    },
    {
        type: "checkbox",
        name: "middleware",
        choices: [{ name: "koaStatic" }, { name: "koaRouter" }],
    },
]);
console.log(r);
// 以下代码暂 注释

测试,终端执行node index.js, 出现交互式配置

配置项如果变多时,代码放在index就很不便于维护,根目录下新建question文件夹封装配置项
question下新建index.js,代码如下:

import inquirer from "inquirer";
import packageName from "./packageName.js";
import port from "./port.js";
import middleware from "./middleware.js";
export default () => {
    return inquirer.prompt([
        /* Pass your questions in here */
        packageName(),
        port(),
        middleware(),
    ]);
}

新建packageName.js, 代码如下:

export default () => {
    return {
        type: "input",
        name: "packageName",
        message: "set package name",
        validate(val) {
            if (val) return true;
            return "please enter package name";
        },
    };
};

新建middleware.js, 代码如下:

export default () => {
    return {
        type: "checkbox",
        name: "middleware",
        choices: [{ name: "koaStatic" }, { name: "koaRouter" }],
    };
};

新建port.js, 代码如下:

export default () => {
    return {
        type: "input",
        name: "port",
        default() {
            return 8080;
        },
        message: "set port number",
    };
};

根目录下新建config.js,封装配置文件,代码如下:

export function createConfig(answer) {
    function haveMiddleware(name) {
        return answer.middleware.indexOf(name) !== -1;
    }
    return {
        packageName: answer.packageName,
        port: answer.port,
        middleware: {
            static: haveMiddleware("koaStatic"),
            router: haveMiddleware("koaRouter"),
        },
    };
}

修改根目录index.js, 修改内容如下:

import question from "./question/index.js";
import { createConfig } from "./config.js";
const answer = await question();
const inputConfig = createConfig(answer);
console.log(inputConfig);

重复测试,输出结果一致,说明这里的代码抽离封装是没问题的, 可以放开下面代码的注释

依赖安装

使用execa插件进行package依赖的安装,execa是对node官方推荐库child-process子进程的二次封装,使用更加方便

execa文档:

https://www.npmjs.com/package/execa

npm install execa 安装execa

修改index.js,修改内容如下:

import { execa } from "execa";
// 4. Todo
execa("npm install", {
    cwd: getRootPath(),
    stdio: [2, 2, 2],
});

全局使用cli

在支持全局使用之前,需要修改一下模板文件中的文件引用路径,不然执行时会报错

根目录下新建bin文件夹,之前的文件(index, createIndexTemplate, createPackageTemplate, config, template, question)移到bin下, 修改package.json, 代码如下:

{
  "name": "zyf-cli",
  "version": "1.0.0",
  "description": "基于nodejs的cli工具",
  "main": "index.js",
  "bin": "./bin/index.js",
  "type": "module",
  "scripts": {
    "test": "rm -rf ./demo && node index.js",
    "test-g": "rm -rf ./demo && zyf-cli"
  },
  "repository": {
    "type": "git",
    "url": "git@gitee.com:wendZzoo/zyf-cli.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.8",
    "execa": "^6.1.0",
    "inquirer": "^9.0.2"
  }
}

上面可以看到新增了一条指令test-g, 需要先配置一下全局使用

修改一下createIndexTemplate.js 中文件路径的引用方式,修改代码如下:

import ejs from "ejs";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
export default (config) => {
    const __dirname = fileURLToPath(import.meta.url);
    const indexTemplate = fs.readFileSync(
        path.resolve(__dirname, "../template/index.ejs")
    );
    const code = ejs.render(indexTemplate.toString(), {
        middleware: config.middleware,
    });
    return code;
};

因为package.json中配置了"type": "module",原本node可以使用的__dirname只能借助fileURLToPath实现
相同的,createPackageTemplate一样的改造,代码重复就不贴了

配置全局使用, 终端执行npm link, npm root -g 打开输出的文件路径,全局下已经出现了zyf-cli

执行yarn test-g, 正常出现demo

代码格式化

使用prettier格式化demo下代码

prettier官方文档:

https://www.prettier.cn/docs/index.html

npm install prettier 安装prettier

只需要在创建模板最终输出的时候,使用prettier进行代码格式化

改造createIndexTemplate的return, 代码如下:

import prettier from "prettier";

return prettier.format(code, { parser: "babel" });

createPackageTemplate修改如下:

import prettier from "prettier";

return prettier.format(code, { parser: "json" });

最后

至此,一个cli工具项目基本完成,基于此实现思路可以做很多平日里重复工作的优化

### React 安装与环境配置完整步骤指南 #### 1. 安装 Node.js 和 npm 在开始安装 React 之前,需要确保系统中已经安装了 Node.js 和 npm(Node Package Manager)。可以从 [Node.js 官方网站](https://nodejs.org/) 下载并安装最新版本的 Node.js。安装完成后,可以通过以下命令检查是否成功安装: ```bash node -v npm -v ``` 这些命令会分别显示 Node.js 和 npm 的版本号,确认安装成功[^2]。 #### 2. 安装 Create React App Create React App 是一个官方支持的工具,用于快速搭建 React 项目。使用 npm 安装它: ```bash npm install -g create-react-app ``` 安装完成后,可以使用以下命令创建一个新的 React 项目: ```bash create-react-app my-app ``` 这里的 `my-app` 是项目的名称,可以根据需要更改。 进入项目目录并启动开发服务器: ```bash cd my-app npm start ``` 这将启动开发服务器,并在浏览器中打开默认的 React 应用程序,通常位于 `http://localhost:3000`[^2]。 #### 3. 配置开发环境 React 项目通常使用现代 JavaScript 特性,因此可能需要配置一些额外的工具来支持这些特性。常见的配置包括 ESLint、Babel 和 Webpack。 - **ESLint**:用于代码规范和错误检查。 - **Babel**:用于将 ES6+ 代码转换为向后兼容的 JavaScript 代码。 - **Webpack**:用于模块打包和资源管理。 可以通过以下命令安装这些工具: ```bash npm install eslint babel-loader @babel/core @babel/preset-env webpack webpack-cli --save-dev ``` 然后,创建相应的配置文件(如 `.eslintrc`, `.babelrc`, `webpack.config.js`)来配置这些工具的具体行为。 #### 4. 安装 React 开发者工具 为了更好地调试 React 应用程序,建议安装 React 开发者工具扩展。对于 Chrome 浏览器,可以在 Chrome Web Store 中搜索 "React Developer Tools" 并安装。 #### 5. 使用 React 组件 React 应用程序由多个组件组成。每个组件可以是一个函数或类,负责渲染 UI 的一部分。例如,创建一个简单的组件: ```jsx import React from 'react'; function HelloWorld() { return <h1>Hello, World!</h1>; } export default HelloWorld; ``` 在主入口文件 `src/index.js` 中导入并渲染该组件: ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './HelloWorld'; ReactDOM.render(<HelloWorld />, document.getElementById('root')); ``` #### 6. 运行和测试应用 确保开发服务器正在运行(通过 `npm start`),然后在浏览器中查看应用。如果一切正常,应该能看到 "Hello, World!" 的消息。 #### 7. 构建生产版本 当准备好部署应用时,可以使用以下命令构建生产版本: ```bash npm run build ``` 这将生成一个优化过的生产环境代码,存放在 `build` 目录中,可以直接部署到服务器上。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值