ホームページ ウェブフロントエンド jsチュートリアル Chrome 拡張機能の開発 - TypeScript、React、Tailwind CSS、Webpack を使用して最小限のアプリを開発します

Chrome 拡張機能の開発 - TypeScript、React、Tailwind CSS、Webpack を使用して最小限のアプリを開発します

Dec 29, 2024 am 02:26 AM

導入

このブログでは、TypeScript、React、Tailwind CSS、Webpack を使用して Chrome 拡張機能をセットアップおよび開発する方法を説明します。私たちの理解をテストするために、「NoteMe」✍️ という最小限の拡張機能を作成します。私たちの拡張機能には次の機能が含まれます:

  • ユーザーが特定の Web サイトに複数のメモを追加できるようにします
  • ユーザーが特定の Web サイトの保存されたメモを表示できるようにします
  • 特定の Web サイトのメモを削除するオプションを提供します
  • メモをブラウザのストレージにローカルに保存します
  • オプションでメモをクラウド ストレージのバックエンドと同期します

おさらい

このブログでは、最新のテクノロジーを使用して Chrome 拡張機能を構築する方法を学びます。このガイドは、ローカル開発中に拡張機能を構築して Chrome にアップロードする方法にすでにある程度慣れていることを前提としています。これを初めて使用する場合、または基本の詳細なウォークスルーが必要な場合は、私の以前のブログをチェックすることをお勧めします: Link

拡張機能のスニークピーク

拡張機能には次のコンポーネントが含まれます:

  • トグルボタン: サイドバーを開閉するボタンです。
  • サイドバー: ユーザーが次のことができる多用途パネルです。 新しいメモを書きます。 保存されたメモを表示します。 保存したメモを削除します。 ノートをバックエンドと同期します (コード内で利用可能なプロビジョニングが可能ですが、現在バックエンドは接続されていません)。
  • ポップアップ: ユーザーがトグル ボタン (サイドバーの開閉に使用) を画面上の事前に指定した位置に再配置できるようにする小さなウィンドウ : この実装にはバックエンドの統合はありませんが、コードには将来バックエンドを接続するための規定が含まれています。

以下は、拡張機能が完了したときにどのように表示されるかを示すスクリーンショットです:

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

前提条件

このチュートリアルに入る前に、次のツールがシステムにインストールされていることを確認してください:

  • Node.js (v18.16 LTS 以降)
  • NPM (ノード パッケージ マネージャー、Node.js にバンドルされています)
  • TypeScript
  • ウェブパック
  • VS コード エディタ (または任意のコード エディタ)

40,000フィートからの延長

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

上の図は、この拡張機能の内部動作の概要を示しています。この図から導き出せるいくつかの重要なポイントを次に示します:

  • コンテンツ スクリプトは、親 Web ページの DOM と直接対話し、ページのコンテンツを変更できるようにします。
  • ポップアップバックグラウンド、およびコンテンツ スクリプトは、Chrome のランタイム メッセージング システムを通じて相互に通信します。
  • Chrome ストレージまたはバックエンド API 呼び出しに関連するタスクの場合、コンテンツ または ポップアップ スクリプト は、ランタイム メッセージング システムを使用して バックグラウンド ワーカー に責任を委任します。
  • バックグラウンド スクリプトは、アプリのバックエンドと Chrome のストレージとの唯一の仲介者として機能します。また、通知がある場合は、ランタイム メッセージングを使用して他のスクリプトに通知を中継します。
  • ポップアップコンテンツ スクリプト は、Chrome のランタイム メッセージング システムを通じて直接情報を交換します。

拡張機能のセットアップ

Chrome 拡張機能プロジェクトでは特定のプロジェクト構造は必須ではありませんが、manifest.json ファイルがビルド ディレクトリのルートに配置される必要があります。この柔軟性を利用して、さまざまなスクリプトを効果的に整理するのに役立つカスタム プロジェクト構造を定義します。この構造により、スクリプト間でのコードの再利用が向上し、重複が最小限に抑えられ、開発プロセスが合理化されます。

ステップ 1: プロジェクトの基本ディレクトリ構造を作成する

まず、プロジェクトの基本的なディレクトリ構造をセットアップします。次の bash スクリプトを使用して、manifest.json ファイルとともに基本構造を作成できます。

#!/bin/bash

bash_script_absolute_path=$(pwd)
declare public_paths=("public" "public/assets" "public/assets/images")
declare source_paths=("src" "src/lib" "src/scripts" "src/scripts/background" "src/scripts/content" "src/scripts/injected" "src/scripts/popup" "src/styles")
declare public_directory_path="public"
declare manifest_file="manifest.json"
declare project_name="note-me"

