Vite+Vue+TypeScript+ChatGPTで半日足らずでGitHub Pagesのサイトを作った話

本投稿は TECOTEC Advent Calendar 2024 の1日目の記事です。

次世代デジタル基盤開発事業部のIです。普段はエンジニアとしてJavaScript/TypeScriptでWebアプリケーションのシステムの開発を行なっています。

今回は、Vite+Vue3+TypeScriptを使って、当方がプライベートで使うサイトを実装した際に、ChatGPTを併用したことで作業が捗ったときの知見を書いていきたいと思います。

開発の背景

当方がアプリを開発したのは、とあるゲームの音ゲーモードのタイトルリストを作ろうとしたことがキッカケとなります。

このゲームは海外製なので、採用されている曲は洋楽がメインです。

その際、タイトルのコピペはできないため、自力で入力することになるわけですが、海外の曲なので、ウムラウト(ä)とかグレイヴ・アクセント(è)とか、IMEで一発で出なさそうな文字が連発します。

そこで、これらの文字をクリップボードにコピーするアプリを作れば、これらの作業が非常に捗るのではと考えたわけです。

まずは完成したアプリの紹介

完成したアプリは以下のものです。

cyross.github.io

アプリの画面

画面左側のカテゴリ(青地のボタン)をクリックすると、画面右側に文字のリストがサブカテゴリ入りで表示されます。

それぞれの文字の右側にあるクリップボードコピーボタン()をクリックすれば、その文字(Unicode)がクリップボードにコピーされるので、あとはエディタなどにペーストできます。

余談ですが、本文で記載されている特殊な文字や記号は、このアプリでコピペしています。

開発の準備

今回の開発では、DB連携する必要性がないくらいのデータ量で、ゴテゴテしたアニメーションやUIである必要もないと思ったため、シンプルな構成の静的サイトでいこうと考えてましたし、GitHubのアカウントは既に持っていたので、GitHub Pagesを使用することを考えました。

フロントエンドの開発は、手練れている Vite + Vue3(Composition API) + TypeScript を使うことにしました。

ただし、GitHub Pagesでのデプロイは初めてで、実装上分からないことが多いため、傍らにChatGPTを携えます。

ChatGPT の使用パターン

import のショートカット

Vite + Vue + TypeScript で、@ を使ったインポートのショートカットをしたかったのですが、やり方を思い出せず、ChatGPTで訊くことにしました。

Vite+Vue+TypeScriptを使ってWebアプリを作っています。 ts-config-paths を使って @ マークを使った import のショートカットをしたいのですが、どこに設定すればよいでしょうか?

すると、以下の回答が返ってきました。

Vite+Vue+TypeScript プロジェクトで @ マークを使ったインポートのショートカットを設定するには、以下の手順で進めます。


1. tsconfig.json にエイリアス設定を追加

tsconfig.json に paths オプションを設定します。

設定例 json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } }

baseUrl:プロジェクトのルートディレクトリを指定します。 paths:@を src ディレクトリに対応させています。


2. vite.config.ts にエイリアスを設定

Vite の設定ファイルにエイリアスを設定します。vite では resolve.alias を使用します。

設定例

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
});
  • path.resolve(__dirname, 'src'):プロジェクトの src フォルダを @ にマッピングします。

3. TypeScript を使っている場合の注意点

tsconfig.json との整合性

  • vite.config.ts のエイリアスと tsconfig.json の paths は同じ設定にしてください。
  • 片方にエイリアスを設定し忘れるとエラーが発生します。

4. 使用例

エイリアス設定後、@ を使ったインポートが可能になります。

// 通常のインポート
import MyComponent from '../components/MyComponent.vue';
// エイリアスを使ったインポート
import MyComponent from '@/components/MyComponent.vue';

補足: パッケージインストール不要

tsconfig-paths は Node.js 環境用ですが、Vite ではその機能をネイティブでサポートしているため、特別なパッケージは不要です。


これで @ を使ったインポートのショートカットが有効になります!

と書かれてあり、早速設定してみたのですが、vite.config.ts でエラーが出ます。 ChatGPTでは「パッケージインストール不要」と書かれていたのですが、ググってみると、実際は @types/node を明示的にインストールする必要があることが分かりました。ウソつかれてしまいました…。

npm install -D @types/node

これで、エラーは消えました。

文字生成コードの生成

続いて、とあるカテゴリの文字を文字列として取得することにします。英語とかならばすぐに実装できるのですが、ルーン文字()とか発音記号(ŋ)とか単位記号()とかの配列を作ろうとすると、骨が折れます。

この時こそ、GhatGPTの出番です。

例えば、発音記号を配列にして返すコードを作りたい時は、

TypeScriptで、すべての発音記号を列挙する配列を実装してください

と質問します。すると、以下の回答が得られます。

以下は、国際音声記号 (IPA, International Phonetic Alphabet) を元に、すべての発音記号を列挙する配列を TypeScript で実装する例です。


実装例

