This website requires JavaScript.

记一次偷懒实践

2018.05.27 12:36字数 3158阅读 513喜欢 15评论 4

事出有因

通常在 vue-cli 脚手架 src 目录下,有一个 api 文件夹,用来存放被抽离出的 API 请求,如下图所示:

其中 module 文件夹下存放各模块抽离的 API,axios.ts 文件创建 axios 的一个实例,并添加一些公共配置(如:baseURL, timeout,拦截器等),index.ts 即是向外暴露各种 API 方法。

module 下的每个文件内容格式基本都一样:

get 请求传参数有点不同:

export function getSome (
  params?: any
): Promise<Ajax.AjaxResponse> {
  return ax.get('/some', { params })
            .then(res => res.data)
            .catch(error => console.error(error))
}

当项目越来越大,module 下的文件越来越多时(但文件内容基本一样),本着能少写代码就少写代码的我,冒出一个想法,是否能通过一个 json 文件,来生成所需要的文件?如下图:

定义一个如上 json 文件,执行一段脚本,它就可以生成包含下图代码文件:

那就开始吧

我们的目的很简单,读取一个 json 文件,把 json 文件里对应字段的值,写入到一个 .ts 文件里。

这里,我们用到 node 的 fs 模块,用来读取与写入文件。

// index.js
const fs = require('fs')

// 读取 json 文件
const data = fs.readFileSync(`user.json`)

// parse 导入文件
const content = JSON.parse(data)

定义每个函数的 template:

const template = item => {
  return `// ${item.des}\n` +
          `export function ${item.name} (params?: any)` +
          `: Promise<Ajax.AjaxResponse> {\n` +
          `  return ax.${item.method}('${item.url}', ` +
          `${item.method === 'get' ? '{ params }' : 'params'})\n` +
          `           .then(res => res.data)\n` +
          `           .catch(error => console.error)\n` +
          `}\n\n`
}

接着遍历 content

let result = "import ax from '../axios'\n\n"

content.forEach(item => {
  result += template(item)
})

// 生成文件
fs.writeFileSync(`user.ts`, result)

执行命令 node index.js,发现这次尝试是成功的:

实际中,module 应该是很多个,而且输出文件的名字,应该是与对应 json 文件的名字是相同的。就像下图一样:

我们来改动一下前面所写的代码:

const fs = require('fs')
const path = require('path')

// 入口文件夹
const enPath = path.resolve(__dirname, '../src/ajax')

// 出口文件夹
const outPath = path.resolve(__dirname, '../src/api/module')

// 目录不存在时,创建
if (!fs.existsSync(outPath)) {
  fs.mkdirSync(outPath)
}

const template = item => {
  return `// ${item.des}\n` +
          `export function ${item.name} (params?: any)` +
          `: Promise<Ajax.AjaxResponse> {\n` +
          `  return ax.${item.method}('${item.url}', ` +
          `${item.method === 'get' ? '{ params }' : 'params'})\n` +
          `           .then(res => res.data)\n` +
          `           .catch(error => console.error)\n` +
          `}\n\n`
}


// 读取文件夹
const files = fs.readdirSync(enPath)

// 读取单个文件,生成所需文件
files.forEach(file => {
  const data = fs.readFileSync(`${enPath}/${file}`)

  const fileName = file.split('.')[0]

  let result = ''

  if (data.length) {
    result = "import ax from '../axios'\n\n"
    const content = JSON.parse(data)

    content.forEach(item => {
      result += template(item)
    })
  }

  fs.writeFileSync(`${outPath}/${fileName}.ts`, result)

  console.log(`写入文件成功:${outPath}/${fileName}.ts`)
})

执行命令 node index.js,自此,就基本达成了最初的目的。

实际过程中,可能并没什么卵用,比如说某些请求里,需要加不同的配置( baseURL, header 等),还有可能文件夹 ajax 下还细分了文件夹等。不过,折腾一下,总能出来。