厭煩了Ctrl+CV ?試試用node自動生成重複代碼文件

前言

相信在我們日常遇到的項目中,無論是在前端網站還是後臺管理系統中都會有功能類似的頁面。我們在開發這些功能類似的頁面的時候,爲了提高效率,一般都會運用我們的CV大法。但是當我們CV久了之後,會不會覺得這樣的開發方式有些許枯燥?我們能不能通過代碼來生成代碼,進一步提高我們的效率呢?下面我們就來通過一個例子來探索一下怎麼通過node來生成我們需要的前端代碼。

實例

假設我們正在做一個後臺管理系統(react),頁面文件目錄結構如下圖:

image

page文件夾下有兩個文件夾:home和network,他們分別代表了不同的模塊。稍微觀察一下,我們不難發現,這兩個模塊下面的文件目錄結構是一樣的,而且部分文件名也是一樣的。有些人面對這種情況,包括最開始開發項目的我,可能會想,直接CV,簡單快捷。但是這一次,咱先不急,我們再看看js文件需裏面的需要的初始代碼:

結構基本一樣,但是模塊和組件的名稱卻不一樣。

在上面的這種情況下,我們是可以對類似的文件夾以及文件進行復制粘貼,但是我們也必須針對不同的模塊和組件進行重命名等操作,頁面文件少還好說,但是當頁面比較多的時候,比如有七八個模塊以及幾十個頁面的時候,我們進行這些無意義的重複操作,會不會比較難受?

所以我們能否想想辦法,儘可能的規避這些操作?

泰倫盧:辦法?當然是把球傳給詹姆斯!

開個玩笑。首先,我們應該再仔細分析一下pages下面的文件,home和network文件夾下面有着相同的文件目錄結構,但是部分文件夾下面的文件名稱以及內容可能不一樣。這有點類似與組件的複用,so我們是否可以利用類似組件複用的思想,編寫一個統一的模板,然後給其傳遞不同的參數,就可以生成不同的組件。

基本思路如下圖:

通過配置參數的形式來配置我們的文件夾名稱、文件名以及文件模板的參數,然後再一鍵生成我們的文件夾、文件和文件的內容。

node API

基本思路確定,但是我們怎麼去自動生成文件夾和文件呢?我相信後端的小夥伴肯定不陌生,而前端的小夥伴平時在業務中對於這方面的知識可能涉及的就比較少了。但是隻要熟悉node,這一切都不是問題了。

這裏我們就可以利用node的fs(文件系統)API來幫助我們做這些事。

創建目錄

在node中創建文件(目錄)夾有兩種方式:

第一種(異步):fs.mkdir(path[, options], callback)

參數

  • path - 文件路徑。
  • options 參數可以是:
    • recursive - 是否以遞歸的方式創建目錄,默認爲 false。
    • mode - 設置目錄權限,默認爲 0777。
  • callback - 回調函數,沒有參數。

基本用法

fs.mkdir('/pages/home', (err) => {
  if (err) throw err;
});

第二種(同步):fs.mkdirSync(path[, options])

基本用法

fs.mkdirSync('/pages/home');

創建文件

創建文件也有兩種方式:

第一種(異步):fs.writeFile(file, data[, options], callback)

參數

  • file - 文件名或文件描述符。
  • data - 要寫入文件的數據,可以是 String(字符串) 或 Buffer(緩衝) 對象。
  • options - 該參數是一個對象,包含 {encoding, mode, flag}。默認編碼爲 utf8, 模式爲 0666 , flag 爲 ‘w’
  • callback - 回調函數,回調函數只包含錯誤信息參數(err),在寫入失敗時返回。

基本用法

fs.writeFile('文件.txt', '你好~', (err) => {
  if (err) throw err;
  console.log('文件已被保存');
});

第二種(同步):fs.writeFileSync(file, data[, options])

基本用法

fs.writeFileSync('文件.txt', '你好~');

生成目錄和文件

基本的知識我們已經有所瞭解,接下來就可進行代碼的編寫了。當然電腦上需要有node環境,關於node環境一般來說大家都應該配置的有,如果實在沒有網上搜一下就OK了~

建立項目文件

首先搭建好我們的項目:

主要關注紅框裏面的文件夾和文件

  • index.js爲我們的主程序,文件夾(目錄)和文件的生成的程序邏輯都在裏面,也是最終運行的文件
  • pages裏面爲我們生成的文件夾(目錄)和文件
  • template裏面有兩個文件
    • data.js爲我們的配置文件,包含了文件夾(目錄)和文件名稱以及文件模板的參數等配置
    • template.js爲我們的各種文件的模板

這裏說一下,因爲我們這裏是假設是在react的項目下,所以其它的文件基本上是與react相關的。紅框裏面的代碼邏輯與react不耦合,其它框架下也同樣適用。

生成文件夾(目錄)

回到開始的實例,我們需要在pages文件夾下生成下圖格式種的文件夾和文件:

這裏需要注意的是,無論是fs.mkdir()還是fs.mkdirSync(),他們都是已有的文件夾上進行創建的,例如我們要在pages下創建list文件夾,我們不能直接如下所寫:

index.js

const fs = require("fs");
fs.mkdirSync('./page/home/list'); //報錯

因爲這裏的home文件夾是不存在的,所以list文件夾也不會創建成功。正確的應該這樣寫:

const fs = require("fs");
fs.mkdirSync('./page/home'); 
fs.mkdirSync('./page/home/list');