create_directory () {
    if [ ! -d "" ]; then
        mkdir 
    fi
}

create_file () {
    if [ ! -e "/" ]; then
        touch /
    fi
}

create_public_directories () {
    for public_path in "${public_paths[@]}";
    do
        create_directory $public_path
    done
}

create_source_directories () {
    for source_path in "${source_paths[@]}";
    do
        create_directory $source_path
    done
}

execute () {
    echo "creating project struture at "${bash_script_absolute_path}
    create_directory $project_name
    cd $bash_script_absolute_path"/"$project_name
    create_public_directories
    create_source_directories
    create_file $manifest_file $public_directory_path
    echo "done creating project struture at "${bash_script_absolute_path}" with project name "$project_name
}

execute
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ディレクトリ構造が以下のスクリーンショットに示されているものと似ていることを確認してください。

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

ステップ 2: パブリック ディレクトリにある manifest.json ファイルは、以下に示すように構造化されている必要があります。

{
    "manifest_version": 3,
    "name": "NoteMe",
    "version": "1.0",
    "description": "A Chrome extension built with React and TypeScript using Webpack.",
    "action": {
      "default_popup": "popup.html",
      "default_icon": "app-icon.png"
    },
    "background": {
      "service_worker": "background.js",
      "type": "module"
    },
    "content_scripts": [
      {
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_end"
      }
    ],
    "permissions": [
      "storage",
      "activeTab",
      "scripting",
      "webNavigation"
    ],
    "host_permissions": ["<all_urls>"],
    "web_accessible_resources": [
      {
        "resources": ["styles.css", "sidebar-open.png", "sidebar-close.png"],
        "matches": ["<all_urls>"]
      }
    ]
  }
ログイン後にコピー
ログイン後にコピー

注意事項:

  • .ts ファイルは .js ファイルにコンパイルされるため、ファイル拡張子は .js になります。これは、Chrome 環境での実行時に必要となります。
  • 一致フィールドは を使用します。その値を値として指定すると、拡張機能が Chrome に読み込まれた任意の Web ページで動作できるようになります。
  • app-icon.png、sidebar-open.png、sidebar-close.png の 3 つの画像ファイルが参照されています。これらのファイルは、このブログの最後にリンクされているリポジトリにあります。
  • プロジェクトのビルド後、manifest.json ファイルは dist ディレクトリのルート レベルに配置する必要があります。これを確実に行うには、ビルド プロセス中に適切に移動するように Webpack 設定を構成する必要があります。

ステップ 3: npm を初期化し、依存関係をインストールする

  • まず、次のコマンドを使用してプロジェクト内の npm を初期化します: npm init -y
  • 必要な開発依存関係をプロジェクトの devDependency セクションに追加します。次のコマンドを実行します。 npm i --save-dev @types/chrome @types/react @types/react-dom autoprefixer copy-webpack-plugin css-loader mini-css-extract-plugin postcss postcss-loader style-loader tailwindcss ts-loader typescript webpack webpack-cli webpack-dev-server
  • プロジェクトの実行に必要なランタイム依存関係を追加します。 npm i --save 反応反応-dom

ステップ 4:manifest.json で参照されるファイルを作成する

manifest.json で参照される次のファイルを作成します: backgroun.ts、content.ts、popup.html。

  • background.ts: このファイルを src/scripts/background ディレクトリに作成します
  • content.ts: このファイルを src/scripts/content ディレクトリに作成します
  • Popup.html このファイルをパブリック ディレクトリに作成します

ステップ 5: ポップアップと背景のコードを更新する

パブリック ディレクトリの Popup.html ファイルに次のコードを追加します。

#!/bin/bash

bash_script_absolute_path=$(pwd)
declare public_paths=("public" "public/assets" "public/assets/images")
declare source_paths=("src" "src/lib" "src/scripts" "src/scripts/background" "src/scripts/content" "src/scripts/injected" "src/scripts/popup" "src/styles")
declare public_directory_path="public"
declare manifest_file="manifest.json"
declare project_name="note-me"

create_directory () {
    if [ ! -d "" ]; then
        mkdir 
    fi
}

create_file () {
    if [ ! -e "/" ]; then
        touch /
    fi
}

create_public_directories () {
    for public_path in "${public_paths[@]}";
    do
        create_directory $public_path
    done
}

create_source_directories () {
    for source_path in "${source_paths[@]}";
    do
        create_directory $source_path
    done
}

execute () {
    echo "creating project struture at "${bash_script_absolute_path}
    create_directory $project_name
    cd $bash_script_absolute_path"/"$project_name
    create_public_directories
    create_source_directories
    create_file $manifest_file $public_directory_path
    echo "done creating project struture at "${bash_script_absolute_path}" with project name "$project_name
}

