最近空闲下来一直在想怎么才能提高开发效率,减少无用代码的书写呢?思考了一下,无用代码的生成场景有两种:一种是一个全新模块的创建,一种是新组件的创建。
这里先讲一下对于全新模块的创建。
我们项目的全新模块的创建有点复杂,结构是这样的:
- actions中存放每个页面对应的请求方法,和redux的action方法。
- comonents中存放每个页面对应的内容组件。
- containers中存放对每个页面的引入。
- reducers中存放每个页面的action中保存的数据结构。
- router中存放的所有的路由。
所以每次开发一个全新的模块时,我必须要创建actions、components、containers、reducers,并在router中注入路由。而在这些文件中会用到关于actions的使用,所以得保证关于actions的引用正确。每次开发新模块都需要走一遍这样的流程,重要但是重复度很高,所以我觉得这部分是能够处理成模版,一键生成的。
关于这个模版的开发思路如下:
-
模块的名称可以由用户灵活输入。比如用户输入test。
-
根据用户输入的模块名称,创建containers/test.js文件,并注入内容。
-
根据用户输入的模块名称,在components下创建test目录,并在test下创建index.js和index.cssmodule文件,并注入对应的内容。
-
根据用户输入的模块名称,创建reducers/test/index.js文件,并注入内容。
-
根据用户输入的模块名称,创建actions/test/index.js文件,并注入内容。
现在,思路有了,我们可以开始开发了~~。
一、获取用户输入
首先我们创建一个create.js文件。关于用户的输入,我们可以使用readline包来实现。
const readline = require('readline');
const readlineObj = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function init(){
readlineObj.question('要创建的模块名字是什么呢?', name =>{
....
})
}
init();
这里readlineObj.question方法的第一个参数,是我们在用户输入时给的提示,第二个参数是一个回调函数,函数的参数name就是用户输入。
获取到用户的输入之后,我们就可以根据用户输入创建新的模块了,但是在创建之前,我们要先去看看有没有同名的模块已经被创建。
二、查找是否有同名文件
查找是否有同名文件,我们可以在containers中查看。查看的函数这样写:
const fs = require("fs");
const chalk = require('chalk');
const isHasFile = (name, callback) => {
const dir = path.resolve('./src/containers');
fs.readdir(dir, (err, dirName) => {
const hasFile = dirName.find(val => val === `${name}.js`);
if(hasFile){
console.log(chalk.red('该文件名已经存在!')); readlineObj.close();
}
callback();
});
};
isisHasFile函数的第一个参数name是我们输入的模块名称,callback是发现该模块名没有时,要执行的回调函数。
我们通过fs的readdir方法读取src/containers目录中的文件。readdir的第一个参数dir是要读取的目录,第二个是回调函数。回调函数的第一个是error信息,第二个是获取到的文件名。
这里使用find方法查找container下是否存在test.js。如果存在,使用chalk.red向用户输出一个红色的'该文件名已经存在!'的提示,并使用readlineObj.close()关闭交互。 如果不存在则调用callback,执行后续操作。
三、router中注入路由
router/index.js中的内容是这样的:
export default [
{path: '/aaa', component: 'aaa'}
]
这种文件内容的注入,我们只能通过将文件原本内容和诸如内容进行拼接。代码如下:
// router中添加路由const
addAddRouter = (name) => {
const filePath = path.resolve('./src/route/index.js');
fs.readFile(filePath, 'utf-8', (err, data) => {
const dataArr = data.split('];');
const content = `
${ dataArr[0] },
{path: '/${name}',component: '${name}'}}
];
`;
fs.writeFileSync(filePath, content);
......
});
};
addAddRouter即为添加路由的函数,这里的name参数为用户输入的模块名称。
使用fs的readFile方法读取route/index.js中的内容,以utf-8编码。
fs.readFile方法最后一个参数是一个回调函数,该函数的第一个参数,是一个err信息,第二个参数是读取到的内容,这里使用split方式对内容进行拆分,之后与要注入的内容拼接,最后使用fs.writeFileSync方法写入就行。
四、创建containers/test.js
创建containers/test.js的代码如下:
// 创建containersconst
createContainer = name => {
const containerUrl = `./src/containers/${name}.js`;
const containerContent = `test container`;
fs.appendFile(`${containerUrl}`, containerContent, err => {
if (err) throw err;
console.log(chalk.green(`${containerUrl}文件创建成功!`));
});
};
这里通过fs的appendFile方法向containers目录下添加文件,这里的name为要添加的文件名。
appendFile函数的第一个参数是要添加的文件的路径,第二个参数是添加文件的内容,第三个参数是回调函数,该回调函数只有一个参数,就是error信息。
回调中,如果有error,则使用throw error抛出错误,会自动中断交互。如果没有,则使用chalk.green向用户输入一行绿色的'./src/containers/test.js文件创建成功!'。
五、创建components/test文件
components/test目录下要创建两个文件:index.js、index.cssmodules.styl。代码如下:
// 创建components
const createComponents = (name, extraName) => {
const dirUrl = `./src/components/${name}`;
const dirName = path.resolve(dirUrl);
// 创建目录
fs.mkdirSync(dirName);
createIndexJs(name, dirUrl);
createStyleFile(name, dirUrl);
};
// 创建style文件
const createStyleFile = (name, dirUrl) => {
const styleContent = `.${name}-page background #fff `;
fs.appendFile(`${dirUrl}/index.cssmodule.styl`, styleContent, err => {
if (err) throw err;
console.log(chalk.green(`${dirUrl}/index.cssmodule.styl文件创建成功!`));
});
};
// 创建js
const createIndexJs = (name, dirUrl) => {
const jsContent = 'test index.js' ;
fs.appendFile(`${dirUrl}/index.js`, jsContent, err => {
if (err) throw err;
console.log(chalk.green(`${dirUrl}/index.js文件创建成功!`));
});
};
这里有3个函数:
- createComponents用于给components给components中创建目录,比如test目录。
- createStyleFile用于给新创建的test目录下,添加index.cssmodule.styl文件。
- createIndexJs用于给新创建的test目录下,添加index.js文件。
其中:
-
fs.mkdirSync是创建目录用的函数,参数是要创建的目录的路径。
-
fs.appendFile是创建文件用。
之后创建reducers和actions的步骤和components的一致,就不再重复。
写完所有的代码之后,就可以运行创建一个模块试试了~~
不过现在每次创建新模块时,都要node create.js,有点麻烦,我们可以在package.json的scripts中添加:
"create": "node ./create.js"
使用npm run create就可以方便的启动了~~~
注:这里使用yarn create启动时,发现找不到create模块,所以npm run create和yarn create还是有区别的。