脚手架

优质
小牛编辑
133浏览
2023-12-01

前言

相信很多人都用过vue-clicreate-react-app或者类似的脚手架。
脚手架方便我们复制,粘贴,或者clone代码库,而且还可以更具用户的选择,引入用户所需要的插件。
脚手架往往搭配着早已设计好了架构的项目,然后按需进行拷贝。

Yeoman

介绍

官网介绍: The web's scaffolding tool for modern webapps.

yeoman是一款来做脚手架的工具,我们借助它,就能很容易地开发出自己的脚手架了。
yeoman具体的使用,本文不会介绍太多,官网的文档差不多就够了,我也会在文章末尾放上自己搜集的一些参考资料,同学们自己看看就好了。

安装

安装yeoman: npm install -g yo

generator

generator其实就是一个node module,即npm。yeoman根据我们写的generator来执行我们写的构建代码。(对怎么自己选一个npm包不熟悉的同学,可以戳这里>>
generator文件夹必须以generator-开头,然后之后跟上自定义的脚手架名字,比如generator-zx-vue,将它做成npm包以后,上传到npm官网,只有在电脑上全局安装,然后用yoman运行就好了,之后会详细介绍。

创建自己的generator

除了手动创建自己的generator项目,我们还可以通过别人已经做好的脚手架来创建。
安装generator-generator: npm install -g generator-generator
然后,运行脚手架: yo generator
之后,我们就可以看到一系列的提示,按照提示输入完信息以后,我们就有了一份编写自己的generator的模板项目了。

编写自己的generator

其实,这个generator脚手架生成的很多文件我们都不需要管,我们只需要把注意力放在generator/app这个文件夹下的内容就好了。
templates文件是用来作为仓库,我们在编写脚本的时候,如果需要哪些文件,就直接去这个仓库里copy出来就好了。

划重点

1. 问题

因为我们自己做的generator是一个npm包,我们自然希望对其进行版本管理,用上git,方便今后的迭代。
templates其实也是一个独立的项目,我们之前说了,它是一个早已完成了的项目架子,我们是从gitlab或者github上copy过来的而已。那该怎么管理这两个不同的项目呢?

2. 解决-git子模块

git用的6的同学肯定一下子就想到git子模块的知识了。
不熟悉的同学可以戳 git文档-子模块>>

因此,我们不是把项目copy进templates,也不是git clone进templates,而是先删除app文件夹下的templates,然后:
git submodule add https://github.com/CodeLittlePrince/vue-construct-for-zx-vue.git templates
这样的话,我们就可以更新自己的仓库项目(vue-construct-for-zx-vue),generator项目的话,pull子模块就好了。两者保持独立,方便迭代和维护。

实际运用submodule后发现,其实真的很难让作为模板的项目独立运行,而且它的.git也会影响实际项目的git配置,所以不再采用submodule。

编写构建脚本

接下来,我们就可以来编写app文件夹下的index.js文件了:

const Generator = require('yeoman-generator')
const chalk = require('chalk')
const yosay = require('yosay')
const path = require('path')
const fs = require('fs')

module.exports = class extends Generator {
  initializing() {
    // 打印欢迎语
    this.log(
      yosay(`Welcome to the shining ${chalk.cyan('generator-zx-vue')} generator!`)
    )
  }
  prompting() {
    // 让用户选择是否需要包含vuex
    const prompts = [
      {
        type: 'input',
        name: 'name',
        message: 'Name of project:',
        default: path.basename(process.cwd())
      },
      {
        type: 'input',
        name: 'description',
        message: 'Description:',
        default: '',
      },
      // {
      //   type: 'confirm',
      //   name: 'includeVuex',
      //   message: 'Would you like to include Vuex in your project?',
      //   default: false,
      // }
    ]
    return this.prompt(prompts).then(answers => {
      this.name = answers.name
      this.description = answers.description
      // this.includeVuex = answers.includeVuex
      this.log(chalk.green('name: ', this.name))
      this.log(chalk.green('description: ', this.description))
      // this.log(chalk.green('includeVuex: ', this.includeVuex))
    })
  }

  writing() {
    // 复制普通文件
    // https://github.com/sboudrias/mem-fs-editor
    this.fs.copyTpl(
      this.templatePath(),
      this.destinationPath(),
      {
        name: this.name
      },
      {},
      { globOptions:
        {
          dot: true
        }
      }
    )
    // 根据用户选择,决定是否安装vuex
    if (this.includeVuex) {
      const pkgJson = {
        name: this.name,
        description: this.description,
        // dependencies: {
        //   vuex: '^3.0.1'
        // }
      }
      // Extend or create package.json file in destination path
      this.fs.extendJSON(this.destinationPath('package.json'), pkgJson)
    }
  }

  install() {
    this.npmInstall()
  }

  end() {
    this.log(chalk.green('Construction completed!'))
  }
}

语法很简单,具体可以自己看yeoman官方文档,我简单的介绍一下几个比较常用的函数,或者说生命周期:

函数名我用来做什么
initializing我用来写一些欢迎语
prompting与用户的交互,比如input、checkbox、confirm等
writing拷贝和编辑文件
install安装依赖,如npm install
end写一些如goodbye的结束语

本地测试是否有用

没发布上线的npm包,本地测试只需要link一下就好了,到generator根目录,然后运行npm link,这样我们就可以使用我们的generator了,比如,到一个新的空文件夹下运行:yo zx-vue,就可以看到项目开始自动构建了。
测试完成后,就可以发布到npm官网了,发布流程可参考我另一篇文章npm-从0开始写一个npm module

zx-vue

目的

zx-vue是一个以vue-construct作为模板仓库的脚手架,为了方便新项目构建,也为了今后的新项目能够统一。

使用

首先,安装全局yeomman和generator-zx-vue
npm install -g yo
npm install -g generator-zx-vue
然后找一个空的文件夹执行:
yo zx-vue
生成项目以后的操作可以参考vue-construct
最后,generator-zx-vue的地址是generator-zx-vue

结尾

我之前原本打算把vuex作为一个可选项,让用户选择是否引入这个库。
但是,做下来以后发现,因为用到了ejs模板去做这个事情,然后,最终输出的文件会因为<% if (condition) { %>这种ejs语法导致换行,或者缩进不符合eslint。当然,我也可以把项目弄的更空一点,把所有vuex的使用清掉,但这样也不是很好,因为我又想让用户跑起来这个项目就能看到整个全家桶的效果在页面上使用到。
其实还有另外一种比较暴力的方法就是,我弄一个有vuex的项目,一个没有vuex的项目,然后选择copy哪份,,太暴力。
憋了好久也没想到什么很好接受的方法,所以就暂且把vuex也直接带上。
最后,也希望有想法的同学还有大佬多多留言,给点建议^_^

最终,我还是选择了算是暴力的模式把,将用vuex和不用vuex的分为两个代码仓库,详细可以参见子咻的vue脚手架——zx-vue

参考资料

yeoman官方文档

使用Yeoman定制前端脚手架

别人写的脚手架generator-webapp

文件操作相关

node-glob参数

ejs文档

git-子模块