从零开始一个前端脚手架(一)

1,088 阅读3分钟

背景

脚手架在前端工程化领域的重要性不言而喻,每个公司(或团队)都会根据自己的业务特性维护适合自己的脚手架。具体来说其重要性体现在以下几个方面:

  • 统一开发流程(项目初始化,启动,打包,部署都可以收拢在脚手架内部完成,业务人员只用关注业务即可);
  • 与其他基建能力更好的配合,比如代码检测,mock等。都可以在脚手架层面对接;

既然如此,那作为一个前端人员,得理解脚手架的工作原理以及其基本实现吧。接下来我们一步一步从零开始完成一个简单的脚手架。

项目搭建

初始化项目

mkdir simple-cli
cd simple-cli
mkdir cli    // 存放cli源码的目录
mkdir demo   // 存放demo的目录

进入到cli目录(后续操作默认都在cli目录下)

平平无奇,直接执行npm init。一顿回车就能得到一个项目。但是只有一个package.json文件。

同一层级新建index.js

#!/usr/bin/env node
// 上边这一行代码很重要,指定开发环境为 node
console.log('---index.js-----')

全局链接配置

package.json文件增加配置:

{
  "bin": {
    "simple-cli": "index.js"
  }
}

bin的配置很重要,用来指明对应可执行文件的位置。 未来用户通过npm全局安装我们的脚手架之后,就可以执行simple-cli指令了。 更多关于package.json配置的解读在这里

但是这个包还在开发阶段,当然不可能安装了。此时可以借助另一个指令npm link。控制台进入当前目录下执行:

npm link

此时npm会将bin下的指令链接到全局(未来可以通过npm unlink断开)。

此时在控制台执行:

simple-cli    // 输出 ---index.js-----

babel配置

脚手架的执行环境是node。而node是遵循CommonJs的。 为了能执行ES6代码,则需要对我们的代码进行转义。继续在package.json中增加如下配置:

  "scripts": {
    "dev": "npx babel src --watch --out-dir lib"
  }

这个配置的含义是:babel转义src目录下的文件,并输出到lib目录下, --watch的含义是监听src目录,当该目录下有代码改动时,就会重新编译一次。

配置 .babelrc, 新建文件cli/.babelrc:

{
  "presets": [
    "@babel/preset-env"
  ]
}

控制台执行:

npm install @babel/cli --save-dev
npm install @babel/core --save-dev
npm install @babel/preset-env --save-dev
npm run dev

新建文件src/index.js,写入代码:

console.log('src/index.js')

此时会自动新建一个文件lib/index.js,其内容就是src/index.js转义后的代码。

修改cli/index.js文件代码为:

#!/usr/bin/env node
// 上边这一行代码很重要,指定开发环境为 node
require('./lib/index')

此时控制台输入

simple-cli    // 输出'src/index.js'

到这里得到如下目录:

.
├── cli
│   ├── index.js
│   ├── lib
│   │   └── index.js
│   ├── package.json
│   ├── .babelrc
│   └── src
│       └── index.js
└── demo

我们的项目基础配置已经完成了。后续在src目录下开发具体功能。

定义基础指令

对于一个脚手架工具,应该具有以下基础指令:

simple-cli start  
simple-cli build
simple-cli publish

这里借助commander来实现其定义。 首先npm install commander --save-dev。修改src/index.js文件:


import { program } from 'commander'
const pkg = require('../package.json')

// 定义 -v/ --version 指令 
program.version(`当前版本: ${pkg.version}`, '-v, --version', 'get current version')

// 自定义指令 start
program
    .command('start')
    .description('start a program')
    .action(() => {
        // todo
        console.log('command start ')
    })

// 自定义指令 build
program
    .command('build')
    .description('build program')
    .action(() => {
        // todo
        console.log('command build')
    })

// 自定义指令 publish
program
    .command('publish')
    .description('publish program')
    .action(() => {
        // todo
        console.log('command publish')
    })

program.parse(process.argv)

此时控制台执行simple-cli help将得到如下输出:

Options:
  -v, --version   get current version
  -h, --help      display help for command

Commands:
  start           start a program
  build           build program
  publish         publish program
  help [command]  display help for command

这里只做了其定义,每个指令的具体实现将在后面陆续实现。

未完待续

源码地址
从零开始一个前端脚手架(二)
从零开始一个前端脚手架(三)
从零开始一个前端脚手架(四)

参考文章