likes
comments
collection
share

手把手带你开发你的第一个前端脚手架

作者站长头像
站长
· 阅读数 63

开发一个简单的脚手架

  1. 创建 npm 项目

首先创建一个文件夹,然后进入到该文件夹目录下,执行

npm init -y
  1. 创建脚手架入口文件bin/index.js,在index.js中添加如下代码
#!/usr/bin/env node

console.log('hello cli')
  1. 配置 package.json,添加 bin 属性
{
  "name": "yj-study-create-cli",
  "version": "1.0.1",
  "description": "",
  "bin": {
    "yj-study-create-cli": "bin/index.js"
  },
  "main": "index.js",
  ...
}
  1. 将脚手架发布到 npm
npm publish

当发布到npm之后,通过全局安装来使用下我们上面创建的脚手架:

npm install -g yj-study-create-cli

此时我们会在/**/.nvm/versions/node/v16.14.0/bin下看到该脚手架对应的可执行文件,这个文件就软链接到我们开发的bin/index.js文件。

手把手带你开发你的第一个前端脚手架

在命令行输入yj-study-create-cli之后,就会打印出hello cli

这样我们就完成了一个简单脚手架的开发,是不是非常简单。

脚手架的调试

当我修改了脚手架内容之后,每次都要通过npm publish上传到npm上面,然后在npm install才能看到效果,这样非常繁琐和不方便,那怎么调试脚手架呢?我们可以通过npm link把本地脚手架文件通过软链接的形式链接到全局。

首先进入到脚手架目录,执行:

npm link

可以发现在node/bin目录下面建立了一个可执行文件yj-study-create-cli,它指向了lib/node_modules/bin/index.js 手把手带你开发你的第一个前端脚手架

我们进入到这个bin/index.js看下:

手把手带你开发你的第一个前端脚手架

发现,它不是一个文件,它也是一个软链接,这个软链接指向了本地脚手架文件。

这样当我修改本地脚手架之后,在命令行输入yj-study-create-cli就能看到修改的效果。这样就完成了本地脚手架的调试。

脚手架引入本地库文件

我们知道脚手架开发过程中肯定会引入其他的库文件,如果这个库文件不是npm上的包,而是本地开发的,那如何引入呢?以及引入后如何调试呢?

首先我们新建一个本地库文件,执行npm init -y,然后新建一个lib/index.js,在里面写一个函数:

module.exports = {
  sum(a, b) {
    return a + b
  }
}

然后修改package.jsonmain.js字段:

"main": "lib/index.js",

最后执行npm link

手把手带你开发你的第一个前端脚手架

我们可以发现在node/v16.14.0/lib/node_modules/下存在一个yj-study-create-lib的软链接,它指向本地的库文件。

我们知道node/v16.14.0/lib/node_modules/是全局安装npm包的位置,现在库文件也被安装在这里,说明这个库文件被全局安装了,那么就可以在任何工程中可以引用。

现在脚手架工程需要引入这个包,首先进入到脚手架工程目录中,然后执行npm link yj-study-create-lib,它会在这个工程下安装yj-study-create-lib这个包:

手把手带你开发你的第一个前端脚手架

同时,需要手动的在package.json中添加:

"dependencies": {
    "yj-study-create-lib": "^1.0.0"
}

然后在脚手架中使用这个库文件:

#!/usr/bin/env node

const lib = require('yj-study-create-lib')

console.log(lib.sum(1, 2))

最后,在命令行中输入yj-study-create-cli,就能获得正确的结果。

npm link的理解

库文件 如果你开发的某个库,当你执行npm link时,就相当于在本地全局安装了这个库。

然后在使用这个库的工程中,执行npm link lib-name,就会在工程下的node_modules安装这个库文件,这样就可以使用这个库了。

如果你在工程中不想引用这个库了,执行npm unlink lib-name即可。如果出现报错,可以直接rm -rf node_modules,然后再重新安装npm install

如果想解除库文件链接到全局的node_modules,执行npm unlink,如果报错Must provide a package name to remove,则执行npm unlink -g即可。

脚手架文件

如果你开发的是一个脚手架,当你执行npm link时,会在node/bin下面创建一个可执行文件,这个可执行文件软链接到node/lib/node_modules所对应的文件,同时这个文件又软链接到本地的脚手架工程文件,这样当你修改脚手架逻辑时,在本地就能看到修改后的效果。

