1. 背景紹介1.1. 事業紹介プラットフォームAとプラットフォームBは同じシステムチェーンに属しています。前者は主にユーザー登録とオンボーディングサービスの提供に特化し、後者は特定の業務運用サービスの提供に重点を置いています。どちらも運用担当者が頼りにするオンライン管理ツールです。 1.2.現状分析現在、両方のプラットフォームは同じビジネスに利用されており、アプリケーションBのページはアプリケーションAのプラットフォームに完全に組み込まれています。これに加えて、システム機能とユーザーエクスペリエンスの面で、以下の問題点があります。 そこで当時、同じビジネスにサービスを提供していたため、2 つのプラットフォームをコード レベルで統合して、ユーザー エクスペリエンスを最適化し、コストを削減して効率を向上できるかどうかを検討しました。 2.結果発表プラットフォーム統合後、主な最適化は次の 4 つの側面に反映されます。 最適化前(単一ページにリダイレクトするときに空白画面が表示される時間は約 2998 ミリ秒でした): 最適化後(単一ページにリダイレクトするときの白い画面の時間は約 800 ミリ秒です): 3. 具体的な対策3.1. スキーム調査3.1.1.展開方法•デプロイメントの最適化: アプリケーション A のフロントエンドとバックエンドは現在一緒にデプロイされていますが、フロントエンドを分離して独立してデプロイする予定です。 •リソースの節約: Xingyun デプロイメント プラットフォームの研究に基づいて、アプリケーション A とアプリケーション B の静的なフロントエンド リソースをコンテナのグループに集中的にデプロイし、リソースの使用率を最適化するハイブリッド デプロイメント戦略を提案します。 3.1.2. コードリポジトリの統合•アプリケーション A の 3 つのプロジェクトは、統一されたコーディング標準を使用して、バックエンドと単一のコード リポジトリを共有します。一方、アプリケーション B は別のコード リポジトリを使用します。フロントエンド コードをそこから分離する必要があり、分離プロセスが既存の構成に影響を与えないようにする必要があります。3.1.3. プロジェクトのフレームワーク• 4 つのプロジェクトはすべて、依存関係に若干の違いはあるものの、テクノロジー フレームワークとして Vue 2 を使用しています。3.1.3. システム権限•アプリケーション A と B は ERP ログイン用です。3.2. アーキテクチャ設計シームレスなユーザーエクスペリエンスを確保するため、両プラットフォームのユーザーは引き続きそれぞれのドメインを使用してサイトにアクセスします。統合されたプロジェクトは現在の環境を自動的に認識し、対応するコンテンツを読み込むため、ユーザーは統合前と統合後で同じコンテンツを閲覧できます。 3.3. 具体的な計画3.3.1.ディレクトリ構造の設計統合に関しては、ファイルの競合を防止し、統合の複雑さを軽減し、統合後に問題が発生する可能性を低減することを最優先に考慮しています。両システムの正常な動作を確保することが最優先事項です。論理分解には、以下の3つの側面が含まれます。 1.ファイルの分割と分類2つのシステムには数十のファイルが含まれています。分析の結果、以下の部分に分解しました。[ページファイル、共通コンポーネントファイル、モックファイル、AxPIインターフェースファイル、基本リクエストカプセル化ファイル、ルートコンポーネントファイル、ストアファイル、共通スタイルファイル、共通メソッドコンポーネント、mainjsファイル、index.htmlファイル] 2. 構造的統合と差別化 2つのプロジェクトは構造が似ているため、セクションごとに統合できます。全体的なアプローチとしては、システムA用とシステムB用に、それぞれ大きな違いのあるファイル用のフォルダを2つ作成します。そして、インデックスファイルを使用して、現在のランタイム環境がシステムAかシステムBかを識別し、対応するコンテンツをロードします。 3. コンテンツの統合と競合解決 差異が小さい、または差異がないファイルについては、内容を統合しました。競合するコンテンツは手動で修正し、グローバル参照もそれに応じて更新しました。 ├── ルート │ ├── モック │ ├── 公開 │ ├── ソース │ │ ├── アピ │ │ │ ├── apiA // A業務のリクエストインターフェースを格納 │ │ │ ├── apiB // B業務のリクエストインターフェースを格納 │ │ │ ├── apiC // C業務のリクエストインターフェースを格納 │ │ │ ├── baseHttp.js // 基本的なリクエストをカプセル化 │ │ │ ├── ARequest.js // A業務の共通処理。リクエストヘッダーやレスポンスコードの処理など。 │ │ │ ├── BRequest.js // B業務の共通処理。リクエストヘッダーやレスポンスコードの処理など。 │ │ │ ├── CRequest.js // C業務の共通処理。リクエストヘッダーやレスポンスコードの処理など。 │ │ │ ├── DRequest.js // D業務の共通処理。リクエストヘッダーやレスポンスコードの処理など。 │ │ ├── assets │ │ │ ├── アイコン // アイコンコンテンツ│ │ ├── 共通 │ │ │ ├── 設定 │ │ │ ├── styles // 共通スタイル │ │ ├── components // 共通コンポーネント │ │ ├── directive // カスタムディレクティブ │ │ ├── layout // 共通レイアウト │ │ ├── router │ │ │ ├── a.js // アプリケーション 'a' に対応 │ │ │ ├── b.js // アプリケーション 'b' に対応 │ │ │ ├── c.js // アプリケーション 'c' に対応 │ │ │ ├── index.js │ │ ├── ストア │ │ │ ├── モジュール │ │ │ ├── getters.js │ │ │ ├── index.js │ │ ├── ユーティリティ │ │ ├── ビュー │ │ │ ├── a // a 業務ファイル │ │ │ ├── b // b 業務ファイル │ │ │ ├── c // c 業務ファイル │ │ ├── main.js │ │ └── App.vue │ ├── 環境 │ ├── package.json 3.3.2. アプリケーションタイプの判断アプリケーション種別の識別は、私たちのプロセスにおいて非常に重要な部分であり、環境認識の基盤となります。ユーザーが異なるドメインからアプリケーションにアクセスすると、フロントエンドは異なるドメインが複数のアプリケーションに対応するマッピングテーブルを保持します。main.js ファイルは、この識別と判断のプロセスを可能な限り迅速に実行します。 let APPLICATION_TYPE = 'a' let host = window.location.host; // テスト環境と本番環境を含むドメイン名のリストを管理する const A_HOST = ['a.com', 'a_pre.com'] const B_HOST = [] const C_HOST = [] const D_HOST = [] if(A_HOST.includes(host)){
APPLICATION_TYPE = 'a'}else if(B_HOST.includes(host)){
APPLICATION_TYPE = 'b'}else if(C_HOST.includes(host)){
APPLICATION_TYPE = 'c'}else if(D_HOST.includes(host)){
APPLICATION_TYPE = 'd'} // グローバルウィンドウをマウントします。_APPLICATION_TYPE = APPLICATION_TYPE3.3.3. ルーティング設計異なるドメイン名に基づいてルート設定を取得し、ルート設定に基づいてルートを生成します。システム A とシステム B はそれぞれルート リストを保持します。バックエンドからルート構造が返された後、異なるアプリケーションに応じて異なるファイルの内容がマッピングされます。ルート パスは変更されず、コンポーネントの前にプレフィックス (アプリケーション カテゴリ) が付けられ、アプリケーションの下の対応するコンポーネントが検索されます。 •ステップ 1: フロントエンドは現在のドメイン名を取得し、現在のアプリケーションを確認します。グローバル APPLICATION_TYPE フィールドに基づいて識別します。•ステップ2: フロントエンドはルートリストを管理する ルーター=[{
パス: '/home',
コンポーネント: レイアウト、
meta: { title: 'ホーム', icon: 'el-icon-s-grid', alwaysShow: true },
リダイレクト: '/home',
子供たち: [
{
パス: '/home',
コンポーネント: () => import('@/views/home/index'),
名前: 'home',
meta: { title: 'ホームページ', icon: ''}
}
]
}] •ステップ 3: 現在のアプリケーションのバックエンド インターフェイスへの要求に基づいて、ルーティング構成情報を取得します (コンポーネントのパスの先頭に各アプリケーションのファイル名が付加されます)。 RouterApi = {'a':'/api1','b':'/api2','c':'api3'} とします。api.get(RouterApi[APPLICATION_TYPE]) component = 'アプリケーション ファイル名' + API 戻りパス。 •ステップ 4: ルーティング情報がフロントエンドに配置されるアプリケーションの場合、フロントエンドはルーティング構成情報テーブルを維持します。 './d.json' から dRouter をインポートします (APPLICATION_TYPE==='d' の場合){
ルーター=dRouter} •ステップ 5: ルート構成情報に基づいてルート構造を生成します。 •ステップ 6: Vue オブジェクトをインスタンス化します。3.3.4. 環境変数の設計環境は主に、モック環境、ローカル開発環境、テスト環境、本番環境の種類に分けられます。 環境によって必要な変数ファイルは異なります。各エンドポイントに必要なパラメータは変数ファイルに設定され、APPLICATION_TYPEと変数ファイル内の設定を組み合わせることで、対応するパラメータが取得されます。 例: # .env.pruduction # a ビジネス VUE_APP_A_BASEURL = '' # b ビジネス VUE_APP_B_BASEURL = '' # c ビジネス VUE_APP_C_BASEURL = '' # d ビジネス VUE_APP_D_BASEURL = '' 3.3.5. 設計依頼1.共通リクエストのカプセル化基本的な共通リクエストはcreateHttp.jsにカプセル化されています。各ビジネスロジックは、共通リクエストと独自のコード、リクエストパラメータ、その他の情報をさらにカプセル化し、ビジネスニーズに応じて呼び出すことができます。 •基本的なリクエスト: createHttp.js •一般的なビジネスロジックのカプセル化:a. ARequest.js (ビジネスロジックAの共通パラメータとコードの処理) b. BRequest.js (Bビジネスロジックの共通パラメータとコードの処理) c. CRequest.js (Cビジネス共通パラメータとコード処理) d. DRequest.js (一般的なビジネスパラメータとコードの処理) •ビジネス層の呼び出し:a. API/APIA ビジネスインターフェース b. API/APIBビジネスインターフェース c. API/APIC Cビジネスインターフェース // 共通リクエストラッパー baseHttp.js export const createHttp = (baseUrl, successFun = () => {}, errorFun = () => {}, requestInterceptor = () => {}) => {
定数 http = axios.create({
ベースURL: ベースURL、
タイムアウト: 5 * 60 * 1000,
資格情報付き: true
})
// http リクエストインターセプター http.interceptors.request.use(
非同期設定 => {
requestInterceptor(config) を待機します。
設定を返す},
エラー => {
Promise.reject(err) を返す
}
)
// http レスポンス インターセプター http.interceptors.response.use(successFun, errorFun)
httpを返す}2. バックエンドサービスリクエストのカプセル化を直接呼び出す //ビジネスの基本リクエスト関数 requestInterceptor(){
// システムA共通リクエストパラメータ処理... }function successFn(){
// システムA共通応答結果処理統合加算 }function errorFn(){
// Aはコード関連ケースを含む一般的な例外を処理します。 } export default createHttp(baseUrl, successFn, errorFn, requestinterceptor)3. ビジネス インターフェイスの使用: さまざまなビジネス ニーズに応じて、異なるディレクトリ ブランチに分割します。 // ビジネスリクエストAはARequest.get(url,{params:data})を呼び出します//ビジネスリクエストBはBRequest.post(url,{params:data})を呼び出します3.3.6. 権限とログインAPPLICATION_TYPE フィールドに基づいて、異なる環境が識別され、異なるサーバー インターフェイスが要求されます。異なるサーバーは異なるアプリケーションを表します。 ユーザーがログインしていないさまざまなアプリケーションの場合、フロントエンドは複数のログイン処理ロジックのセットを維持し、アプリケーションの種類に応じて異なる処理ロジックを実行します。 3.3.7. 共通機能の設計共通の utils フォルダーを作成し、2 つのプロジェクトの共通関数をマージし、競合する関数の名前を変更し、グローバルにインポートされた部分のパスと関数を同期します。 3.3.8. 足場構成設計2つのプロジェクト間の足場構成の違いと、それぞれの構成の機能を特定しました。プロジェクトの通常の運用に影響を与えることなく、元の機能が確実に満たされるよう、構成にいくつかの修正と最適化が行われました。 3.3.9. Vuexストアのデザインストアの全体的な構造は変更されず、プロジェクト内で参照されるアドレスも変更されません。ストアはプロジェクト内の多くの場所で使用されているため、構造を変更しないことで変更コストを最小限に抑えることができます。2つのプロジェクトでモジュール名が重複している場合は、モジュールの内容を手動でマージします。 名前が同じだが内容が異なる既存の関数については、APPLICATION_TYPE フィールドに基づいて 2 つの関数を結合し、個別に処理します。 3.3.10. ページ参照デザイン•引用方法の変更ビジネス要件により、アプリケーションAは、以前はiframe経由で参照されていたアプリケーションBのページを埋め込んでいます。統合後、ページファイルとコンポーネントは分離されなくなり、アプリケーションBのファイルとコンポーネントを直接インポートできるようになります。 •バックエンドデータ統合アプリケーションAのバックエンドサーバーには、ダウンロードリストなどの機能があります。アプリケーションBはこれらの機能を使用する必要がありますが、データの非互換性のため直接参照できません。フロントエンド統合後、アプリケーションBはアプリケーションAのページコンポーネントを直接参照できるようになり、シームレスなビジネスロジックを実現できます。その結果、以下のようになります。 4. まとめ2ヶ月にわたる集中的な作業を経て、2つの大規模プロジェクトの統合に成功し、大きな進展を遂げました。この統合プロセスは、プロジェクトのコード標準とアーキテクチャを統一しただけでなく、コンポーネントの再利用性を大幅に向上させることにもつながりました。その過程では数々の課題や挫折に直面しましたが、最終的な成果であるユーザーエクスペリエンスの大幅な向上は、私たちの努力を報うものでした。 あらゆるプロジェクトの成功の裏には、数え切れないほどの試行錯誤と最適化が隠されていることを私たちは理解しています。このプロセスを通して、私たちは継続的に学び、適応し、改善を重ね、最終的にシームレスなプロジェクト統合を実現しました。この経験と成果は、私たちのチームにとって貴重な教訓となっただけでなく、同様の課題に直面している方々にもインスピレーションと支援を提供できると信じています。 |