为什么需要脚手架?详解node构建脚手架的步骤

为什么需要脚手架?怎么搭建脚手架?下面本篇文章介绍一下node构建脚手架的步骤,希望对大家有所帮助!

为什么需要脚手架?详解node构建脚手架的步骤

1 为什么需要脚手架

根据交互动态生成项目结构和配置文件等。用户通过命令交互的方式下载不同的模版经过模版引擎渲染定制项目模版模版变动,只需更新模版即可,不需要用户更新脚手架 【相关教程推荐:nodejs视频教程、编程教学】

2 构建步骤

新建mycli文件夹(可自定义文件名),下方新建bin文件,bin文件新建index.js,这个index.js就是入口文件,index.js文件头部加入#!/usr/bin/env node代码

生成package.json文件,此时会有个bin配置对象,key值即为全局脚手架名称,value是入口文件bin文件的index.js路径。

    npm init -y    npm install

登录后复制

为什么需要脚手架?详解node构建脚手架的步骤

将脚手架全局命令链接到全局,终端打印mycli即链接成功。

//命令可以将一个任意位置的npm包链接到全局执行环境,从而在任意位置使用命令行都可以直接运行该npm包。npm link

登录后复制

安装依赖

  npm install commander inquirer@8.2.5 download-git-repo chalk@4.1.2 ora@5.4.1 figlet handlebars

登录后复制commander:命令行工具,有了它我们就可以读取命令行命令,知道用户想要做什么了inquirer: 交互式命令行工具,给用户提供一个漂亮的界面和提出问题流的方式download-git-repo:下载远程模板工具,负责下载远程仓库的模板项目chalk:颜色插件,用来修改命令行输出样式,通过颜色区分 info、error 日志,清晰直观ora:用于显示加载中的效果,类似于前端页面的 loading 效果,像下载模板这种耗时的操作,有了 loading 效果可以提示用户正在进行中,请耐心等待figlet :镂空字体样式

注意:下方代码都放在bin文件index.js进行调试

2.1 commander.js概述

commander.js是一个工具,用来构建node的命令行程序,使得能够使用自定义指令在全局命令行运行node脚本。本来我们只能在脚本所在文件的根目录里通过node xxx.js运行脚本,通过commander构建命令行程序后,就能在任意一个目录里,比如桌面,比如用户目录,直接输入自定义的那个指令,就能直接运行脚本,更加简便。

#!/usr/bin/env node//就是解决了不同的用户node路径不同的问题,可以让系统动态的去查找node来执行你的脚本文件。//node.js内置了对命令行操作的支持,在 package.json 中的 bin 字段可以定义命令名和关联的执行文件。const program = require("commander")program.version('1.1.0')function getFramwork (val) {  console.log(val);}const myhelp = function (program) {  program.option('-f --framwork ', '设置框架', getFramwork)}const createProgress = function (program) {  program.command('create  [other...]')    .alias('crt')    .description('创建项目')    .action((progress, arg) => {      console.log(progress, arg);    })}myhelp(program);createProgress(program);program.parse(process.argv)// 补充.parse()// 作用就是解析,参数就是要解析的字符串,一般使用时参数就是用process.argv,就是用户输入参数

登录后复制

执行全局命令mycli即可输出所有命令~~

image.png

2.2 download-git-repo

download(repository, destination, options, callback)repository:下载地址destination:下载路径options:配置项 {clone:true}callback:下载后的回调

#!/usr/bin/env nodeconst download = require('download-git-repo');download('direct:https://gitlab.com/flippidippi/download-git-repo-fixture.git', "xxx", { clone: true }, (err) => {  console.log(err ? 'Error' : 'Success')})

登录后复制

执行mycli即可看到文件下生成一个xxx文件

image.png

2.3 Inquirer(命令交互)

inquirer 是一个常用的交互式终端用户界面集合。 简单来说 inquirer 是可以让我们很方便的做各种终端交互行为的一个库。

inquirer 主要提供了三个方法方便我们注册问题

