自动化文件创建-plop使用介绍
介绍
plop是一个用于自动化创建、修改文件的小工具。在维护代码的过程中,我们常常遇到需要在项目中四处寻求最佳实践的文件,比如说创建一个页面时,需要编写页面、样式、README文档、在路由配置中添加对应的路由信息等,如果对项目不熟悉的情况下,可能需要花时间查看其他页面并拷贝所需部分的代码来创建新页面。有了plop后,就可以通过几个简单的问答,直接将文件创建好,节约开发时间。
plop基于inquirer 和handlebar两个库。利用inquirer实现收集用户输入数据,借助handlebar生成指定模板的文本。根据plopfile中的配置,最终进行文件的创建或修改。
安装
- 添加plop库
yarn add --dev plop
- 修改package.json,添加script:
"plop": "plop", - 在根目录下创建
plopfile.js文件
module.exports = function (plop) {
// create your generators here
plop.setGenerator('basics', {
description: 'this is a skeleton plopfile',
prompts: [], // array of inquirer prompts
actions: [] // array of actions
});
};
- 执行
yarn plop指令
使用
plop通过plop.setGenerator的api函数创建整个自动化流程。description是一个可选字符串,描述流程的作用;prompts是一系列的问题,用于收集生成模板所需的数据。actions则是一系列的行为,包括新增文件、修改文件或是其他自定义行为。
下面通过几个例子来了解如何使用plop。
1. 基础使用
plop.setGenerator('basics', {
description: '基础使用',
prompts: [
{
type: 'input',
name: 'filePath',
message: '请输入页面路径。',
},
],
actions: [
{
type: 'add',
path: '{{filePath}}',
},
],
});
actions的path字段接受handlebar式的模板字符串,即可使用双括号访问从prompts获取到的数据。
2. 对用户输入添加校验
plop.setGenerator('page', {
description: '创建多语言页面',
prompts: [
{
type: 'input',
name: 'filePath',
message: '请输入页面路径。例如 `kebab-case/kebab-case`',
validate(input) {
if (!input) {
return '请输入页面地址';
}
return true;
},
},
],
actions: [
{
type: 'add',
path: '{{filePath}}',
},
],
});
prompts字段是基于Inquirer,可拓展的功能有validate(数据校验)、choices(选项)、default(默认值)等。具体参照Inquirer文档。
3. 通过模板文件进行新增
首先创建模板文件
// config/plop-templates/page.hbs
import React from 'react'
export default function {{name}}() {
return <div></div>;
}
再修改setGenerator函数
plop.setGenerator('basics', {
description: '模板文件',
prompts: [
{
type: 'input',
name: 'name',
message: '请输入名称。',
},
],
actions: [
{
type: 'add',
templateFile: 'config/plop-templates/page.hbs',
path: 'src/page/index.tsx',
},
],
});
在模板文件中使用的是handlebar的语法,双括号除了引用参数外,还有类似vue中的Filter语法的Helper,其中内置的一些逻辑判断、循环等工具方法。具体查看handlebars文档。
- 修改文本
修改文件有两种形式,一种是通过pattern参数,正则匹配并替换文本。另一种是通过transform函数。transform函数会接收整个文件的文本作为参数,再返回修改后的文本替代原文件。
以下是一个添加路由配置的例子。
- 首先在路由原文件加上替换标识。
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
},
...
{
path: "contacts/:contactId",
element: <Contact />,
},
+ // add plop config
]);
- 添加替换模板文件
config/plop-templates/modify.hbs。
{
path: "{{path}}",
element: <{{name}} />,
},
// append plop config
- 再修改setGenerator函数
plop.setGenerator('basics', {
description: '模板文件',
prompts: [
{
type: 'input',
name: 'name',
message: '请输入名称。',
},
{
type: 'input',
name: 'path',
message: '请输入路由。',
},
],
actions: [
{
type: 'modify',
path: 'src/router.js',
pattern: /\/\/ append plop config/,
templateFile: 'config/plop-templates/modify.hbs',
},
],
});
4. 动态actions
actions除了可以为数组外,还可以使用一个返回数组的函数,通过判断用户输入的数据,选择性的执行命令,还可以修改传入模板的数据。
plop.setGenerator('basics', {
description: '动态actions',
prompts: [
{
type: 'confirm',
name: 'isNeedREADME',
message: '是否需要README',
},
],
actions: (data) => {
let list = [
{
type: 'add',
path: 'src/page/index.tsx',
data: {
...data,
othersData: null,
},
},
];
if (data.isNeedREADME) {
list.push({
type: 'add',
path: 'src/page/README.md',
});
}
return list;
},
});
总结
plop是一个简单小巧实用的工具,但官方文档主要以文本描述为主,初次使用时可能会感觉比较枯燥,希望通过本文的几个针对具体场景的例子,可以帮助大家更快上手。
参考链接
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天