プレイドインターン体験記:開発体験の向上を目指し行なったこと

はじめに

初めまして、田添春樹と申します。2024年9月から12月までの3ヶ月間、KARTE Webチームでエンジニアとしてインターンシップを行なっておりました。

インターンシップに参加する以前、趣味で関わっていたOSSプロジェクトにおいて、Vueを用いた開発を行なっておりました。その際の開発経験が楽しかったことと、これからもVueを用いて開発を行いたいことなどを、プレイドに勤務している親友と話した際に、このインターンシップに誘っていただきました。

私はどちらかと言えば、縁の下の力持ちとして物事に取り組むことが多く、開発においても、開発者が今後の開発をストレスなく、より良い環境で行えるようにリファクタリングなどを行なってきました。面談の際に、その旨を伝え、インターンシップとして開発体験を向上させるための業務をすることとなりました。

このインターンシップで行った内容は以下のようになっております。

  • KARTEのエレメントビルダーのViteバージョンアップ
  • KARTEのユーザーリストや行動チェーン、ユーザーストーリーといった機能(以下、これらの機能をまとめてinsight-frontと呼称します。)における、開発体験向上を目的としたViteへの移行と、Vueのバージョンアップやそれらに伴う依存パッケージのバージョンアップ

本記事ではインターンシップで行ってきたことの内容について、上記の二点をお伝えします。

エレメントビルダーのViteバージョンアップ

課題

KARTEのエレメントビルダーは、顧客⼀⼈ひとりに合わせて、最適なコミュニケーションができるように、顧客の行動に基づいてポップアップ表示などのアクションを作成・カスタマイズできる機能です。

action-editor.png

しかし、これまでのエレメントビルダーには以下のような課題がありました。

  • 開発環境がメンテナンスされていないため、ここ最近のフロントエンド環境と乖離が生じてきて、開発しにくい状況になってきていた
  • Viteのバージョンが古いため、KARTEのデザインシステムの導入に特別な対応が必要になる

特に、一点目の課題が大きく、これまでのエレメントビルダーの開発環境におけるViteやVitestなどのパッケージはエレメントビルダーが開発されていた当時の状態のままになっておりました。これまでの開発環境のままでも開発はすることができますが、フロントエンド周りの環境は日々変わっていきます。今後新たな機能を実装する際、または新たなパッケージを導入する際、開発環境の遅れによって、それらの新しい機能の実装やパッケージの導入により多くの時間をかけてしまうことになります。

これらの課題を解決するために、エレメントビルダーのViteのバージョンを上げることになりました。

これまでエレメントビルダーで使用していたViteのバージョンは3.2.5で、今回のバージョンアップで4.5.3になりました。これまで使用していたVite 3系から一気にViteの最新バージョンへ上げるのではなく、小さくアップデートを行いたかったため、今回は4系へアップデートしました。

https://v4.vite.dev/

また、それに伴って、Vitestのバージョンも上げることとなり、0.24.3から0.34.6にアップデートしました。

これまで使用していたVitest 0系から1系に上げるには、Vite 5系が必要となっており、先述のVite 4系を使う方針のために、1系ではなく0系の最新バージョンへアップデートしました。

https://v0.vitest.dev/

テストが動かない

ViteとVitestのバージョンアップを行ったことで、テストが動かなくなってしまったため、関連するパッケージのバージョンアップも行っていきました。

エレメントビルダーは細分化されたモジュールで作られており、それぞれに対応するパッケージの管理が複雑になっています。バージョンを上げたパッケージが他のパッケージのバージョンをサポートしていないことや、メンテナンスされていないパッケージを使用していることなど、複数の要因でテストが動かなくなってしまいました。

たとえば、@testing-library/react-hooksというパッケージでは、React 18でrenderHookAPIがreact-testing-libraryreact-native-testing-libraryの両方に追加されたことにより、@testing-library/react-hooks@testing-library/reactに書き換える必要があります。

https://github.com/testing-library/react-hooks-testing-library?tab=readme-ov-file#a-note-about-react-18-support

