前端如何搭建一個簡單的腳手架

前言

這裏先簡單瞭解一下基礎知識,接下來會基於typescript和rollup參考寫一個較爲完整的腳手架(動態模板),如下只能拉取較爲簡單的靜態模板。javascript

基礎

腳手架發佈和安裝

這裏假設咱們的腳手架名字是ds-cli,如下都用這個名字。咱們在命令行使用腳手架命令爲ds前端

  • 咱們怎麼樣讓用戶經過npm或者yarn全局安裝ds-cli以後,在終端能執行ds命令呢?答案就在package.json的bin字段
  • 當咱們bin字段指向咱們的目標文件main.js,同時目標文件開頭具備
//這裏是main.js
#!/usr/bin/env node

// --這種用法是爲了防止操做系統用戶沒有將node裝在默認的/usr/bin路徑裏。當系統看到這一行的時候,
// 首先會到env設置裏查找node的安裝路徑,再調用對應路徑下的解釋器程序完成操做。
//這裏是package.json
"bin": {
    "ds": "./main.js"
}
複製代碼
  • 這樣當咱們發佈上npm,別人下載下來後,就能夠直接使用ds命令了。

解析命令行

  • 如何輕鬆便捷的讀取命令行裏的參數呢?這裏咱們使用tj大神的commander
const cmd = require("commander");

// 好比咱們想執行ds init **的命令,想出現「初始化組件模板」的描述
// action是執行這個命令後續的回調,...args是後面**的參數
cmd
  .command('init')
  .description('初始化組件模板')
  .action((...args) => {});

//解析命令行
cmd.parse(process.argv);
複製代碼

用戶交互

咱們經過詢問用戶來得到必定的交互,這樣能夠知道用戶須要什麼vue

  • 採用inquirer詢問項目描述,做者
//好比咱們在上面那個action裏面搞事情,即ds init以後問用戶
...action((...args)=>{
    inquirer
      .prompt([
        {
          name: "description",
          message: "請輸入項目描述"
        },
        {
          name: "author",
          message: "請輸入做者名稱"
        }
      ]).then(answers=>{
          //在這裏得到上面的答案
          console.log(answers.description,answers.author)
      })
})
複製代碼

拉取遠程的倉庫

const download = require("download-git-repo");
// 第一個git地址,第二個name是git clone下來後的名字...
download(
    "https://github.com/yokiyokiyoki/vue-fullpage.git#master",
    name,
    { clone: true },
    err => {
    ...
    }
);
複製代碼

簡單的模板替換

  • 咱們經過詢問交互後,確定內部作了些改變。這裏咱們能夠把package.json的做者和描述簡單改了
  • 能夠使用handlebars,模板語法簡單
//這個是經過download-git-repo拉下來的package.json
{
    "author":"{{author}}",
    "description":"{{description}}"
}
複製代碼
  • 而後咱們經過讀取文件字符串給handbars編譯一下拿到的變量,再寫入
//經過詢問拿到的answers
const meta = {
    name,
    description: answers.description,
    author: answers.author
};
const fileName = `${name}/package.json`;
//判斷一下是否有這個文件
if (fs.existsSync(fileName)) {
    const content = fs.readFileSync(fileName).toString();
    const result = handlebars.compile(content)(meta);
    fs.writeFileSync(fileName, result);
}
複製代碼

終端的一些效果

  • 高亮終端打印出來的信息:chalk。如chalk.green('成功了'),chalk.red('失敗了')
  • 終端加載效果:ora,有個loading效果
const spinner = ora("正在下載模板...");
spinner.start();
spinner.succeed();
複製代碼

源碼

#!/usr/bin/env node
// --這種用法是爲了防止操做系統用戶沒有將node裝在默認的/usr/bin路徑裏。當系統看到這一行的時候,
// 首先會到env設置裏查找node的安裝路徑,再調用對應路徑下的解釋器程序完成操做。
const program = require("commander");
const download = require("download-git-repo");
const inquirer = require("inquirer");
const handlebars = require("handlebars");
const fs = require("fs");
const ora = require("ora");
const chalk = require("chalk");
const symbols = require("log-symbols");

program
  .version("0.0.1", "-v, --version")
  .command("init <name>")
  .action(name => {
    if (fs.existsSync(name)) {
      // 錯誤提示項目已存在,避免覆蓋原有項目
      console.log(symbols.error, chalk.red("項目已存在"));
      return;
    }
    inquirer
      .prompt([
        {
          name: "description",
          message: "請輸入項目描述"
        },
        {
          name: "author",
          message: "請輸入做者名稱"
        }
      ])
      .then(answers => {
        download(
          "https://git.datatub.com:Uranus/general-template#master",
          name,
          { clone: true },
          err => {
            const spinner = ora("正在下載模板...");
            spinner.start();
            if (!err) {
              spinner.succeed();
              const meta = {
                name,
                description: answers.description,
                author: answers.author
              };
              const fileName = `${name}/package.json`;
              if (fs.existsSync(fileName)) {
                const content = fs.readFileSync(fileName).toString();
                const result = handlebars.compile(content)(meta);
                fs.writeFileSync(fileName, result);
              }
              console.log(symbols.success, chalk.green("項目初始化完成"));
            } else {
              spinner.fail();
              console.log(symbols.error, chalk.red(`拉取遠程倉庫失敗${err}`));
            }
          }
        );
      });
  });
//解析命令行
program.parse(process.argv);

複製代碼
  • 上面是main.js文件,而後修改一下package.json的字段(bin字段修改,模板變量)
  • 發佈npm(如何發佈,請參考這裏),本身經過npm全局下載以後體驗一下

下篇

前端如何搭建一個成熟的腳手架java

相關文章
相關標籤/搜索