execute
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

注:

上記のコードは 2 つのリスナーをインストールします:

  1. chrome.runtime.onInstalled.addListener によって登録された関数は、拡張機能がブラウザにインストールされるたびに実行されます。これを使用して、Chrome ストレージまたはバックエンド (該当する場合) を事前定義された状態で初期化できます。
  2. chrome.runtime.onMessage.addListener によって登録された関数は、バックグラウンド スクリプトがコンテンツまたはポップアップ スクリプトからメッセージを受信するたびに実行されます。

さらに、import ステートメントは src/lib ディレクトリからリスナーを取り込みます。アプリのコア ロジックは src/lib に構築されており、さまざまなコンテキスト (コンテンツやバックグラウンド スクリプトなど) での再利用が可能です。

ステップ 6: src/lib ディレクトリのチュートリアル

src/lib ディレクトリには、拡張機能のコア ロジックが格納されています。以下はその構造と主要コンポーネントの概要です:

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

  • コンポーネントディレクトリ: 拡張機能で使用されるすべての React コンポーネントが含まれています。
  • lib/components/ContentApp.tsx: コンテンツ スクリプトのコンテナ コンポーネントとして機能します。
  • lib/components/NoteMePosition.tsx: ポップアップ スクリプトを担当するコンポーネントが含まれています。
  • helpers.ts: 拡張機能全体で使用されるヘルパー関数が含まれています。
  • ストレージモデル.ts: Chrome のローカル ストレージとのやり取りを管理します。保存されるデータの構造の詳細については、types.ts.
  • とともにこのファイルを参照してください。
  • types.ts: 拡張機能で使用されるカスタム タイプを定義します。
  • worker.ts: バックグラウンド イベント リスナーのコールバックが含まれます。

詳細な実装については、リポジトリ内の実際のコードを参照してください。

ステップ 7: React コンポーネントのマウント

このステップでは、レンダリング用に React コンポーネントをマウントします。これらのコンポーネントは、src/scripts/content/content.ts と src/scripts/popup/popup.ts の 2 つの異なるスクリプトにマウントされます。

ポップアップ スクリプト: src/scripts/popup/popup.ts にあります。

#!/bin/bash

bash_script_absolute_path=$(pwd)
declare public_paths=("public" "public/assets" "public/assets/images")
declare source_paths=("src" "src/lib" "src/scripts" "src/scripts/background" "src/scripts/content" "src/scripts/injected" "src/scripts/popup" "src/styles")
declare public_directory_path="public"
declare manifest_file="manifest.json"
declare project_name="note-me"

create_directory () {
    if [ ! -d "" ]; then
        mkdir 
    fi
}

create_file () {
    if [ ! -e "/" ]; then
        touch /
    fi
}

create_public_directories () {
    for public_path in "${public_paths[@]}";
    do
        create_directory $public_path
    done
}

create_source_directories () {
    for source_path in "${source_paths[@]}";
    do
        create_directory $source_path
    done
}

execute () {
    echo "creating project struture at "${bash_script_absolute_path}
    create_directory $project_name
    cd $bash_script_absolute_path"/"$project_name
    create_public_directories
    create_source_directories
    create_file $manifest_file $public_directory_path
    echo "done creating project struture at "${bash_script_absolute_path}" with project name "$project_name
}

execute
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

コンテンツ スクリプト: src/scripts/content/content.ts にあります。

{
    "manifest_version": 3,
    "name": "NoteMe",
    "version": "1.0",
    "description": "A Chrome extension built with React and TypeScript using Webpack.",
    "action": {
      "default_popup": "popup.html",
      "default_icon": "app-icon.png"
    },
    "background": {
      "service_worker": "background.js",
      "type": "module"
    },
    "content_scripts": [
      {
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_end"
      }
    ],
    "permissions": [
      "storage",
      "activeTab",
      "scripting",
      "webNavigation"
    ],
    "host_permissions": ["<all_urls>"],
    "web_accessible_resources": [
      {
        "resources": ["styles.css", "sidebar-open.png", "sidebar-close.png"],
        "matches": ["<all_urls>"]
      }
    ]
  }
ログイン後にコピー
ログイン後にコピー
重要なポイント:
  • 個別のマウント スクリプト: ポップアップ スクリプトとコンテンツ スクリプトは異なるコンテキストで動作します
  • ポップアップ スクリプト: ロードされる Popup.html Web ページのコンテキスト内で実行されます。  
  • コンテンツ スクリプト: ブラウザにロードされたメイン Web ページのコンテキスト内で実行されます。
  • コンテンツ スクリプトのシャドウ DOM:  
    • コンテンツ スクリプトによって挿入されたスタイルは、親 Web ページの外観に影響を与える可能性があります。  
    • これを防ぐために、Shadow DOM を使用してスタイルをカプセル化し、拡張機能内でスタイルが分離されたままになるようにします。  
    • ポップアップ スクリプトは独自の隔離された環境 (popup.html) で動作するため、これは必要ありません。