他にも、@sveltejs/vite-plugin-svelteというパッケージにおいて、Vitest は基本的にnode_modules配下にあるモジュールはaliasで設定していなくても、モジュール依存を解決してくれるのですが、テスト内でコンポーネントをレンダーした際にonMountが実行されないというバグを解決するために、以下のように明示的に設定しないといけませんでした。

import { defineConfig } from 'vitest/config';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { dirname, resolve } from 'node:path';

export default defineConfig({
  // ...
  resolve: process.env.TEST ? {
    alias: [{
      find: /^svelte$/,
      replacement: resolve(__dirname, "node_modules/svelte/index.mjs") 
     }]
  } : {
    alias: {
      '@plaidev/karte-action-sdk/templates': resolve(__dirname, './src/templates.ts'),
    },
  },
  // ...
});

https://github.com/testing-library/svelte-testing-library/issues/222

https://testing-library.com/docs/svelte-testing-library/faq#why-isnt-onmount-called-when-rendering-components

小さく解決する

先述の通り、エレメントビルダーは細分化されたモジュールで作られており、それぞれにテストが用意されています。(以下は一部抜粋)

.
├── api
├── asset-builder
├── core
│   ├── action-compiler
│   ├── action-sdk
│   └── action-utils
├── front
└── internal

これらのテストのほとんどが動かなくなってしまったので、それぞれのモジュールごとに小さくテストが通るよう修正を行い、最終的に全てのテストが通るようにパッケージのバージョンアップやパッケージの置き換えを行いました。

パッケージのバージョンアップを行った結果、パッケージの破壊的変更によってテストコードの修正を行う必要がありました。修正を行うためには、どこに問題があるのか探す必要があり、使用しているパッケージのソースコードを実際に動かしてみて、意図的にエラーを発生させ、エレメントビルダーのテストにおける問題のある箇所を発見することができました。

insight-front開発体験改善

課題

insight-frontを開発する際、他のシステムからイベントを飛ばしてデータを作る必要があり、フロントエンドのデバッグに時間を要するという課題がありました。

insight-front.png

この部分の課題を解決することで、今後新たな機能を開発する際や修正を行う際に素早く対応できるため、これまで使用されていたWebpackからViteへ移行することになりました。

Viteに移行することによって具体的にどんな点がより良くなるのかというと、開発サーバーの立ち上がりがWebpackよりも早くなるのでデバッグに要する時間が少なくなります。

https://vite.dev/guide/why.html#slow-server-start

Vite移行に向けて

WebpackからViteへ移行するために、以下のような手順を踏んでいきます。

Vue 2.7へアップデート

insight-frontはVue 2で開発されており、ViteではVueアプリケーションのバンドルをするために、Vueの単一ファイルコンポーネントのサポートを提供している@vitejs/plugin-vue2を導入する必要があります。

insight-frontで使用されていたVueのバージョンは2.6.12だったため、@vitejs/plugin-vue2が要求するVue 2の最新バージョンであるVue 2.7へアップデートする必要がありました。

また、Vue 2はすでにサポートが終了しているため、セキュリティパッチを当てたVue 2を使用しています。

https://v2.vuejs.org/v2/guide/migration-vue-2-7.html

ES ModulesとCommonJSによるデュアルパッケージ化

localDependenciesというプレイド独自の依存関係の解決機構を使用しており、ここに使用される社内の共通パッケージはCommonJSでビルドされていました。これまではWebpackを使用してバンドルしていたので、CommonJSで書かれた共通パッケージも問題なくバンドルし、アプリケーションを動作させることが出来ました。(Webpackを用いてバンドルしている場合でも、使用しているパッケージがNode.js依存である場合、手動でpolyfillを挿入するように設定する必要があります。)

しかし、このlocalDependenciesの解決機構を使っていることにより、Viteで共通パッケージのCommonJSの依存解決ができずバンドル出来ないため、これらの共通パッケージをES ModulesとCommonJSでバンドルする必要がありました。

"localDependencies": {
  "@plaidev/xxx-common": "../../../common",
  "@xxx/insight-front-common": "../front-common"
},