prompt(questions) => promise该方法就是 终端交互的核心方法,运行 prompt 方法即告诉终端启动 交互式命令界面。 – prompt 方法需要传入一个 questions 数组, questions 数组包含对象形式的各个 question. question 的具体结构字段含义在后文介绍。 – prompt 方法的返回值是一个 promise 对象,promise.then 接收的返回值是 answers 对象,answers 对象包含前面所有问题回答的数据结果。

#!/usr/bin/env nodeconst inquirer = require("inquirer")function getUsername() {  return inquirer    .prompt([      {        type: "input",        name: "progress",        message: "请输入项目名称",        default: "progress",        filter(input) {          return input.trim()        },        validate(input) {          return input.length > 0        },      },    ])    .then((answer) => {      console.log(answer)    })}function getFramework() {  return inquirer    .prompt([      {        type: "list",        name: "framework",        choices: [          "express",          new inquirer.Separator(),          "koa",          new inquirer.Separator(),          "egg",        ],        message: "请选择你所使用的框架",      },    ])    .then((answer) => {      console.log(answer)    })}function getSelect() {  return inquirer    .prompt([      {        type: "checkbox",        name: "userndasde",        choices: [          { name: "pr", disabled: true },          { name: "oa", checked: true },          "gg",        ],        message: "需要的验证格式",        // default: ["oa"],      },    ])    .then((answer) => {      console.log(answer)    })}async function init() {  await getSelect()  await getUsername()  await getFramework()}init()

登录后复制

2.4 ora and chalk(美化)

在用户输入答案之后,开始下载模板,这时候使用 ora 来提示用户正在下载中。

注意:注意版本不同引入方式不同,这里用ora(版本5.4.1) ,chalk(版本4.1.2)

const ora = require("ora")const chalk = require("chalk")const spinner = ora("Loading unicorns").start()spinner.text = chalk.blue("下载中~~~~~~")setTimeout(() => {  spinner.succeed(chalk.red("下载成功!"))  spinner.fail("下载失败!")  spinner.warn("警告!")}, 2000)

登录后复制

2.5 figlet(镂空文字)

镂空文字调试器地址:地址

figlet旨在完全实现JavaScript中的FIGfont规范。它可以在浏览器和Node.js中工作。

用法

figlet.text( description,{options},callback(err,data){}) 这个是异步的会被

参数

description:需要格式化的字符串

options:参数配置

Font:字体,Default value:Standard;horizontalLayout:布局,Default value:default; Values:{default,full,fitted};verticalLayout:垂直布局, Default value:default; Values:{defalut,full,fitted,controlled smushing,universal smushing};Width:宽度;whitespaceBreak:换行(Boolean); Default value:false

callback(err,data):回调

const figlet = require("figlet")const chalk = require("chalk")//简单函数function handleAsync(params) {  const JAVASCRIPT = figlet.textSync(    "NODEJS",    {      font: "big",      horizontalLayout: "fitted",      verticalLayout: "controlled smushing",      width: 600,      whitespaceBreak: true,    },    function (err, data) {      if (err) {        console.log("Something went wrong...")        console.dir(err)        return      }      console.log(data)    }  )  console.log(chalk.blue.bold(JAVASCRIPT))}handleAsync()

登录后复制

image.png

总结

创建一个完整的脚手架

目录结构:

为什么需要脚手架?详解node构建脚手架的步骤

bin/index.js
#!/usr/bin/env nodeconsole.log("adas");require("../lib/commander/index.js")

登录后复制

lib/commonder/index.js
const program = require("commander")const init = require('../inquirer/index');const downloadFun = require("../core/download.js");program.version('1.1.0')function getFramwork (val) {  console.log(val);}const myhelp = function (program) {  program.option('-f --framwork  [other...]', '设置框架', getFramwork)}const createProgress = function (program) {  program.command('create  [other...]')    .alias('crt')    .description('创建项目')    .action((progress, arg) => {      init();    })}const downloadUrl = function (program) {  program.command('download  [...other]')    .description('下载内容')    .action((url, ...args) => {      console.log(args);      downloadFun(url, args[1].args[1])    })}myhelp(program);downloadUrl(program);createProgress(program)program.parse(process.argv)