const ipaSymbols: string[] = [
  // 子音
  "p", "b", "t", "d", "k", "g", "ʔ",
  "m", "n", "ŋ",
  "ɸ", "β", "f", "v", "θ", "ð", "s", "z", "ʃ", "ʒ", "ʂ", "ʐ", "ç", "ʝ", "x", "ɣ", "χ", "ʁ", "ħ", "ʕ", "h", "ɦ",
  "ʋ", "ɹ", "ɻ", "j", "ʍ", "w", "ɰ",
  "l", "ɭ", "ʎ", "ʟ",
  // 母音
  "i", "y", "ɨ", "ʉ", "ɯ", "u",
  "ɪ", "ʏ", "ʊ",
  "e", "ø", "ɘ", "ɵ", "ɤ", "o",
  "ə",
  "ɛ", "œ", "ɜ", "ɞ", "ʌ", "ɔ",
  "æ", "ɐ",
  "a", "ɶ", "ɑ", "ɒ",
  // 追加記号(補助記号)
  "ˈ", "ˌ", "ː", "ˑ", "ʼ",
  "̩", "̯", "͡", "͜",
  // 声調記号
  "˥", "˦", "˧", "˨", "˩",
  // その他
  "ʘ", "ǀ", "ǃ", "ǂ", "ǁ"
];
export default ipaSymbols;

各カテゴリの説明

  1. 子音 (Consonants):

    • 声門閉鎖音 (ʔ)、鼻音 (m, n, ŋ)、摩擦音 (f, s, ʃ など)、側音 (l など) を含む。
  2. 母音 (Vowels):

    • 前舌 (i, y)、中央 (ə)、後舌 (u, ɑ) など。
  3. 追加記号 (Diacritics):

    • 長音記号 (ː) や声調記号 (˥ など)。
  4. 声調記号 (Tone Marks):

    • 中国語やタイ語など声調言語に使用。
  5. クリック音 (Clicks):

    • 南アフリカの言語で使用される記号(例: ʘ, ǀ)。

使用例

この配列を利用して発音記号が有効かどうかを判定したり、UIでリスト表示することができます。

例1: 発音記号の存在確認

const isValidSymbol = (symbol: string): boolean => ipaSymbols.includes(symbol);
console.log(isValidSymbol("p"));  // true
console.log(isValidSymbol("x"));  // true
console.log(isValidSymbol("@"));  // false

例2: 表示用途

ipaSymbols.forEach((symbol) => {
  console.log(symbol);
});

注意

  • このリストはIPA表記の主要な記号を網羅していますが、全ての補助記号や特殊ケースを含むわけではありません。
  • 必要に応じて、言語や用途に特化した記号を追加してください。

ここで、配列 ipaSymbols を宣言しているコードをコピーして、アプリのコードにペーストすれば万事OKです。

ただし、必要に応じて 「Unicodeで」 などの付帯条件を追加する必要があります。例えば、

TypeScriptで、すべての通貨単位記号を列挙する配列を実装してください

とだけ書くと、USDJPY といった3文字の略称のリストを作ってしまうので、

TypeScriptで、すべての通貨単位記号をUnicodeで列挙する配列を実装してください

と書くことで、¢ といった、クリティカルな実装コードを生成してもらうようにします。

また、出来上がった一覧を改めて見てみると、例えば通貨単位の場合、イギリスのポンド(£)などが無く、不十分なため、最終的にWikipediaの項目を参考に、手作業で通貨単位を集めることになりましたが、大幅な作業量削減になったのは事実です。

クリップボードへのコピーコンポーネント

肝心のクリップボードへのコピーですが、あまりやったことがありません。というわけで、ChatGPT に聞いてみます。

Vite+Vue3.5+TypeScriptを使って、definePropsで定義した文字列をクリップボードにコピーするボタンを実装したい

以下、ChatGPTの回答。

以下は、Vite+Vue 3.5+TypeScriptで、defineProps で受け取った文字列をクリップボードにコピーするボタンを実装する例です。


実装例

1. コンポーネントコード

<template>
  <div>
    <p>{{ text }}</p>
    <button @click="copyToClipboard">Copy to Clipboard</button>
    <p v-if="copied" class="success-message">Copied to clipboard!</p>
  </div>
</template>

<script lang="ts">
import { defineProps, defineComponent, ref } from 'vue';
export default defineComponent({
  setup() {
    // Props 定義
    const props = defineProps<{
      text: string;
    }>();
    // コピー成功フラグ
    const copied = ref(false);
    // クリップボードにコピーする関数
    const copyToClipboard = async () => {
      try {
        await navigator.clipboard.writeText(props.text);
        copied.value = true;
        // 一定時間後にフラグをリセット
        setTimeout(() => {
          copied.value = false;
        }, 2000);
      } catch (err) {
        console.error("Failed to copy: ", err);
      }
    };
    return {
      copyToClipboard,
      copied,
    };
  },
});
</script>

<style scoped>
button {
  padding: 8px 12px;
  background-color: #007BFF;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button:hover {
  background-color: #0056B3;
}
.success-message {
  color: green;
  margin-top: 10px;
}
</style>

2. 使用例

このコンポーネントを使用する場合、text プロップスにコピーしたい文字列を渡します。

