首頁  >  文章  >  web前端  >  為什麼需要腳手架?詳解node建造鷹架的步驟

為什麼需要腳手架?詳解node建造鷹架的步驟

青灯夜游
青灯夜游轉載
2023-04-10 19:06:061390瀏覽

為什麼需要鷹架?怎麼搭建鷹架?以下這篇文章介紹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
將腳手架全域指令連結到全域,終端列印
    mycli
  • 即連結成功。 <pre class="brush:js;toolbar:false;">//命令可以将一个任意位置的npm包链接到全局执行环境,从而在任意位置使用命令行都可以直接运行该npm包。 npm link</pre>
  • 安裝依賴
  •   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腳本。本來我們只能在腳本所在檔案的根目錄裡透過

node xxx.js

運行腳本,透過commander建置命令列程式後,就能在任意一個目錄裡,例如桌面,例如使用者目錄,直接輸入自訂的那個指令,就能直接執行腳本,更加簡單。

#!/usr/bin/env node
//就是解决了不同的用户node路径不同的问题,可以让系统动态的去查找node来执行你的脚本文件。
//node.js内置了对命令行操作的支持,在 package.json 中的 bin 字段可以定义命令名和关联的执行文件。
const program = require("commander")
program.version(&#39;1.1.0&#39;)

function getFramwork (val) {
  console.log(val);
}

const myhelp = function (program) {
  program.option(&#39;-f --framwork <framwork>&#39;, &#39;设置框架&#39;, getFramwork)
}

const createProgress = function (program) {
  program.command(&#39;create <progress> [other...]&#39;)
    .alias(&#39;crt&#39;)
    .description(&#39;创建项目&#39;)
    .action((progress, arg) => {
      console.log(progress, arg);
    })
}
myhelp(program);
createProgress(program);
program.parse(process.argv)
// 补充
.parse()
// 作用就是解析,参数就是要解析的字符串,一般使用时参数就是用process.argv,就是用户输入参数
    執行全域指令
  • mycli即可輸出所有指令~~
  • #2.2 download-git-repo
  • #download
  • (repository, destination, options, callback)
  • repository
  • :下載位址
  • destination
  • :下載路徑

options:設定項{clone:true}

#callback

:下載後的回呼為什麼需要腳手架?詳解node建造鷹架的步驟

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

執行

mycli

即可看到檔案下產生一個xxx檔案

#2.3 Inquirer(指令互動)
  • inquirer 是一個常用的互動式終端使用者介面集合。簡單來說 inquirer 是可以讓我們很方便的做各種終端互動行為的一個函式庫。 inquirer 主要提供了三個方法方便我們註冊問題

#prompt(questions) => promise

該方法就是終端交互的核心方法,運行prompt 方法即告訴終端啟動互動式命令介面。 - prompt 方法需要傳入一個 questions 數組, questions 數組包含物件形式的各個 question. question 的具體結構字段含義在後文介紹。 - prompt 方法的回傳值是 promise 對象,promise.then 接收的回傳值是

answers

對象,answers 物件包含前面所有問題回答的資料結果。

#!/usr/bin/env node
const 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()

為什麼需要腳手架?詳解node建造鷹架的步驟

总结

创建一个完整的脚手架

目录结构:

  • bin/index.js
#!/usr/bin/env node
console.log("adas");
require("../lib/commander/index.js")
  • lib/commonder/index.js
const program = require("commander")
const init = require(&#39;../inquirer/index&#39;);
const downloadFun = require("../core/download.js");
program.version(&#39;1.1.0&#39;)
function getFramwork (val) {
  console.log(val);
}
const myhelp = function (program) {
  program.option(&#39;-f --framwork <framork> [other...]&#39;, &#39;设置框架&#39;, getFramwork)
}
const createProgress = function (program) {
  program.command(&#39;create <progress> [other...]&#39;)
    .alias(&#39;crt&#39;)
    .description(&#39;创建项目&#39;)
    .action((progress, arg) => {
      init();
    })
}
const downloadUrl = function (program) {
  program.command(&#39;download <url> [...other]&#39;)
    .description(&#39;下载内容&#39;)
    .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(&#39;fs&#39;);
const path = require("path");
const handlebars = require("handlebars");
  function modifyPackageJson (options) {
    let downloadPath = options.projectName;
    const packagePath = path.join(downloadPath, &#39;package.json&#39;);
    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(&#39;modify package.json complate&#39;);
    } else {
      throw new Error(&#39;no package.json&#39;);
    }
  }
  module.exports = modifyPackageJson
  • lib/core/download.js
  const download = require(&#39;download-git-repo&#39;);
  const ora = require("ora");
  const chalk = require("chalk");
  const figlet = require("figlet");
  const modifyPackageJson = require("./action")
  
  function handleAsync (params) {
    const JAVASCRIPT = figlet.textSync(&#39;JAVASCRIPT&#39;, {
      font: &#39;big&#39;,
      horizontalLayout: &#39;fitted&#39;,
      verticalLayout: &#39;controlled smushing&#39;,
      width: 600,
      whitespaceBreak: true
    }, function (err, data) {
      if (err) {
        console.log(&#39;Something went wrong...&#39;);
        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: &#39;list&#39;,
        name: &#39;framework&#39;,
        choices: ["front", "manager"],
        message: "请选择你所使用的框架"
      }
    ]).then((answer) => {
      return answer.framework;
    })
  }
  
  function getProjectName () {
    return inquirer.prompt([
      {
        type: &#39;input&#39;,
        name: &#39;projectName&#39;,
        message: &#39;项目名称&#39;,
        filter (input) {
          return input.trim();
        },
      }
    ]).then((answer) => {
      console.log(answer, "FDsfs");
      return answer.projectName;
    })
  }
  
  function getIsEslint () {
    return inquirer.prompt([
      {
        type: &#39;confirm&#39;,
        name: &#39;isIslint&#39;,
        message: &#39;是否使用eslint校验格式?&#39;
      }
    ]).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建造鷹架的步驟的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除