登录后复制lib/core/action.js (package.json重写)

const fs = require('fs');const path = require("path");const handlebars = require("handlebars");  function modifyPackageJson (options) {    let downloadPath = options.projectName;    const packagePath = path.join(downloadPath, 'package.json');    console.log(packagePath, "packagePath");        //判断是否存在package.json文件    if (fs.existsSync(packagePath)) {      let content = fs.readFileSync(packagePath).toString();            //判断是否选择了eslint      if (options.isIslint) {        let targetContent = JSON.parse(content);        content = JSON.stringify(targetContent);        targetContent.dependencies.eslint = "^1.0.0";        console.log("content", content);      }            //写入模板      const template = handlebars.compile(content);      const param = { name: options.projectName };      const result = template(param);            //重新写入package.json文件      fs.writeFileSync(packagePath, result);      console.log('modify package.json complate');    } else {      throw new Error('no package.json');    }  }  module.exports = modifyPackageJson

登录后复制lib/core/download.js

  const download = require('download-git-repo');  const ora = require("ora");  const chalk = require("chalk");  const figlet = require("figlet");  const modifyPackageJson = require("./action")    function handleAsync (params) {    const JAVASCRIPT = figlet.textSync('JAVASCRIPT', {      font: 'big',      horizontalLayout: 'fitted',      verticalLayout: 'controlled smushing',      width: 600,      whitespaceBreak: true    }, function (err, data) {      if (err) {        console.log('Something went wrong...');        console.dir(err);        return;      }      console.log(data);    });    console.log(chalk.blue.bold(JAVASCRIPT));  }    const downloadFun = (url, option) => {    const spinner = ora("Loading unicorns").start()    spinner.text = chalk.blue("下载中");        download(url, option.projectName, { clone: true }, function (err) {      if (err) {        spinner.fail("下载失败!");        handleAsync()      } else {        spinner.succeed(chalk.red("下载成功!"))        console.log(chalk.blue(`cd ${option.projectName}`))        console.log(chalk.red("npm install"))        console.log(chalk.yellow(`npm run dev`))        modifyPackageJson(option)        handleAsync()      }    })  }  module.exports = downloadFun;

登录后复制inquire/index.js 注意frameworkConfig写自己的gitlab仓库地址

  const inquirer = require("inquirer");  const downloadFun = require("../core/download.js");  const frameworkConfig = {    front: "https://gitlab.com/flippidippi/download-git-repo-fixture.git",    manager: "https://gitlab.com/flippidippi/download-git-repo-fixture.git"  }  const config = {};    function getFramework () {    return inquirer.prompt([      {        type: 'list',        name: 'framework',        choices: ["front", "manager"],        message: "请选择你所使用的框架"      }    ]).then((answer) => {      return answer.framework;    })  }    function getProjectName () {    return inquirer.prompt([      {        type: 'input',        name: 'projectName',        message: '项目名称',        filter (input) {          return input.trim();        },      }    ]).then((answer) => {      console.log(answer, "FDsfs");      return answer.projectName;    })  }    function getIsEslint () {    return inquirer.prompt([      {        type: 'confirm',        name: 'isIslint',        message: '是否使用eslint校验格式?'      }    ]).then((answer) => {      return answer.isIslint;    })  }    async function init () {    config.projectName = await getProjectName();    config.framework = await getFramework();    config.isIslint = await getIsEslint();    let url = config.framework == "front" ? frameworkConfig.front : frameworkConfig.manager;    downloadFun("direct:" + url, config);  }  module.exports = init;

登录后复制

更多node相关知识,请访问:nodejs 教程!

以上就是为什么需要脚手架?详解node构建脚手架的步骤的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2631242.html

(0)
上一篇 2025年3月7日 03:49:23
下一篇 2025年3月6日 12:06:41

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论