0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue3でrouterのコンフリクトを防ぐ

Posted at

概要

Vue3router/index.ts が Pull Request / Marge Request のたびに毎回コンフリクトして困っていたので、views 以下のディレクトリ構成とファイル名から自動で router/index.ts が入るようにしてみました!

背景

Vue3 とても便利なのですが、vue-clivue-router とともに使っていて、
router/index.ts のコンフリクト解決が面倒に感じています。
Nuxt 3 が使えれば解決なのですがまだ Beta 版で IntelliJ/WebStorm の Vue プラグインも対応していないのでちょっと使いづらいです。
そこで簡単に router/index.tsnpm run するときに生成してしまうのを作ってしまおうというのが今回の取り組みです。

目指すもの

  • router/index.ts の内容は npm run dev, npm run build 時に自動で入り、メンテナンス不要。
  • ついでに、すべてのページにデバッグ用にアクセスできる索引的なコンポーネントも生成する。

実装方法

1. メインとなるプログラムの dynamicRouterGenerator を配備

1-1. src/lib/dynamicRouterGenerator/.gitignore

generated-router.ts
GeneratedIndex.vue

1-2. src/lib/dynamicRouterGenerator/.gitignore

// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require('fs')

let files = []

/**
 * @param dirPath 「/」始まり or ''
 */
const searchFiles = (dirPath) => {
  const allDirents = fs.readdirSync(`${__dirname}/../../views${dirPath}`, { withFileTypes: true })
  for (const dirent of allDirents) {
    if (dirent.isDirectory() && dirent.name !== 'components') {
      searchFiles(`${dirPath}/${dirent.name}`)
    } else if (dirent.isFile() && dirent.name.match(/\.vue$/)) {
      const importPath = `@/views${dirPath}/${dirent.name}`
      const accessPath = `${dirPath}/${dirent.name}`
        .replace(/\.vue$/, '')
        .replace(/\/index$/, '')
        || '/'
      const moduleName = `${dirPath}/${dirent.name}`
        .replace(/^\//, '')
        .replace(/\.vue$/, '')
        .replace(/\//g, '__')
        .replace(/-/g, '_')
      const title = `${dirPath}/${dirent.name}`
        .replace(/^\//, '')
        .replace(/\.vue$/, '')
        .replace(/-/g, ' ')
        .replace(/\b(\w)/g, (w) => w.toUpperCase())
        .replace(/\//g, '<span style="margin-left: 40px;"></span>')
      files.push({
        accessPath,
        importPath,
        moduleName,
        title,
      })
    }
  }
}

searchFiles('')

files.sort((a, b) => a.accessPath < b.accessPath ? -1 : 0)

fs.writeFileSync(`${__dirname}/generated-router.ts`, `\
import { RouteRecordRaw } from 'vue-router'
${files.map(f => `\
import ${f.moduleName} from '${f.importPath}'
`).join('')}\

export const dynamicRoutes: Array<RouteRecordRaw> = [
${files.map(f => `\
  { path: '${f.accessPath}', component: ${f.moduleName} },
`).join('')}\
]
`)


fs.writeFileSync(`${__dirname}/GeneratedIndex.vue`, `\
<template>
  <ul>
${files.map(f => `\
    <li><router-link to="${f.accessPath}">${f.title}</router-link></li>
`).join('')}\
  </ul>
</template>
`)

2. router 書き換え

2-1. src/router/index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { dynamicRoutes } from '@/lib/dynamicRouterGenerator/generated-router'

const routes: Array<RouteRecordRaw> = [
  ...dynamicRoutes,
]

const index = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default index

3. 索引ページ配置

3-1. src/views/index-for-debug.vue

<template>
  <GeneratedIndex style="font-size: 40px;" />
</template>

<script setup lang="ts">
import GeneratedIndex from '@/lib/dynamicRouterGenerator/GeneratedIndex.vue'
</script>

<style scoped>
li { font-size: 40px; }
</style>

4. package.json

4-1. npm install

npm install --save-dev @types/node

4-2. scripts

  "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "lint": "vue-cli-service lint"
  },

変更後
  "scripts": {
    "dev": "node src/lib/dynamicRouterGenerator && vue-cli-service serve",
    "build": "node src/lib/dynamicRouterGenerator && vue-cli-service build",
    "test:unit": "node src/lib/dynamicRouterGenerator && vue-cli-service test:unit",
    "lint": "node src/lib/dynamicRouterGenerator && vue-cli-service lint"
  },

使い方

通常通り npm run devnpm run build するだけ。
必要なファイルが自動で入ります。
新規ページを生成したときは npm run dev を再起動します。

http://localhost:8080/index-for-debug
にアクセスすることで索引も表示されます。

src/
  views/
    index.vue
    aaa/
      bbb/
        ccc-ddd.vue
        ccc-eee.vue

という構成の場合、下記のような索引ページが生成されます。

image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?