TypeScriptのパフォーマンス



TypeScriptを構成して、コンパイルと編集を高速化する簡単な方法があります。そして、それらが実装されるのが早ければ早いほど良いです。コンパイルと編集が遅い原因を調査するための一般的なアプローチ、いくつかの修正、およびTypeScriptチームが問題を調査するのに役立つ一般的な方法もあります。



1.コンパイルしやすいコードを書く



1.1。交差点(交差点)よりもインターフェイスの優先度



多くの場合、オブジェクトタイプの単純なエイリアスは、インターフェイスと同じように機能します。



interface Foo { prop: string }

type Bar = { prop: string };

      
      





ただし、2つ以上のタイプの組み合わせが必要な場合は、インターフェースでそれらを拡張するか、エイリアス内にタイプの共通部分を作成できます。これらのアプローチの違いは重要です。



インターフェイスは、通常解決することが重要なプロパティの競合を公開する単一のフラット化オブジェクトタイプを作成します。そして、交差点は単にプロパティを再帰的に結合し、場合によっては生成します never



..。また、インターフェイスのレンダリングが向上しますが、交差点のタイプエイリアスを他の交差点に表示することはできません。交差タイプとは異なり、インターフェイス間のタイプ関係はキャッシュされます。最後の重要な違いは、ターゲット交差タイプに対して検証する場合、各コンポーネントは検証/フラット化される前に検証されることです。



したがって、型の交差を作成するのではなく、interface



/ extends



型を拡張することをお勧めし ます。



- type Foo = Bar & Baz & {
-     someProp: string;
- }
+ interface Foo extends Bar, Baz {
+     someProp: string;
+ }

      
      





1.2。タイプ注釈の使用



特に戻り値の型注釈を追加すると、コンパイラの作業を大幅に節約できます。これは、名前付きタイプは通常、匿名タイプ(コンパイラーがキャストできる)よりもコンパクトであるためです。これにより、宣言ファイルの読み取りと書き込みにかかる時間が短縮されます(たとえば、インクリメンタルビルドの場合)。キャスティングはとても便利なので、普遍的に行う必要はありません。ただし、コード内に遅いフラグメントが見つかった場合は、試してみると便利です。



- import { otherFunc } from "other";
+ import { otherFunc, otherType } from "other";

