coderz blog

邂逅CLI开发-woker开发过程

2021-05-24

邂逅CLI开发-woker开发过程

在前端开发过程中,我们会使用各种各样的脚手架 vue-cli、create-react-app等工具。

这些工具是怎么开发出来的?当我们输入一个命令其内部帮我们处理了哪些事情?

最近写了一个叫 woker 的小工具,记录下其开发过程。文档会分成两部分

CLI 脚手架开发过程;

woker 使用介绍;

Vue 项目模板:https://github.com/coderx-waper/z-vue-template

脚手架地址:https://github.com/coderx-waper/woker

如对你有帮助,欢迎一键三联~ 点个 star 还是要 求一下的😬


开发过程

一、项目开始

  • 创建空文件夹 作为我们项目的存放位置

    1
    例如:cd woker
  • 创建 package.json文件

    在终端执行 npm init -y ,即可生成 package.json 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    {
    "name": "woker",
    "version": "1.0.1",
    "description": "vue-cli",
    "main": "index.js",
    "bin": {
    "woker": "index.js"
    },
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": ["vue-cli","coderz","vue","woker"],
    "author": "coderz",
    "license": "ISC",
    "homepage": "https://github.com/coderx-waper/woker.git",
    "repository": {
    "type": "git",
    "url": "https://github.com/coderx-waper/woker.git"
    },
    "dependencies": {
    "commander": "^7.2.0",
    "download-git-repo": "^3.0.2",
    "ejs": "^3.1.6",
    "inquirer": "^8.0.0"
    }
    }

  • 配置文件夹

    最终 woker 项目中文件目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ├── lib
    | ├── config // 配置文件
    │ │ └── repo_config.js
    | ├── core // 核心文件
    │ │ ├── react // 待增加...
    │ │ ├── vue
    │ │ ├── └── action.js
    │ │ ├── └── create.js
    │ │ ├── └── help.js
    | ├── templates // ejs 模板文件
    │ │ └── vue-component.ejs
    │ │ └── vue-router.ejs
    │ │ └── vue-store.ejs
    │ │ └── vue-types.ejs
    | ├── untils //
    │ │ └── terminal.js
    │ │ └── utils.js
    ├── index.js
    ├── package-lock.json
    ├── package.json
    ├── README.md

二、创建命令

必须注意一点 ,这段代码必须放在 index.js 文件的最上面

1
#!/usr/bin/env node

修改 package.json 文件

1
2
3
"bin": {
"woker": "index.js"
},

执行 npm link woker 才会生效

创建命令需要借助 commander 库来实现,用法可自行参考官网 commander

三、创建项目指令

1
2
3
program.command('create <project> [others...]')
.description('clone repo into a folder')
.action(createVueProjectAction)

createVueProjectAction 是封装在 action.js 文件中的一个动作,在action中的创建过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// create a vue template action
const createVueProjectAction = async (project, others) => {

console.log(project, others)

// 1 clone project
console.log('coderz helps you clone a vue template, this requires a budget...')

await download(vuerepo, project, {
clone: true
});

// 2 npm install
const commandTerminal = process.platform === 'win32' ? 'npm.cmd' : 'npm'
await commandSpawn(commandTerminal, ['install'], {
cwd: `./${project}`
})
// 3 run serve
commandSpawn(commandTerminal, ['run', 'serve'], {
cwd: `./${project}`
})

// 4 z-vue-template install it --open

}

这里涉及几个几个问题:

  • download :可以进行 clone 的一个第三方库 download-git-repo 可自行在 npm 中查看其用法
  • commandSpawn:执行终端命令的函数 可在 terminal.js 文件中找到其实现方法
  • vuerepo:vue-template 模板地址,封装在 lib/config/repo-config.js 中,后续考虑可自定义模板地址,目前使用自己写的 z-vue-template

四、添加组件指令

添加指令

1
2
3
4
5
program.command('addcpn <name>')
.description('add vue component, eg: addcpn NavBar [-d src/components]')
.action((name) => {
addComponentAction(name, program.dest || 'src/components')
})
  • addComponentAction 逻辑
1
2
3
4
5
6
7
8
9
10
11
12
// create component action
const addComponentAction = async (name, dest) => {
// needs ejs template -> .vue
const result = await compile('vue-component.ejs', {
name,
lowerName: name.toLowerCase()
})
// write to source folder
const targetPath = path.resolve(dest || 'src/components', `${name}.vue`)
writeFile(targetPath, result)

}

这里面存在一个问题即创建当文件夹不存的时,创建会出错,故而在调用 writeFile 中进行了文件夹的递归调用根据targetPath创建对应文件夹,其中的实现逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
const mkdirSync = (dirname) => {
if (fs.existsSync(dirname)) {
return true
} else {
// 不存在,判断上一级文件夹是否存在?
if (mkdirSync(path.dirname(dirname))) {
// 存在父文件,就直接新建该文件
fs.mkdirSync(dirname)
return true
}
}
}

添加组件需要去了解 ejs用法,项目中已经根据需要提前写好了vue-component.ejs模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
<div class="<%= data.lowerName %>">
<h2>{{ message }}</h2>
</div>
</template>

<script>
export default {
name: "<%= data.name %>",
components: {
},
mixins: [],
props: {
},
data: function() {
return {
message: "Hello <%= data.name %>"
}
},
created: function() {
},
mounted: function() {
},
computed: {
},
methods: {
}
}
</script>

<style scoped>
.<%= data.lowerName %> {

}
</style>

模板ejs 编译核心:需要使用到 ejs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**编译文件 */
const compile = (template, data) => {
// 获取 路径
const temp = `../templates/${template}`
const temPath = path.resolve(__dirname, temp)
return new Promise((resolve, reject) => {
ejs.renderFile(temPath, {
data
}, {}, (err, result) => {
if (err) {
reject(err)
}
resolve(result)
})
})
}

五 、添加其他指令

添加 page指令和 store 指令同上,逻辑可以查看 woker 中的实现。这里不再累述。

六、发布到npm

在发布之前,所有指令必须测试无问题

修改package.json:添加 homepage、repository

1
2
3
4
5
"homepage": "https://github.com/coderx-waper/woker.git", //此处填写你的 homepage
"repository": {
"type": "git",
"url": "https://github.com/coderx-waper/woker.git" //此处填写你的 repository
},

在命令行中登录:

1
npm login //根据提示输入信息即可

发布到npm registry中

1
npm publish

woker使用介绍

  • woker 是什么?

    Front-end scaffolding, currently supports vue

  • 后续打算?

    支持 支持 react template

如何安装?

1
npm install -g woker

创建项目

目前woker仅支持vue,cli已经帮你配置了

  • 常用的目录结构
  • axios
  • vue-router
  • vuex
  • vue.config.js
    创建项目
1
2
woker create <project>[^project]: 你的项目名称 例如: woker create demo

自动拉取z-vue-template项目模板,自动打开 http://localhost:8080/、启动项目

创建组件

1
woker addcpn <component>[^component]: 你的组件名称 例如: woker addcpn HelloWold

创建页面

创建页面过程中会自动配置路由

1
woker addpage <profile>[^profile]: 你的页面名称 例如: woker addpage profile

Tags: NodeJs
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章