當然我們不可能直接就這樣來寫,我們可以利用遞歸的方式來創建目錄:

index.js

const fs = require("fs");
const path = require("path");

function mkdirsSync(dirname) {
    if (fs.existsSync(dirname)) { // 這裏是檢測文件目錄是否已經存在
        return true;
    } else {
        if (mkdirsSync(path.dirname(dirname))) {
            fs.mkdirSync(dirname);
            return console.log(`創建目錄成功-${dirname}`);
        }
    }   
}
mkdirsSync('./page/home/list');

接下來是配置文件:

data.js

exports.data = [
    {
        folder:'home',
    },
    {
        folder:'home/list',
    },
    {
        folder:'home/images'
    },
    {
        folder:'home/form',
    },
    {
        folder:'network',
    },
    {
        folder:'network/list',
    },
    {
        folder:'network/images'
    },
    {
        folder:'network/form',
    }
]

引入配置文件,並進行遍歷生成文件:

index.js

const fs = require("fs");
const path = require("path");
//引入配置文件
const profileData = require("./template/data");
// 遞歸創建目錄 同步方法
function mkdirsSync(dirname) {
    if (fs.existsSync(dirname)) {
        return true;
    } else {
        if (mkdirsSync(path.dirname(dirname))) {
            fs.mkdirSync(dirname);
            return console.log(`創建目錄成功-${dirname}`);
        }
    }   
}
//遍歷配置文件並調用創建目錄方法
profileData.data.forEach((item) => {
    if(item.folder){
        mkdirsSync(`./pages/${item.folder}`)
    }
})

生成文件

我們把目錄生成了,生成文件時就主要關注於文件名和文件內容就行了。首先我們要定義好文件的模板,這裏主要要用到模板字符串(``)。因爲其中的一些文件內容種的 class的名稱不一樣, 所以在定義模板的時候, 可以爲這類模板定義一個參數, 如下所示的className :

template.js

exports.page = function (className) {
    return `
import * as React from 'react';

export class ${className} extends React.Component{
    constructor(props){
        super(props);

        this.state = {}
    }

    componentDidMount(){

    }

    render() {
        return (
            <div></div>
        )
    }
}
    ` 
}

exports.api = `const API = "localhost://8080/my-api";`

exports.route = `
import * as React from 'react';

export const route = [];
`

模板定義好後, 繼續在配置文件data.js添加相應的阿配置項,如下所示的fileclassName:

data.js

exports.data = [
    {
        folder:'home',
        file:'api.js'
    },
    {
        folder:'home',
        file:'route.js'
    },
    {
        folder:'home/list',
        file:'home.js',
        className:'Home'
    },
    {
        folder:'home/images'
    },
    {
        folder:'home/form',
        file:'modal.js',
        className:'homeModal'
    },
    {
        folder:'network',
        file:'api.js',
    },
    {
        folder:'network',
        file:'route.js'
    },
    {
        folder:'network/list',
        file:'network.js',
        className:'Network'
    },
    {
        folder:'network/images'
    },
    {
        folder:'network/form',
        file:'modal.js',
        className:'networkModal'
    }
]

最後進行的就是文件生成代碼的編寫:

index.js

const fs = require("fs");
const path = require("path");
//引入配置文件
const profileData = require("./template/data")
//引入文件模板
let template = require("./template/template");
let page = template.page;
let api = template.api;
let route = template.route;


//遍歷創建文件
profileData.data.forEach((item) => {
    if(item.file){
        //創建API文件
        if(item.file.indexOf("api") != -1){
            fs.writeFile(`./pages/${item.folder}/${item.file}`, api, function(err){
                if(err){
                    return console.log('創建失敗', err);
                }
                console.log(`創建文件成功!-${item.file}`);
            })
        }
        
        //創建route文件
        if (item.file.indexOf("route") != -1){
            fs.writeFile(`./pages/${item.folder}/${item.file}`, route, function(err){
                if(err){
                    return console.log('創建失敗', err);
                }
                console.log(`創建文件成功!-${item.file}`);
            })
        }

        //創建主體頁面
        if (item.className){
            fs.writeFile(`./pages/${item.folder}/${item.file}`, page(item.className), function(err){
                if(err){
                    return console.log('創建失敗', err);
                }
                console.log(`創建文件成功!-${item.file}`);
            })
        } 
    }
})

最後, 我們可以直接運行index.js:

我們可以看見控制檯打印出來的信息是是我們創建成功了文件夾(目錄)和文件, 最後在看看pages文件夾下面的目錄與文件:

我們可以把的到的目錄和文件與開始實例中的文件相對比, 發現我們已經成功生成了想要得到的目錄和文件了~

大功告成~

完整的代碼和例子我已經放在了我的GitHub上面了,小夥伴們可以根據自己的實際需求來進行修改,提高自己的開發效率。

參考

https://www.runoob.com/nodejs/nodejs-fs.html

http://nodejs.cn/api/fs.html

最後

上述通過文件配置和模板調用的方式,自動生成了重複的代碼文件。這種方式在一定程度上可以減少我們複製粘貼的重複勞動,提高我們的工作效率。這種方式也是我在開發中的一種嘗試,其中還有很多不足之處。如果有小夥伴在工作中也有過類似提高開發效率的嘗試,歡迎和大家一起分享~

文中若有錯誤的地方,也歡迎提出來~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章