<template>
  <div>
    <CopyButton text="Hello, Clipboard!" />
  </div>
</template>
<script lang="ts">
import CopyButton from './CopyButton.vue';
export default {
  components: {
    CopyButton,
  },
};
</script>

解説

1. defineProps: - 親コンポーネントから渡される文字列を受け取ります。 - text はコピー対象の文字列。

2. クリップボードAPI: - navigator.clipboard.writeText を使用してテキストをクリップボードにコピーします。

3. 成功メッセージ: - コピーに成功すると copied フラグを true に設定し、一定時間後にリセットします。

4. エラー処理: - コピー操作に失敗した場合はエラーメッセージをコンソールに表示します。


ブラウザ互換性について

navigator.clipboard.writeText は、モダンブラウザ(Chrome, Edge, Firefox, Safariなど)でサポートされています。ただし、一部の古いブラウザでは動作しない可能性があります。 古いブラウザ対応が必要な場合は、 document.execCommand を使用したフォールバック処理を追加することを検討してください。

そこで、一つコンポーネントファイルを作り、Composition APIに直して実装しました。

copied を使ったアラートは、表示するには狭すぎるので、とっ外しました。

ただ、一部 iOS のブラウザでは対応できないため、ここでは、必要な情報をググるなどして、 iOS 判別や iOS 用のコピーコードを入れて対応しました。

GitHub Pages へのデプロイ

このアプリはGitHub Pagesにデプロイするので、npm run build すればいいわけですが、ここでちょっと手こずったことがありました。

なぜかデプロイしても、画面には何も表示されないのです。

原因が分からなかったので、ChatGPTに聞いてみることにしました。

Vite+Vue+TypeScript を使って、 GitHub Pages のビルドをする時に注意することは何でしょうか?

すると、いくつか回答があったのですが、次の回答に注目しました。

vite.config.tsでbase設定を追加

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
  plugins: [vue()],
  base: '/<REPOSITORY_NAME>/', // リポジトリ名を設定
});

そこで、vite.config.tsbase プロパティを設定すると、無事にアプリが表示できるようになりました。

開発して分かった知見

一通りデプロイまで完了したことで、得られたことを纏めました。

1. ChatGPTを含むAIを介して開発するときは、それ相応の技術スキルが必要

ChatGPTを使って質問してクリティカルな答えが返ったとしても、生成されたコードを見ると全く頓珍漢な実装になっていたり、十分網羅されていなかったり、ウソをつかれたりすることがあります。

そして、このコードが「これは頓珍漢だ!」と認識できるような技術スキルが無いままAIにかかりっきりになると、そのコードをノーアイデアでコピペしてしまい、実行結果が思いもよらないものとなり、なぜそうなるのか分からずに詰むといった結末が予見されます。 そのため、完全にAIに頼り切りにはせず、しっかりスキルを研鑽することを強くお勧めいたします。

2. ChatGPTに質問するときの尋ね方大事

次に、ChatGPTに実装コードを尋ねるときに、尋ね方を間違えると、あらぬ方向の回答がでることがあります。 「〇〇するにはどうしたらいいのか」という風に、ふわっとした内容で訊いてしまうと、開発や設計のアドバイスが出てしまい、実装するコードが出て来ないので、具体的な内容が必要です。

例えば、「TypeScript で〇〇するコードを実装してほしい」と書くと、コード例を答えてくれます。

また、付加情報も付けるとより精度の高いコードが出てきます。

例えば、「整数の配列を引数に取り、この配列がフィボナッチ定数かを boolean で返す TypeScript のコードを実装してほしい」と聞くと、よりイメージに近いコードを出力できるようになります。

条件を追加するときは、改行して「要素の値が〇のときは、×を返す」としてもいいですし、データの詳細を書くことも可能です。

3. クリティカルな答えではなくても妥協する

とはいえ、100%正解のコードが返って来ないことはあり得ます。これは 1. の内容と被りますが、ある程度の実装スキルがあれば、このコードを自分の思うような結果になるように改造することができます。 これだけでも、ゼロから実装することを思えば、十分な実装コスト削減効果を得られます。

ただし、まだまだ不十分だと判断したときは、回答を受けた後に、続けて質問するのも有効です。例えば、「上記のコードで結果が得られるのはわかりました。しかし、××のときはエラーを投げるようにしてほしいです」と質問すると、その意見を汲んだコードを生成することがあります。

総評:AIは開発の進捗を手助けしてくれる相棒になれる

最終的に、ChatGPT(AI)を併用した開発に関して、「作業進捗に十分有効だった」と評価しました。

個人的なアプリの実装に多大な時間を費やすのはナンセンスですので、ストレスなくデプロイまで持って行けたのは収穫でした。

この記事が、AI併用の手助けとなれば幸いです。

テコテックの採用活動について

テコテックでは新卒採用、中途採用共に積極的に募集をしています。
採用サイトにて会社の雰囲気や福利厚生、募集内容をご確認いただけます。
ご興味を持っていただけましたら是非ご覧ください。 tecotec.co.jp