- export function func() {
+ export function func(): otherType {
      return otherFunc();
  }

      
      





1.3。複数のタイプよりも基本タイプの方が優先



複数のタイプは優れたツールです:タイプの可能な値の範囲を表現できます。



interface WeekdaySchedule {
  day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday";
  wake: Time;
  startWork: Time;
  endWork: Time;
  sleep: Time;
}

interface WeekendSchedule {
  day: "Saturday" | "Sunday";
  wake: Time;
  familyMeal: Time;
  sleep: Time;
}

declare function printSchedule(schedule: WeekdaySchedule | WeekendSchedule);

      
      





しかし、すべてに代償があります。引数が渡される printSchedule



たびに、セットの各要素と比較する必要があります。これは2つの要素の問題ではありません。ただし、セットに12個の要素がある場合、コンパイル速度が遅くなる可能性があります。たとえば、冗長な要素を削除するには、それらをすべてペアで比較する必要があります。これは2次関数です。このようなチェックは、大きなセットを交差させるときに発生する可能性があります。セットの各要素の交差が、削減する必要のある巨大なタイプにつながる可能性がある場合です。また、セットではなくサブタイプを使用することで、これらすべてを回避できます。



interface Schedule {
  day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday";
  wake: Time;
  sleep: Time;
}

interface WeekdaySchedule extends Schedule {
  day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday";
  startWork: Time;
  endWork: Time;
}

interface WeekendSchedule extends Schedule {
  day: "Saturday" | "Sunday";
  familyMeal: Time;
}

declare function printSchedule(schedule: Schedule);

      
      





より現実的な例は、すべての組み込みDOM要素タイプをモデル化しようとする場合です。この場合、重いセットを作成するよりもHtmlElement



頻繁な要素を使用してDivElement



ImgElement



など で展開する基本タイプを作成することをお 勧めし DivElement | /*...*/ | ImgElement | /*...*/



ます。



2.プロジェクトリンクの使用



大規模なTypeScriptコードベースを構築する場合は、複数の独立したプロジェクトに編成すると便利です それらのそれぞれはtsconfig.json



、他のプロジェクトに依存関係を持つ独自のものを持ってい ます。これにより、1回のコンパイルでダウンロードするファイルが多すぎるのを防ぐことができます。また、さまざまなコードベーススキームを簡単に組み合わせることができます。 コードベースをプロジェクト



分割する非常に簡単な方法がいくつかあり ますたとえば、クライアント用のプロジェクト、サーバー用のプロジェクト、およびそれらの間の共通プロジェクト。



             ------------
              |          |
              |  Shared  |
              ^----------^
             /            \
            /              \
------------                ------------
|          |                |          |
|  Client  |                |  Server  |
-----^------                ------^-----

      
      





テストは、別のプロジェクトに分割することもできます。



             ------------
              |          |
              |  Shared  |
              ^-----^----^
             /      |     \
            /       |      \
------------  ------------  ------------
|          |  |  Shared  |  |          |
|  Client  |  |  Tests   |  |  Server  |
-----^------  ------------  ------^-----
     |                            |
     |                            |
------------                ------------
|  Client  |                |  Server  |
|  Tests   |                |  Tests   |
------------                ------------

      
      





人々はよく「プロジェクトの大きさはどれくらいにするべきですか?」と尋ねます。「関数の大きさはどれくらいにするべきか」と尋ねるようなものです。または「クラスの大きさはどれくらいですか?」多くは経験に依存します。たとえば、フォルダを使用してJS / TSコードを共有でき、一部のコンポーネントが相互接続されて1つのフォルダに配置できる場合、それらは同じプロジェクトに属していると見なすことができます。また、大規模または小規模のプロジェクトは避けてください。それらの1つが他のすべてを合わせたものよりも大きい場合、これは悪い兆候です。また、オーバーヘッドが増加するため、数十の単一ファイルプロジェクトを作成しないことをお勧めします。



プロジェクト間のリンクについては、 こちらをご覧ください



3.tsconfig.jsonまたはjsconfig.jsonの構成



TypeScriptおよびJavaScriptユーザーは、tsconfig.jsonファイルを使用していつでもコンパイルをカスタマイズできます。 Jsconfig.jsonファイル使用して、 JavaScript編集をカスタマイズすることもできます



3.1。ファイルの定義



構成ファイルに一度にリストされるファイルが多すぎないことを常に確認してください。



あなたは tsconfig.json



二つの方法でプロジェクトファイルを定義することができます。



  • リストfiles



    ;
  • リストinclude



    exclude



    ;


2つの主な違いは、 files



ソースファイルパスのリストを取得し、 include



/ exclude



グロビングパターンを使用して対応するファイルを識別することです。



を定義することにより files



、TypeScriptがファイルを直接すばやくロードできるようにします。プロジェクトに多くのファイルがあり、高レベルのエントリポイントが少ない場合、これは面倒な場合があります。また、に新しいファイルを追加するのを忘れがちで、 tsconfig.json



奇妙なエディターの動作に遭遇します。



include



/ exclude



これらのファイルのすべてを識別する必要はありませんが、システムは追加されたディレクトリを調べてそれらを検出する必要があります。そして、存在する場合 、多くの、コンパイルが遅くなる場合があります。さらに、コンパイル.d.ts



多数の不要なテストファイルが含まれる ことがあります。これにより、速度が低下し、メモリ消費量が増加する可能性があります。最後に、 exclude



適切なデフォルトがありますが、モノリポジトリなどの一部の構成にはnode_modules



、コンパイル時に追加されるような「重い」フォルダがあります



これを行うのが最善です:



  • プロジェクトの入力フォルダーのみを定義します(たとえば、コンパイルおよび分析中に追加するソースコード)。
  • 同じフォルダ内の異なるプロジェクトからのソースファイルを混在させないでください。
  • テストを同じソースフォルダに保存する場合は、簡単に除外できるように名前を付けてください。
  • のような大きなアセンブリアーティファクトや依存関係フォルダを作成しないでくださいnode_modules





注:リストがない場合、 exclude



フォルダー node_modules



はデフォルトで除外されます。また、リストを追加する場合は、リストに明示的に示すことが重要 node_modules



です。



ここに例があり tsconfig.json



ます:



{
    "compilerOptions": {
        // ...
    },
    "include": ["src"],
    "exclude": ["**/node_modules", "**/.*/"],
}

      
      





3.2。@typesの追加の制御



デフォルトでは、TypeScriptは、インポートしたかどうかに関係なく、フォルダー内にあるすべてのnode_modules



パッケージを自動的に追加し ます @types



これは、Node.js、Jasmine、Mocha、Chaiなどを使用するときに、これらのツール/パッケージがインポートされずにグローバル環境にロードされるため、特定の機能を「正しく機能」させるためです。



このロジックにより、プログラムのコンパイルと編集が遅くなる場合があります。また、次のようなエラーを引き起こす多数のグローバルパッケージで宣言の競合が発生することもあります。



Duplicate identifier 'IteratorResult'.
Duplicate identifier 'it'.
Duplicate identifier 'define'.
Duplicate identifier 'require'.

      
      





グローバルパッケージが必要ない場合は、/ :の「types」オプション空のフォルダー定義でき ます。 tsconfig.json



jsconfig.json







// src/tsconfig.json
{
   "compilerOptions": {
       // ...

       // Don't automatically include anything.
       // Only include `@types` packages that we need to import.
       "types" : []
   },
   "files": ["foo.ts"]
}

      
      





グローバルパッケージが必要な場合は、フィールドに追加します types







// tests/tsconfig.json
{
   "compilerOptions": {
       // ...

       // Only include `@types/node` and `@types/mocha`.
       "types" : ["node", "mocha"]
   },
   "files": ["foo.test.ts"]
}

      
      





3.3。インクリメンタルプロジェクト生成



このフラグ --incremental



により、TypeScriptは最後にコンパイルされた状態をファイルに保存できます .tsbuildinfo



--watch



TypeScriptモードと同様に、前回の実行以降に再チェック/上書きできるファイルの最小セットを定義するために使用されます プロジェクト間リンク



フラグを使用すると、増分生成がデフォルトで有効になります composite



が、他のプロジェクトも高速化できます。



3.4。検証のスキップ.d.ts



デフォルトでは、TypeScriptは.d.ts



プロジェクト内のすべてのファイルを完全に再チェック して、問題や不整合を見つけます。しかし、これは通常必要ありません。多くの場合、これらのファイルはすでに機能することがわかっています。型拡張メソッドはすでにチェックされていますが、重要な宣言は引き続きチェックされます。



TypeScriptを使用すると、フラグskipDefaultLibCheck



は、提供された.d.ts



ファイル(たとえば、lib.d.ts



)の型チェックスキップ できます



フラグskipLibCheck



有効にして、コンパイル中のすべての .d.ts



ファイルのチェックをスキップする こともでき ます。



これらの2つのオプションは、多くの場合、構成エラーと競合を非表示にします。 .d.ts



ファイルなので、ビルドを高速化するためにのみ使用することをお勧めします



3.5。より高速なバリアディックチェック



犬や動物のリスト?あなたはつながること List<Dg>



List<Animls>



?答えを見つける簡単な方法は、要素ごとにタイプを構造的に比較することです。残念ながら、このソリューションは非常に高額になる可能性があります。我々は十分に知っている場合でも List<>



、我々はそれを参照することが許されるかどうかを判断するに割り当てチェックを削減することが可能 Dog



Animal



(各要素をチェックせず、です List<>



)。特に、パラメータタイプの変動性を知る必要があります T



。コンパイラは、フラグがオンの場合にのみ最適化を最大限に活用できます strictFunctionTypes



(それ以外の場合は、速度は遅くなりますが、より寛大な構造チェックが使用されます)。したがって、フラグ--strictFunctionTypes



(でデフォルトで有効になっています--strict



)を使用してビルドすることをお勧めし ます



4.他の組み立てツールのセットアップ



TypeScriptは、特にバンドラーを使用できるWebアプリケーションを構築する場合に、他の構築ツールでコンパイルされることがよくあります。いくつかのアイデアしか提供できませんが、一般的にこのアプローチは一般化できます。



この部分に加えて、選択したツールのパフォーマンスについて必ずお読みください。次に例を示します。





4.1.



タイプチェックは通常、他のファイルからの情報を必要とし、コードの変換/書き込みなどの他のステップと比較して比較的コストがかかります。タイプチェックは非常に時間がかかる可能性があるため、内部開発サイクルに影響を与える可能性があります。つまり、編集-コンパイル-実行のサイクルが長くなり、不快になります。



したがって、多くのビルドツールは、ファイルの作成をブロックすることなく、別のプロセスでタイプをチェックできます。この場合、TypeScriptがビルドツールでエラーを報告する前に、誤ったコードが実行される可能性があります。多くの場合、最初にエディターにエラーが表示され、コードが実行されるのを待ちません。



例は fork-ts-checker-webpack-pluginですWebpack、または同様の awesome-typescript-loaderの場合



4.2。分離ファイルの作成



デフォルトでは、TypeScriptでファイルを作成するには、ファイルに対してローカルではない可能性のあるセマンティック情報が必要です。これは、特徴が好きかを理解する必要があるconst enum



生成されます namespace



ただし、他のファイルをチェックして任意のファイルの結果を生成する必要があるため、生成が遅くなることがあり ます。



非ローカル情報を必要とする機能が必要になることはめったにありません。enum



代わりにレギュラー を使用できconst enum



代わりにモジュール を使用できます namespace



したがって、TypeScriptにはフラグがあります isolatedModules



非ローカル情報を必要とする機能でエラーを発行します。このフラグを使用するとtranspileModule



、BabelのようなTypeScriptAPIまたは代替コンパイラを使用するツールを安全に使用できます



値をインライン化する必要があるため、サンドボックス化されたファイル変換では、このコードは実行時に正しく機能しません const enum



幸いなことに、彼は isolatedModules



事前に私たちに警告します。



// ./src/fileA.ts

export declare const enum E {
    A = 0,
    B = 1,
}

// ./src/fileB.ts

import { E } from "./fileA";

console.log(E.A);
//          ~
// error: Cannot access ambient const enums when the '--isolatedModules' flag is provided.

      
      





注意: isolatedModules



コード生成を自動的に高速化するわけではありません。サポートされていない可能性のある機能の使用についてのみ警告します。さまざまなビルドツールとAPIでモジュールを個別に生成する必要があります。



次のツールを使用して、ファイルを個別に作成できます。





5.問題調査



何かがうまくいかない理由を理解するためのさまざまな方法があります。



5.1。エディタプラグインを無効にする



プラグインは、エディターの動作に影響を与える可能性があります。それら(特にJavaScript / TypeScript関連のもの)を無効にして、パフォーマンスと応答性が向上するかどうかを確認してください。



一部の編集者は、独自のパフォーマンスに関する推奨事項を持っています。それらを読んでください。たとえば、Visual StudioCodeには 別のヒントページがあります



5.2。extendedDiagnostics



TypeScriptをで実行し--extendedDiagnostics



て、コンパイラの時間がどこで費やされているかを確認できます



Files:                         6
Lines:                     24906
Nodes:                    112200
Identifiers:               41097
Symbols:                   27972
Types:                      8298
Memory used:              77984K
Assignability cache size:  33123
Identity cache size:           2
Subtype cache size:            0
I/O Read time:             0.01s
Parse time:                0.44s
Program time:              0.45s
Bind time:                 0.21s
Check time:                1.07s
transformTime time:        0.01s
commentTime time:          0.00s
I/O Write time:            0.00s
printTime time:            0.01s
Emit time:                 0.01s
Total time:                1.75s

      
      





Total time



重複しているものもあれば、まったく測定されていないものもあるため、記載されているすべての時間コストの合計にはならないことに注意しください



ほとんどのユーザーにとって最も関連性の高い情報:



フィールド
Files





プログラムに含まれるファイルの数(を使用して表示できるファイルの種類--listFiles



)。
I/O Read time





ファイルシステムからの読み取りに費やされた時間。これには、からのフォルダの読み取りが含まれますinclude



Parse time





プログラムのスキャンと解析に費やされた時間。
Program time





ファイルシステムからの読み取り、プログラムのスキャンと解析、およびその他のグラフ計算にかかる合計時間。これらのステージは、それらが経由して、それらが追加されるとすぐに有効にしてロードする必要があるため、ここで結合さimport



export



Bind time





特定のファイルにローカルなさまざまなセマンティック情報の組み立てに費やされた時間。
Check time





プログラムのタイプをチェックするのに費やした時間。
transformTime time





TypeScript AST(ソースファイルを表すツリー)をレガシーランタイム環境で機能するフォームに書き換えるのに費やした時間。
commentTime





生成されたファイルのコメントの評価に費やされた時間。
I/O Write time





ディスク上のファイルの書き込みと更新に費やされた時間。
printTime





生成されたファイルの文字列表現を計算してディスクに保存するのに費やした時間。


これらの入力を考えると、必要なものは次のとおりです。



  • ファイル/コード行の数は、プロジェクト内のファイルの数にほぼ対応していますか?そうでない場合は、を使用してみてください--listFiles



  • あるProgram time



    I/O Read time



    外観の大きなは?設定が正しいか確認してくださいinclude



    /exclude





他のタイミングに問題があるように見えますか?あなたは問題報告に記​​入することができます!診断に役立つもの:



  • emitDeclarationOnly



    値がprintTime



    高い場合から始めます
  • コンパイラのパフォーマンス問題の報告手順




5.3。showConfig



tsc



特にtsconfig.jsons



他の構成ファイルを拡張できることを考えると、 起動時にコンパイルが実行される設定が常に明確であるとは限りません showConfig



それが何を計算するかを説明することができ tsc



ます。



tsc --showConfig

# or to select a specific config file...

tsc --showConfig -p tsconfig.json

      
      





5.4。traceResolution



withtraceResolution



実行する ファイルがコンパイルに追加された理由がわかります データは非常に広範囲にわたるため、結果をファイルに保存できます。



tsc --traceResolution > resolution.txt

      
      





あなたがすべきではないファイルを見つけた場合は、リストを修正することができます include



/ exclude



ファイルに tsconfig.json



、などの設定を調整し types



typeRoots



paths







5.5。1つのtscを実行する



ユーザーは、Gulp、Rollup、Webpackなどのサードパーティビルドツールでパフォーマンスが低下することがよくあります。TypeScripttsc --extendedDiagnostics



とサードパーティツールの間の大きな不一致を見つけるために実行 すると、外部構成のエラーまたは非効率が示される可能性があります。



自問する必要があること:



  • tsc



    TypeScript統合ツールとのビルド時間に大きな違いはありますか?
  • サードパーティのツールに診断ツールがある場合、TypeScriptとサードパーティのツールでソリューションは異なりますか?
  • ツールにはパフォーマンスの低下を引き起こす可能性のある独自の構成がありますか?
  • ツールには、パフォーマンスの低下を引き起こす可能性のあるTypeScript統合するための構成がありますか(ts-loaderのオプションなど)?


5.6。依存関係の更新



計算が複雑なファイルがTypeScriptの型チェックに影響を与える場合があります .d.ts



まれですが、発生します。これは通常、TypeScriptの新しいバージョン(より効率的に)またはパッケージの新しいバージョン@types



(回帰を逆転させる可能性があります)にアップグレードすることで解決され ます。



6.よくある問題



困難に直面したとき、あなたは一般的な問題の解決策について学びたいと思うでしょう。以下が役に立たない場合は、問題報告できます



6.1。正しく構成されていない包含と除外



前述のように、include



/ オプションexclude



は誤用される可能性があります



問題 原因 補正
node_modules



より深いサブフォルダーから誤って追加されました。
構成されていません exclude



"exclude": ["**/node_modules", "**/.*/"]





node_modules



より深いサブフォルダーから誤って追加されました。
"exclude": ["node_modules"]





"exclude": ["**/node_modules", "**/.*/"]





ドット付きの非表示ファイルはランダムに追加されます(たとえば.git



)。
"exclude": ["**/node_modules"]





"exclude": ["**/node_modules", "**/.*/"]





予期しないファイルを追加しました。 構成されていません include



"include": ["src"]







7.問題レポートの完成



プロジェクトがすでに正しく最適に構成されている場合は、問題レポートに記入できます



優れたレポートには、問題のわかりやすい説明が含まれています。つまり、Gitを介して簡単に複製できるいくつかのファイルのコードベースが含まれています。この場合、アセンブリツールとの外部統合は必要ありません。アセンブリツールを介して呼び出す tsc



か、TypeScriptAPIを使用するサンドボックス化されたコードを使用できます。複雑な呼び出しと設定を必要とするコードベースに優先順位を付けることはできません。



はい、これは必ずしも簡単に達成できるとは限りません。特に、コードベース内で問題の原因を特定することは困難であり、知的財産保護に関する考慮事項もあるためです。問題の重要性が高いと思われる場合は、NDAを送信できる場合があります。



問題の再現性に関係なく、レポートを完成させるときは、これらのヒントに従ってください。解決策を見つけるのに役立ちます。



7.1。コンパイラパフォーマンスの問題レポート



場合によっては、ビルドと編集の両方でパフォーマンスの問題が発生します。次に、TypeScriptコンパイラに焦点を当てることは理にかなっています。



まず、TypeScriptの「夜間」バージョンを使用して、修正された問題が発生していないことを確認します。



npm install --save-dev typescript@next

# or

yarn add typescript@next --dev

      
      





パフォーマンスの問題の説明には、次のものを含める必要があります。



  • TypeScriptのインストール済みバージョン(npx tsc -v



    またはyarn tsc -v



    )。
  • TypeScript(node -v



    が実行されていたノードのバージョン
  • オプションextendedDiagnostics



    tsc --extendedDiagnostics -p tsconfig.json



    で実行した結果
  • 理想的には、目前の問題を実証するためにプロジェクト自体が必要です。
  • コンパイラプロファイラログ(ファイルisolate-*-*-*.log



    および*.cpuprofile



    )。


コンパイラのプロファイリング



Node.jsv10 +をフラグで実行し--trace-ic



、TypeScriptを フラグで実行して、診断トレースを提供することが重要 --generateCpuProfile



です。



node --trace-ic ./node_modules/typescript/lib/tsc.js --generateCpuProfile profile.cpuprofile -p tsconfig.json

      
      





これ ./node_modules/typescript/lib/tsc.js



は、ご使用のバージョンのTypeScriptコンパイラがインストールされているパスに置き換えることができます。代わりにtsconfig.json



、任意のTypeScript構成ファイルにする ことができます。代わりに profile.cpuprofile



-選択した出力ファイル。



2つのファイルが生成されます。



  • --trace-ic



    データをビューファイルに保存しますisolate-*-*-*.log



    (たとえばisolate-00000176DB2DF130-17676-v8.log



    )。
  • --generateCpuProfile



    選択した名前のファイルにデータを保存します。上記の例では、これはprofile.cpuprofile



    です。


:これらのファイルには、パスやソースコードなど、ワークスペースからの情報が含まれている場合があります。どちらのファイルもプレーンテキストで作成されており、Githubレポートに添付する前に編集できます(たとえば、機密情報を明らかにする可能性のあるパスをクリアすることによって)。



ただし、Githubに配置することに疑問がある場合は、私たちに書いてください。情報を非公開で送信できます。



7.2。レポートエディタのパフォーマンスの問題



編集パフォーマンスが低下する理由はたくさんあります。また、TypeScriptチームは、JavaScript / TypeScript言語サービスのパフォーマンス、および言語サービスと特定のエディター(Visual Studio、Visual Studio Code、Visual Studio for Mac、Sublime Textなど)との統合にのみ影響を与えることができます。エディターですべてのサードパーティプラグインが無効になっていることを確認してください。これにより、問題がTypeScript自体に関連していることが確認されます。



エディターのパフォーマンスの問題はもう少し複雑ですが、同じ考え方が当てはまります。再現可能な問題を伴うクローン化された最小限のコードベースが理想的です。また、場合によっては、NDAに署名して、問題を調査および切り分けることができます。



からのデータの追加 tsc --extendedDiagnostics



、ただし、TSServerトレースがある場合はさらに優れています。



VisualStudioコードでTSServerログを取得する



  1. コマンドバーを開き、次の手順を実行します。
  2. オプションを設定します«typescript.tsserver.log»: «verbose»,



  3. VSコードを再起動し、問題を再現します。
  4. VSコードで、コマンドを実行しTypeScript: Open TS Server log



    ます。
  5. ファイルが開くはずtsserver.log



    です。


:TSServerログには、パスやソースコードなど、ワークスペースからの情報が含まれている場合があります。Githubに掲載することに疑問がある場合は、私たちに書いてください。情報を非公開で送信できます。



All Articles