insight-frontにおいて、localDependenciesという解決機構で依存解決を行なっている共通パッケージ内には大量のコードが存在しており、その中からinsight-frontを動かすために必要なコードを調査する時間や、それらのコードをES ModulesとCommonJSでデュアルパッケージ化するための時間、実際にES ModulesとCommonJSでデュアルパッケージ化した後に、関連するシステムが動くかどうか確認するための時間など、多くの時間を費やすことになるだろうと予想しました。

ES ModulesとCommonJSによる共通パッケージのデュアルパッケージ化をするには多くの時間がかかってしまうため、Viteの機能を利用してES ModulesとCommonJSでバンドル出来ないか試してみることにしました。

https://vite.dev/config/build-options#build-lib

Viteでビルドする

上記に書いた通り、insight-frontを取り巻く依存関係の問題は大きく、それらを解決するために大量に時間を要することが予想されました。また、私自身がフロントエンドについての知識がまだまだ浅く、一気にこれらを解決させようとしてどこに問題が発生しているのか調査すること自体にも多くの時間を使ってしまいました。

この失敗を受けて、小さく小さく課題に取り組むことを意識し、最初からアプリケーションのソースコード全体をビルドさせることは考えないようにしました。まずは、小さなHTMLファイルのビルドから行い、実際にアプリケーションを動かした際に問題がないことを確かめることから始めました。そこにVue 2で書かれた小さなコードを追加するような形で、必要なプラグインなどを細かく追加していくなど、インクリメンタルな実装を行なっていくことで自身のViteに対する解像度も上がってきました。

しかし、ここでインターンシップ期間が終わってしまい、insight-frontをWebpackからViteに移行することが出来ませんでした。複雑な問題が絡み合い、この課題を解くのは難しかったのですが、自身が普段のめり込むことが無いような部分にのめり込み、様々なことを学ぶことが出来ました。

インターンシップを終えて

総括

インターンシップとして主に二つの内容に取り組んできました。

開発環境をメンテナンスをしないまま、放置してしまうことにより、今後のバージョンアップで大きな障壁となってしまうことを避けるためにも、日頃からメンテナンスを怠らないようにしたいです。

しかし、プロダクトの開発において、メンテナンスをすることにより、本来先に実装したかった内容に遅れが生じてしまうことがあります。その実装の遅れとメンテナンスをすることによる恩恵を考えて、両方を天秤にかけ、どちらがプロダクトにより大きなインパクトを与えられるのか考え続けなければなりません。

そして、目の前の難しい課題に対して、直線的に解決策を取ろうとするのではなく、回り道をしつつ、小さく小さく問題を区切りながら解決に向かうことを意識していきたいです。

成長

これまでは、主にPHPを用いたバックエンドの開発を行なっており、フロントエンドの開発は自作のブログや先述のOSSプロジェクトの小さな機能の開発以外ではほとんど触ったことがなく、こんなにもガッツリとフロントエンドの領域にのめりこむのは初めてでした。

フロントエンドの技術について、あまり知識がない状態からキャッチアップを行いつつ、大きな成果を出すことが出来て、とても学びのあるインターンシップだったと感じております。

もちろん、一人では抱えきれない悩みや課題などが生じた際に一緒に解決してくださったメンターの方やKARTE Webチームの方々のおかげだと感じております。

KARTEの強みを理解し、どうすればその強みをプロダクトに機能として実装できるのか。そして、顧客に大きなインパクトを与えられるか、という思考のサイクルを止めることなくプロダクトに向き合っているプレイドの方々の姿勢に感銘を受けました。

そして、インターンシップを行なっていく中で自分に何が足りないのか、プロダクト開発やその会社に属する人間としてどんな視点を持てば良いのか、深く考えることのできたインターンシップでした。

最後に

インターンシップ期間中は広島からフルリモートでの勤務をしていました。フルリモートでなかなか顔を合わせてお話しする機会がない中、広島から東京のオフィスに出社した際には、他のインターンシップ生とのランチに誘っていただいたり、多くの方々とお話しさせていただく機会に参加させていただいたりと、社内の雰囲気もとても良かったです。

3ヶ月という短い間でしたが、メンターの方やKARTE Webチームの方々など、多くの方々のおかげで濃密な3ヶ月を過ごすことが出来ました。本当にありがとうございました。


プレイドでは開発インターンを募集しています。興味のある方はぜひ下記のリンクからご応募ください!