如果脚手架开发完了,可以通过npm remove -g cli-name去除对本地脚手架的软链接。

脚手架命令注册与参数解析

使用脚手架一般会跟上命令和相应的参数,比如:

yj-study-create-cli init --name

我们可以通过process.argv拿到这些参数:

手把手带你开发你的第一个前端脚手架

获取到这些参数之后,就可以执行对应的逻辑,比如:

const argv = process.argv
// 获取命令
const command = argv[2]
// 获取命令的参数
const options = argv.slice(3)
let [option, param] = options
option = option.replace('--', '')

// 命令对应的逻辑
const actions = {
  init({ option, param }) {
    console.log('执行init流程', option, param)
  }
}

// 根据命令执行对应的逻辑
if (commands[command]) {
  commands[command]({ option, param })
} else {
  console.log('请输入正确的命令')
}

这样就完成了脚手架命令注册和参数解析。命令对应的逻辑,可以采用分包策略,单独用一个库lib来管理。

当然,一个出色脚手架不可能这么简单,下面我们来看看一个优秀的脚手架包括那些内容。

优秀的脚手架包括哪些内容?

1. 命令注册

以vue脚手架为例,它可以注册很多命令,每个命令所对应的逻辑都可以用一个单独的包来管理,这样就将复杂的系统拆分成若干个模块。

vue create
vue add
vue invoke

2. 参数解析

vue command [options] <params>
  • options全称:--version--help
  • options简写:-V-h
  • 带params的options:--path /Users/sam/Desktop/vue-test

3. 帮助文档

一个清晰的帮助文档,能方便开发者更好的使用脚手架成功。

帮助文档分为全局的帮助文档,和各个命令对应的帮助文档。

vue脚手架对应的全局的帮助文档:

  • Usage
  • Commands
  • Options
Usage: vue <command> [options]

Options:
  -V, --version                              output the version number
  -h, --help                                 output usage information

Commands:
  create [options] <app-name>                create a new project powered by vue-cli-service
  add [options] <plugin> [pluginOptions]     install a plugin and invoke its generator in an already created project
  invoke [options] <plugin> [pluginOptions]  invoke the generator of a plugin in an already created project
  inspect [options] [paths...]               inspect the webpack config in a project with vue-cli-service
  serve [options] [entry]                    serve a .js or .vue file in development mode with zero config
  build [options] [entry]                    build a .js or .vue file in production mode with zero config
  ui [options]                               start and open the vue-cli ui
  init [options] <template> <app-name>       generate a project from a remote template (legacy API, requires @vue/cli-init)
  config [options] [value]                   inspect and modify the config
  outdated [options]                         (experimental) check for outdated vue cli service / plugins
  upgrade [options] [plugin-name]            (experimental) upgrade vue cli service / plugins
  migrate [options] [plugin-name]            (experimental) run migrator for an already-installed cli plugin
  info                                       print debugging information about your environment

  Run vue <command> --help for detailed usage of given command.

各个命令对应的帮助文档:

  • Usage
  • Options
Usage: create [options] <app-name>

create a new project powered by vue-cli-service

Options:
  -p, --preset <presetName>       Skip prompts and use saved or remote preset
  -d, --default                   Skip prompts and use default preset
  -i, --inlinePreset <json>       Skip prompts and use inline JSON string as preset
  -m, --packageManager <command>  Use specified npm client when installing dependencies
  -r, --registry <url>            Use specified npm registry when installing dependencies (only for npm)
  -g, --git [message]             Force git initialization with initial commit message
  -n, --no-git                    Skip git initialization
  -f, --force                     Overwrite target directory if it exists
  --merge                         Merge target directory if it exists
  -c, --clone                     Use git clone when fetching remote preset
  -x, --proxy <proxyUrl>          Use specified proxy when creating project
  -b, --bare                      Scaffold project without beginner instructions
  --skipGetStarted                Skip displaying "Get started" instructions
  -h, --help                      output usage information

还有很多,比如:

  • 命令行交互
  • 日志打印
  • 命令行文字变色
  • 网络通信:HTTP/WebSocket
  • 文件处理

既然需要有这么多功能,业界肯定有成熟的第三方库来解决这些问题,在后面的文章中将会一一实现。

转载自:https://juejin.cn/post/7146828015383609375
评论
请登录