如何打造自己的脚手架

560 阅读5分钟

什么是脚手架?

脚手架本质上是操作系统的客户端,能够快速生成项目的目录和底层架构的前端工程化技术。

为什么使用脚手架?

  • 能够快速启动项目
  • 能够自主选择一些架构功能
  • 能够保持项目的统一性
  • 可以很好的帮助我们进行技术沉淀

脚手架的实现原理?

通过思考几个问题来理解脚手架的实现的原理,以vue-cli脚手架为例

为什么全局安装 @vue/cli 后会添加的命令为vue?

在@vue/cli/package.json bin 属性指定了 "bin":{ "vue":"./bin/vue.js" }

全局安装 @vue/cli的时候发生了什么

  • 将@vue/cli 下载到全局环境下面的node_modules 里面
  • 解析 package.json 里面的bin 属性
  • 在全局 bin 下面创建软链接

执行vue命令的时候发生了什么

首先了解脚手架有几部分组成(以vue create demo-test --force -r registry.npm.taobao.rog为例)

主命令:vue

Command 子命令 :create

Command 的 param: demo-test

Option : --force 、 -r

Option 的param :registry.npm.taobao.rog

脚手架的执行流程

通过which vue 查看 vue 这个命令执行文件,得出的结果是 /usr/local/bin/vue

这个vue文件是个软连接,通过 ls -al 命令可以查出vue指向的文件地址,也就是 ../lib/node_moduels/@vue/cli/bin/vue.js

文字总结:

  • 终端输入 命令 vue create demo-test --force -r registry.npm.taobao.org

  • 终端解析 vue 命令 ,并找到执行文件

  • 利用node 执行 vue.js 文件

  • vue.js 解析 command/option

  • vue.js 执行 command/option

  • 脚手架执行完毕

为什么vue指向一个js文件,我们却可以直接通过vue命令去执行它?

在文件头部加入 注释

 #!/usr/bin/env node  

告诉系统在环境变量中寻找node 来执行此文件。所以 vue.js 就可以直接运行。不用写 node vue.js

开发脚手架包基本的目录结构是什么?

无法复制加载中的内容

如何注册脚手架命令

package.json 文件里面配置bin 属性

"bin": {

    "butterfly-mp-cli": "bin/index.js"  //脚手架核心文件

  }

如何进行本地调试

在项目目录下面执行 npm link ,就能在本地添加了 butterfly-mp-cli 命令。项目发布之后记得npm unlink 取消发布

如何发布脚手架

npm login

npm publish

如何进行多包调试?

创建依赖库项目

{

  "name": "butterfly-mp-lib",

  "version": "1.0.0",

  "description": "butterfly-mp-cli 库文件",

  "main": "lib/index.js",  // 指定核心文件

  "directories": {

    "lib": "lib"

  },

  "scripts": {

    "test": "echo "Error: no test specified" && exit 1"

  },

  "author": "",

  "license": "ISC"

}

npm link 后就可以在cli 项目通过手动配置 就能访问到库文件

"devDependencies": {

    "butterflu-cli-lib": "^1.0.0"

 }

如何进一步完善自己的脚手架

一个完整的脚手架应该包含如下部分

  • 注册脚手架子命令(command)
  • 注册子命令配置(option)
  • 能解析option 的 param
  • 复杂脚手架能运用分包
  • 能提供帮助文档
  • 能进行命令行的交互
  • 能打印日志
  • 能处理文件

要想实现以上的功能我们就要借助个脚手架开发库yargs,来一点点帮助我们完善脚手架。

#!/usr/bin/env node

const yargs = require('yargs/yargs')

const { hideBin } = require('yargs/helpers')

const dedent = require('dedent')

const argv = hideBin(process.argv)

const cli = yargs(argv)

cli

  .strict() // 严格模式

  .alias('h', 'help') //缩写

  .alias('v', 'version')

  .wrap(cli.terminalWidth()) //设置输出宽度

  .epilogue(dedent`这是商城小程序脚手架`) // 尾部添加注释

  .demandCommand(

    1,

    'A command is required. Pass --help to see all available commands and options.'

  )

  .options({

    debugger: {

      type: 'boolean',

      describe: 'Dev Debugger',

      alias: 'd',

    },

    log: {

      type: 'string',

      alias: 'l',

      describe: '这是日志',

    },

  }) // 添加options

  .option('console', {

    type: 'string',

    describe: '这是console',

    alias: 'c',

  }) // 添加option

  .group(['help', 'version'], 'Global Options') // 将options 分组

  .command(

    'init [name]',

    'Do init',

    (yargs) => {

      yargs.options({

        name: {

          type: 'string',

          describe: 'The project name',

          alias: 'n',

        },

      })

    },

    (argv) => {

      console.log(argv)

    }

  )

  .command({

    command: 'create',

    aliases: ['c'],

    builder: (yargs) => {

      yargs.option('name', {

        alias: 'n',

        describe: 'The name',

        type: 'string',

      })

    },

    handler: (argv) => {

      console.log(argv)

    },

  })

  .recommendCommands() //校验提示命令

  .fail((err, msg) => {

    // 输入错误定制信息

    console.log('err', err)

    console.log('msg', msg)

  }).argv

最终效果:

yargs使用总结:

  • strict() 使用严格模式
  • alias() 使用别名
  • wrap() 控制输出的文字宽度
  • options() 以对象的方式添加options
  • command() 添加主命令
  • option() 单个添加option
  • group() 将option分组
  • recommendCommands() 校验命令并给出提示
  • fail() 命令输出错误的回调函数

如何对项目进行多package 管理

Lerna 简介

Lerna 是一个优化基于git+npm 的多package项目管理工具。Lerna 是架构优化的产物,它解释了一个架构真理;项目复杂度提升后,就需要对项目进行架构优化,架构优化的主要目的往往都是以效能为核心。

lerna解决了那些痛点?

  • 重复操作的步骤

    • 多package 本地link
    • 多package 依赖安装
    • 多package 单元测试
    • 多package 代码提交
    • 多package 代码发布
  • 版本一致性

    • 发布时版本一致性
    • 发布后相互依赖版本升级

如何使用Lerna 开发脚手架

安装lerna

npm install lerna -g

了解lerna命令

  • lerna publish
  • lerna version

脚手架代码更新后,可以用来升级脚手架版本。

  • lerna bootstrap

给每个package添加添加所有依赖

  • lerna list
  • lerna changed
  • lerna diff
  • lerna exec

Lerna exec -- rm -f node_modules 在每个package里面执行shell 命令

  • lerna run

执行每个package下面的npm 命令

  • lerna init
  • lerna add

给每个package添加依赖

  • Lerna clean

请空package下面点node_modules 包依赖

  • lerna import
  • lerna link

给package之间的相互依赖添加link

  • lerna create

Lerna create 创建一个新的packgae包

  • lerna info

开始使用

  • 创建脚手架文件夹 butterfly-mp-cli-test
  • 初始化npm npm init
  • 初始化lerna lerna init
  • 创建核心包cli lerna create cli
  • 创建的时候将 包名命名为 @butterfly-mp-cli-test/cli(@butterfly-mp-cli-test npm 组织名)
  • 在cli包里面按照上面讲的配置脚手架命令 bin:{'butterfly-mp-cli-test': 'bin/index.js'}
  • 在项目根目录 添加LICENSE.md (开源声明文件)
  • 在cli包 package.json 添加 "publishConfig": {"access": "public"} 将包设置为公开类型
  • 最后 发布 lerna publish

总结

可以通过lerna 框架和实现部门npm库的搭建和管理,通过yargs 来实现和完善项目脚手架。