🖇️

Nuxt2 で自動インポートしたコンポーネントのファイルにジャンプできるようにする

2023/09/02に公開

解決したかったこと

Nuxt2 + VSCode + Vetur という開発環境ででコンポーネントの自動インポートを利用している場合、コンポーネントファイルへのジャンプが機能しません。
これは、Vetur が Nuxt の自動インポートの機能で生成されるコンポーネントの参照を認識していないためです。

解決方法

アイデア

  • Vetur の設定ファイルにコンポーネント名とパスを記述する事で、補完やジャンプが効くようになります。
  • 一方で Nuxt は内部的に自動インポートの定義ファイルを生成しています。

この2つを利用する事で、自動インポートしたコンポーネントの定義ファイルへのジャンプが可能になると考えました。

実装の概要

Nuxt モジュールを利用して、.nuxt/components/index.js の変更を監視し、変更があれば自動で Vetur の設定ファイルを更新する仕組みを導入します。

modules/veturWatcher.js を作成する

import fs from 'fs';
import path from 'path';

// Veturの設定内容を生成する関数
function generateVeturComponents(rootDir) {
  const filePath = path.resolve(rootDir, '.nuxt/components/index.js');
  const outputFilePath = path.resolve(rootDir, 'veturComponents.js');

  // ファイルが存在しない場合は何もしない
  if (!fs.existsSync(filePath)) return;

  const componentsData = fs.readFileSync(filePath, 'utf-8')
    .match(/export { default as .+ from '.+\/.+'/g)
    .map(line => {
      const matches = line.match(/export { default as (.+) } from '..\/..\/(.+)'/);
      return `  {
    name: '${matches[1]}',
    path: './${matches[2]}',
  },`;
    })
    .join('\n');

  const outputData = `module.exports.components = [\n${componentsData}\n];`;
  fs.writeFileSync(outputFilePath, outputData);
}

export default function veturWatcherModule() {
  // 開発モードのみ動作させる
  if (this.options.dev) {
    // 初期起動時にも設定ファイルを生成する
    generateVeturComponents(this.options.rootDir);

    this.nuxt.hook('build:done', () => {
      // `.nuxt/components/index.js`の変更を監視する
      const filePath = path.resolve(this.options.rootDir, '.nuxt/components/index.js');
      fs.watch(filePath, (eventType) => {
        if (eventType === 'change') {
          generateVeturComponents(this.options.rootDir);
        }
      });
    });
  }
}

nuxt.config.js を修正する

export default {
  // ...
  modules: [
    // ...
    '~/modules/veturWatcher'
  ]
}

開発サーバを起動する

npm run dev

などで Nuxt の開発サーバを起動してください。

生成された veturComponents.js のサンプル

Nuxt が起動すると下記のようなファイルが自動生成されます。

module.exports.components = [
  {
    name: 'AtomsAlert',
    path: './components/Atoms/Alert/index.vue',
  },
  {
    name: 'AtomsAutocomplete',
    path: './components/Atoms/Autocomplete/index.vue',
  },
  // ... 他のコンポーネントの定義も同様に続く
]

vetur.config.js で自動生成された定義ファイルを読み込む

const { components } = require('./veturComponents.js');

/** @type {import('vls').VeturConfig} */
module.exports = {
  projects: [
    {
      root: './',
      globalComponents: components,
    },
  ],
};

veturComponents.js はコンポーネントを作成、移動、名前変更する度に更新されるので、.gitignore することをおすすめします。

以上で自動インポートしたコンポーネントファイルへのジャンプができるようになりました!

設定変更時の Vetur 再起動

コンポーネント名を変更したり、新しいコンポーネントを追加した場合は、Vetur を再起動する必要があります。

  • VSCode で ctrl + shift + P
  • Vetur Resturt VLS (Vue Language Server) を選択

さいごに

今回紹介した方法で Nuxt2 の開発をより快適にできるようになりました。(そもそもはやく Nuxt3 に移行しろよ、という声が聞こえてきますが。)

ちなみに、この解決方法は、vetur.config.js を自動生成するというアイデアを ChatGPT と壁打ちを繰り返すことで導き出したものです。

記事中のコードは ChatGPT が作成したもので、ほとんど自分で書かずに実装しました。
また、この記事も ChatGPT に指示を出して作成したものを手直ししたものです。

非常に面白い開発体験だったので、その会話のリンクを貼っておきます。興味のある方はぜひ見てみてください。

https://chat.openai.com/share/9c017a0a-fea8-408c-8c45-bd6a9739580f

よりそうテックブログ

Discussion