VSCodeを手軽にリロードする為のショートカット - Qiita
Why not register and get more from Qiita?
https://qiita.com/Naturalclar/items/ae9e84fa8cf16a14c7e9
PREVENTでフロントエンドエンジニアをやっている伊賀本です。
私達は、Mystarという高血圧/脂質異常症/糖尿病の治療中の方を対象にした重症化予防支援事業「Mystar」を運営しており、その中でユーザー管理WebアプリのMystarProというものを開発しています。
日々開発業務を行う中で、VSCodeの動作が重くなる問題に直面したので今回はその問題をどう解決したかについて書いていこうと思います。
前項でも書いた通り、VSCodeの動作が重く、TypeScriptのLintの警告表示が、問題があるのに表示されなかったり、問題がないのに表示されたりということが発生していました。
また、補完が効いてくれないこともあり、開発業務に大きな支障をきたしていました。
暫定対応として ウィンドウの再読み込みをしていましたが、都度再読み込みを行っていると開発効率が落ち、ストレスも溜まるため、根本的な解決に乗り出しました。
この問題をフロントエンドエンジニアのチームMTGで相談したところ、業務委託メンバーから「このあたりが怪しいかも」という情報をいただいたので、まずはそこを調査しようということになりました。
怪しい部分のコードの1部は下記の通りです。
export type FasyItemInArray<ArrayType extends unknown[]> = ArrayType[number];
type UnionToIntersection<U> = (U extends any
? (k: U) => void
: never) extends (k: infer I) => void
? I
: never;
type RecursivePicker<T> = {
[K in keyof T]?: T[K] extends object | undefined | null
? RecursivePicker<T[K]>
: true;
};
export type _RecursivePick<T, KO extends RecursivePicker<T>> = Pick<
{
[K in keyof T]: K extends keyof KO
? KO[K] extends true
? T[K]
: KO[K] extends infer KOK
? KOK extends RecursivePicker<T[K]>
? RecursivePick<T[K], KOK>
: T[K] extends infer TKArray
? TKArray extends unknown[]
? RecursivePick<FasyItemInArray<TKArray>, KOK>[]
: never
: never
: never
: never;
},
keyof T & keyof KO
>;
export type RecursivePick<T, KO> = UnionToIntersection<T> extends never
? Maybe<_RecursivePick<NonNullable<T>, KO>>
: _RecursivePick<T, KO>;
以下、こちらのコードのことをRecursivePick
とします
コードの内容としては、バックエンド側で採用している99designs/gqlgenがFragmentsが未対応だったため、型情報をprivate registry経由で読み込み、上記のRecursivePickで型を生成しています。
開発が進むにつれqueryやmutationが増大し、RecursivePickで型の解決ができず、TS Serverが落ちてしまっているのではないか、という仮説を立てました
プロダクトの成長に伴いRecursivePickでの型生成に限界を感じたため、別の方法で型を生成できないか調査しました。
調査の結果graphql code generatorを使ってフロント側で型生成を行っておく方法がよさそうだったため、今回はこちらを導入し対策を行います。
MystarProはNuxt.js, TypeScriptで開発しているので、それに合わせてプラグインを導入していきます。
今回使用したプラグインは以下の通りです。
設定ファイルを作成していきます。先程紹介したプラグインや対象ファイル、スキーマなどを設定していきます。
今回スキーマはバックエンドの本番のものを使用しました。
もちろんAuthorizationの設定が必要となるので、型生成の際には、自身でログインした際に生成されるaccess_tokenを使用して型を生成することになります。
overwrite: true
schema:
- {本番のAPIのURL}/query:
headers:
Authorization: "{access_token}"
documents:
- src/**/*.{vue,ts}
- src/store/*.ts
generates:
src/__generated__/types.ts:
plugins:
- "typescript"
- "typescript-operations"
config:
maybeValue: "T | null"
enumsAsTypes: true
scalars:
ID: "number"
ここまでできたら、型を生成したいクエリを .vue
ファイルに記述していきます。
export const UserCard = gql`
fragment UserCard on UserProgramDetail {
user {
ID
firstName
lastName
}
}
`;
該当の.vue
ファイルがcodegen.yml
のdocuments
で指定されているのを確認して、codegenしてみます。
$ yarn graphql-codegen --config codegen.yml
そうすると該当の型が生成されます。
export type UserCardFragment = {
__typename?: 'UserProgramDetail';
user: {
__typename?: 'UserDetail';
ID: number;
firstName: string;
lastName: string;
};
};
導入以前はTS Serverが頻繁にクラッシュしていましたが、導入を行って以降はほぼ発生しなくなりました。
また、長時間VSCodeを立ち上げていると発生頻度が上がる傾向がありましたが、長時間でも問題なく開発が行えています。
ファンが全開で回ってPCが熱くなることも起きなくなりました。
それだけでも、大きな効果と言えます。
上記の改善を行ったのですがまだ完璧ではなく、同じクエリを別のコンポーネントで使用している場合、Fragment名が被ってしまい、どの型を参照しているのかわからないという問題があります。
ですので、一意なFragment名にするためのルールが必要となります。
なので今後はこのような問題を改善するためにはどのようなルールが必要なのか検討してどのように運用していくか、また記事にできたらと思います。
以上が、今回行った開発環境の改善となります。
一口にVSCodeが重いと言っても色んな状況があるので、調査したり、懸念点を潰していったりと、色んな方法があるとは思いますが、もし現在の環境に不満がある場合は、よりよい環境で開発するために、改善活動を行ってみてはいかがでしょうか!
現在、PREVENTではフロントエンドエンジニアを募集しています!
どれかに当てはまった方は是非チェックしてカジュアルにお話しましょう!
また、フロントエンドエンジニアではない方の募集もありますので、是非ご覧ください!