Skip to content

16-利用node构建自己的脚手架工具

统计信息:字数 5371 阅读11分钟

课程大纲

1、如何利用node编写命令行脚本(操作命令行) 2、脚手架工具常用的包有哪些 3、带你手撸一个自己的 vue-cli

可以自己做项目专属的脚手架工具

如何操作命令行

npm run build 执行的是 build.js 脚本

常见的 nodeJS 包

chalk 输出不同颜色的文字开发脚本的效果的包
ora loading 的效果
commander 解析命令-v
inquirer 提问查询的包npm init 然后会提问名称是什么

练习 build.js

process.env.NODE_ENV = 'production';

const ora = require('ora');
const rm = require('rimraf');
const path = require('path');
const chalk = require('chalk');
const webpack = require('webpack');
const config = require('../config');
const webpackConfig = require('./webpack.prod.conf');

// 开始loading状态
const spinner = ora('building for production...loading...');
spinner.start();

const { assetsRoot, assetsSubDirectory } = config.build;
rm(path.join(assetsRoot, assetsSubDirectory), err => {
  if (err) {
    throw err;
  }
  webpack(webpackConfig, (err, stats) => {
    // webpack 编译结束后,停止loading状态
    spinner.stop();
    if (err) {
      throw err;
    }
    process.stdout.write(stats.toString({
      colors: true,
      modules: false,
      children: false, // if use ts-loader, set this true
      chunks: false,
      chunkModules: false
    }) + '\n\n');

    if (stats.hasError()) {
      // handle error
      console.log(chalk.red('Build failed with errors.\n'));
      process.exit(1);
    }
    console.log(chalk.cyan('Build complete.\n'));
  });
});

下面是一步一步的教程

npm install chalk ora commander inquirer --save
const chalk = require('chalk');
console.log(chalk.red.bgBlue('Hello'));
console.log(chalk.rgb(126,126,126).bgRgb(22,33,89)('hello'));

const spinner = ora('this is a loading').start();
spinner.color = 'yellow';
spinner.text = 'hello nodeJS';
setTimeout(function() {
  spinner.stop();
}, 3000);

自定义命令 package.json

{
  "bin": {
    "mytool": 'index.js'
  }
}

如果已经发布这个库,直接运行执行脚本即可。如果没有发布,本地首先运行 npm link 链接(可能报错,链接多次),然后才能正常使用命令。

Index.js 脚本

#!/usr/bin/env node
const cm = require('commander');
const iq = require('inquirer');
cm.version('1.0.0', '-v, --version');
cm.option('-a -atest', 'this is test');
console.log(1);
cm.command('init <name>').action((name) => {
  console.log(name);
  iq.prompt([
    {
      type: 'input',
      name: 'author',
      message: 'what is your name'
    }
  ]).then((answers) => {
    require('./bin/dowuload.js')(answers.author);
  });
});
cm.parse(process.argv);

download.js

const fs = require('fs');
const chalk = require('chalk');
const ora = require('ora');

module.exports = function(answer) {
  // 数据驱动
  // fs.readFile fs.read fs.createWriteStream
  //[
  //  {type: 'file', path: './app.js'},
  //  {type: 'dir', path: './src'},
  //  {type: 'dir', path: './src/route'},
  //]
    const demoPath = './project';
  const targetPath = './' + answer;
  const ob = [];
  function downdemo() {
    // fs.mkdir(targetPath, () => { pushArr(demoPath); });
    pushArr(demoPath);
    console.log(ob);
    ob.forEach((item) => {
      if (ob[i][0] == 'file') {
        fs.readFile(ob[i][1], (err, data) => {
          fs.writeFile(targetPath + '/' + ob);
        });
      } else {
        fs.mkdir(targetPath + '/' + item[1].replace('./project', ''), function() {})
      }
    });
  }
  function pushArr(path) {
    fs.readdir(path, function(files) {
      files.forEach((item, index) => {
        fs.stat(path + '/' + item, (err, stat) => {
          if (stat.isDirectory()) {
            ob.push(['dir', path]);
            pushArr(path + '/' + item);
          } else {
            ob.push(['file', path]);
          }
        });
      });
    });
  }
}

如何构建CLI

项目脚手架 Vue-cli

  • 下载项目初始化模板
  • 定义项目规则
  • 定义项目操作命令

CLI 工具工作流程:用户输出初始化命令-打开脚本与用户交互-根据命令下载模板-模板下载成功-提示用户

递归,每次递归将文件路径拿出来,变成数组;然后遍历数组,创建文件

具体的文件不好操作时,先把树结构抽象出来;创建文件和创建文件夹;读写和遍历,耦合比较高

读写文件是异步操作;循环中如果有异步操作,node,最好是forEach,避免异步

for循环会造成异步错误

前端为什么趋向于软件工程?前端现在变成独立的种类。前端项目的复杂化,带来难度增加,所以软件工程内容开始在前端出现。

工程化:标准

  • 命令行工具:vue-cli react-create-app
  • 规范 ESLint
  • 测试:单元测试,e2e
  • 构建:webpack
  • 集成和部署:CI CD docker
  • 代码管理:git

自己尝试把SDK打包压缩了,现在只是babel处理了,没有压缩(现在只是编译成ES5,没有打包和压缩,实际上可以使用webpack压缩,因为内部三个模块是互相依存的,对外输出一个模块);自己的JS基础要很扎实,否则后期工程化会遇到很多问题;


Last update: November 9, 2024