ステップ 8: コンパイルとビルドのための構成

拡張機能のコンパイルとビルドに必要な構成の追加

拡張機能を正常にコンパイルしてビルドするには、次のファイルを構成する必要があります:

  1. postcss.config.js
  2. tailwind.config.js
  3. tsconfig.json
  4. webpack.config.js

重要なポイント:

  • デフォルト設定: プロセスを簡素化し、完全に機能する拡張機能の構築という主な目標に集中できるように、可能な限りデフォルト設定が提供されています。
  • リポジトリの詳細: これらのファイルの完全な構成と詳細な設定については、コード リポジトリを参照してください。

これらの構成は、TypeScript のコンパイル、Tailwind CSS 統合、および拡張機能の Webpack ビルド プロセス全体を処理します。

拡張機能のテスト

  1. dist ディレクトリを生成します: 次のコマンドを実行して dist ディレクトリを作成します: npm run build
  2. Chrome にアップロード:    
    • Chrome を開き、chrome://extensions/ に移動します。    
    • 右上隅にある開発者モードを有効にします。    
    • Load Unpacked をクリックし、dist ディレクトリを選択します。
  3. インストールの確認:
    • ロードされると、デフォルトで拡張機能のアイコンが各ページの右下隅に表示されます。
  4. 機能チェック:
    • 位置コントロール: ポップアップ内のコントロールを使用して、アイコンの位置を変更します。
    • メモ機能: メモは Web サイトごとに個別に保存され、他のサイトに影響を与えることなく特定のサイトについて削除できます。
  5. バックエンド シミュレーション:
    • 現在バックエンドは接続されていませんが、コードにはバックエンドと統合するための規定が含まれています。
    • 現在の実装は、setTimeout を使用してバックエンド接続を模倣し、非同期対話をシミュレートすることを約束します。

拡張機能のテスト中にキャプチャされたスクリーンショットをいくつか示します。

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

Chrome Extension Development - Develop minimal app with TypeScript, React, Tailwind CSS and Webpack

重要なポイント

このブログから重要なポイントをいくつか紹介します。

  • コンテンツ スクリプト、ポップアップ スクリプト、バックグラウンド ワーカーなど、Chrome 環境のさまざまなコンポーネントが Chrome のランタイム メッセージング システムを使用してどのように相互に通信するかを調査しました。
  • プロジェクト構造のセットアップ、依存関係のインストール、コア機能の作成など、Chrome 拡張機能を最初から構成して構築する方法を学びました。
  • 次のようないくつかの優れた実践方法を発見しました。
    • 保守性とスケーラビリティのために、スクリプト間でのコードの再利用性を強化します。
    • コンテンツ スクリプトで Shadow DOM を利用して、親 Web ページとのスタイルの競合を防ぎます。

先を垣間見る

将来的には、完全に機能する Chrome 拡張機能を Chrome ウェブストアに公開するプロセスを調査する別のブログに取り組む予定です。このブログの目標は次のとおりです:

  • 現実世界の問題を解決するのに十分な拡張機能複合体を開発します。
  • 拡張機能を Chrome ウェブストアに公開する手順を段階的に説明します。

このブログを読んでいただきありがとうございます!あなたの関心とサポートは私にとってとても意味があります。この旅を続ける中で、さらに多くの洞察を共有できることを楽しみにしています。

コーディングを楽しんでください!

github リンク: https://github.com/gauravnadkarni/chrome-extension-starter-app

この記事はもともと Medium に公開されたものです。

以上がChrome 拡張機能の開発 - TypeScript、React、Tailwind CSS、Webpack を使用して最小限のアプリを開発しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JavaScriptエンジン:実装の比較 JavaScriptエンジン:実装の比較 Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへ:すべてがどのように機能するか C/CからJavaScriptへ:すべてがどのように機能するか Apr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptとWeb:コア機能とユースケース JavaScriptとWeb:コア機能とユースケース Apr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScript in Action:実際の例とプロジェクト JavaScript in Action:実際の例とプロジェクト Apr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンの理解:実装の詳細 JavaScriptエンジンの理解:実装の詳細 Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:コミュニティ、ライブラリ、リソース Python vs. JavaScript:コミュニティ、ライブラリ、リソース Apr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

Python vs. JavaScript:開発環境とツール Python vs. JavaScript:開発環境とツール Apr 26, 2025 am 12:09 AM

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

See all articles