大規模な Vue.js プロジェクトの構築と維持のための 10 のベスト プラクティス

大規模な Vue.js プロジェクトの構築と維持のための 10 のベスト プラクティス

これは、大規模なコードベースを持つ Vue プロジェクトに取り組んでいるときに私が開発したベスト プラクティスです。これらのヒントは、保守と共有が容易な、より効率的なコードを開発するのに役立ちます。

今年のフリーランスとしてのキャリアの中で、いくつかの大規模な Vue アプリケーションに取り組む機会がありました。私が話しているプロジェクトには、12 を超える Vuex ストア、多数のコンポーネント (場合によっては数百)、および多数のビュー (ページ) があります。コードを拡張可能にするための興味深いパターンをたくさん発見できたので、私にとっては実にやりがいのある経験でした。また、有名なスパゲッティコード問題につながるいくつかの悪い習慣も修正する必要がありました。

そこで今日は、大規模なコードベースを扱う場合に従うことをお勧めする 10 のベスト プラクティスを紹介します。

1. スロットを使用してコンポーネントを理解しやすくし、より強力にする

ある日、ポップアップを作成する必要がありました。一見すると、特に複雑なことはなく、タイトル、説明、いくつかのボタンがあるだけです。そこで、すべてを属性として扱うことにします。最後に、誰かがボタンをクリックしたときにイベントが発行されるように、3 つのプロパティを使用してコンポーネントをカスタマイズしました。とても簡単です! :汗_笑顔:

しかし、プロジェクトが拡大するにつれて、チームからはフォーム フィールド、さまざまなボタン (表示されるページによって異なります)、カード、フッター、リストなど、他にも多くの新しいものを表示するように依頼されました。このコンポーネントを拡張するためにプロパティを使い続けると、機能することがわかりました。しかし、神様、:weary: 私は間違っていました!コンポーネントは、無数のサブコンポーネントを含み、使用するプロパティが多すぎ、多数のイベントが発行されたため、すぐに複雑になりすぎて理解できなくなりました。 :volcano: どこかに変更を加えると、別のページの他の部分が壊れてしまうというひどい状況に遭遇したことがあります。保守可能なコンポーネントの代わりにフランケンシュタインの怪物を作ってしまいました!

しかし、最初からスロットに頼っていたら、状況はもっと良くなっていたかもしれません。最後に、この小さなコンポーネントを提供するためにすべてをリファクタリングしました。メンテナンスが簡単になり、理解が速くなり、スケーラビリティが大幅に向上しました。

<テンプレート>
  <div class="c-base-popup">
    <div v-if="$slots.header" クラス="c-base-popup__header">
      <スロット名="ヘッダー">
    </div>
    <div v-if="$slots.subheader" クラス="c-base-popup__subheader">
      <スロット名="サブヘッダー">
    </div>
    <div class="c-base-popup__body">
      <h1>{{ タイトル }}</h1>
      <p v-if="description">{{ 説明 }}</p>
    </div>
    <div v-if="$slots.actions" クラス="c-base-popup__actions">
      <スロット名="アクション">
    </div>
    <div v-if="$slots.footer" クラス="c-base-popup__footer">
      <スロット名="フッター">
    </div>
  </div>
</テンプレート>
<スクリプト> エクスポート デフォルト {
  小道具: {
    説明:
      タイプ: 文字列、
      デフォルト: null
    },
    タイトル:
      タイプ: 文字列、
      必須: true
    }
  }
} </スクリプト> 


私が言いたいのは、経験上、スロットをいつ使用するかを知っている開発者が構築したプロジェクトは、将来の保守性に大きな影響を与えるということです。これにより、発行されるイベントの数が減り、コードが理解しやすくなり、内部に必要なコンポーネントをより柔軟に表示できるようになります。

経験則として、子コンポーネントのプロパティを親コンポーネントに複製することになった場合は、その時点からスロットを使用する必要があることに注意してください。

2. Vuexストアを正しく整理する

多くの場合、新しいVue.js開発者がVuex学習を始めるのは、次の 2 つの問題に遭遇するためです。

  • ツリー構造内で物理的に離れすぎている別のコンポーネントから特定のコンポーネントのデータにアクセスする必要がある場合、または
  • コンポーネントの破壊から生き残るためにはデータが必要です。

ここで、最初のVuexストアを作成し、モジュールについて学習し、アプリケーション内でモジュールを整理し始めます。

問題は、モジュールを作成するときに従うべき単一のパターンがないことです。しかし、どのように整理したいかについてはよく考えることを強くお勧めします。私の理解するところによると、ほとんどの開発者は機能別に整理することを好みます。例えば:

  • 検証コード
  • ブログ
  • 受信トレイ
  • 設定

私としては、API から抽出したデータ モデルに従って整理すると理解しやすくなると思います。例えば:

  • ユーザー数
  • チーム
  • メッセージの内容
  • ウィジェット
  • 記事

どれを選ぶかはあなた次第です。心に留めておかなければならない唯一のことは、適切に整理されたVuexストアによって、長期的にはチームの生産性が向上するということです。これにより、新人がチームに参加した直後からコードベースを理解しやすくなります。

3. Vuex Actionsを使用してAPI呼び出しを行い、データを送信する

私の API 呼び出しのほとんどは、 Vuex vuex actionsで実行されます。なぜこの呼び出しの方が良いのか疑問に思うかもしれません。

なぜなら、それらのほとんどは、ストレージ ( vuex store ) に送信する必要があるデータを抽出するからです。さらに、カプセル化と再利用性も提供しており、非常に気に入っています。私がこれをする理由は他にもいくつかあります:

  • 記事のトップページを 2 つの異なる場所 (ブログとトップページなど) で取得する必要がある場合は、正しいパラメータを使用して適切なディスパッチャを呼び出すことができます。データは、スケジューラ呼び出し以外のコードが重複することなく取得、送信、返されます。
  • 最初のページが取得されるときにそれを取得しないようにするためのロジックを作成する必要がある場合は、それを 1 か所で実行できます。サーバーの負荷を軽減するだけでなく、どこでも機能すると確信しています。
  • これらのアクション (vuex アクション) で Mixpanel イベントのほとんどを追跡できるため、分析コードベースの保守が非常に簡単になります。すべての Mixpanel 呼び出しがアクション内で個別に実行されるアプリケーションがいくつかあります。 :joy: 何を追跡し、何を追跡しないか、いつ送信するかを追跡する必要がないので、このように作業するとどれほど楽しいことでしょう。

翻訳注: Mixpanel 、ユーザーが閲覧したページ数、 iPhoneアプリの分析、 Facebookアプリのインタラクション、電子メールの分析など、さまざまなユーザー行動を開発者が追跡できるようにするデータ追跡および分析会社です。 Firebaseに似た使用時点分析ツール。

4. mapState、mapGetters、mapMutations、mapActionを使用してコードベースを簡素化する

通常、コンポーネント内でstate/getterにアクセスしたり、 action/mutationを呼び出したりする必要がある場合は、複数の計算プロパティまたはメソッドを作成する必要はありません。 mapStatemapGettersmapMutationsmapActionsを使用すると、コードを短縮し、グループ化して簡素化し、ストレージ モジュールの全体像を 1 か所で把握できるようになります。

// 非PM
「vuex」から mapState、mapGetters、mapActions、mapMutations をインポートします。
エクスポートデフォルト{
  計算: {
    // ルートプロパティへのアクセス
    ...mapState("my_module", ["プロパティ"]),
    // ゲッターへのアクセス
    ...mapGetters("my_module", ["プロパティ"]),
    // ルート以外のプロパティへのアクセス
    ...mapState("my_module", {
      プロパティ: 状態 => state.object.nested.property
    })
  },
  メソッド: {
    // アクションへのアクセス
    ...mapActions("my_module", ["myAction"]),
    // ミューテーションへのアクセス
    ...mapMutations("my_module", ["myMutation"])
  }
}; 


これらの便利なヘルパーに関する必要な情報はすべて、公式のVuexドキュメントで入手できます。

5. APIファクトリーを使用する

私は通常、API エンドポイントを取得するためにどこからでも呼び出すことができるthis.$apiヘルパーを作成するのが好きです。プロジェクトのルートには、すべてのクラスを含む api フォルダーがあります (以下の 1 つを参照)。

API
├── auth.js
├── 通知.js
└── チーム.js 


各ノードは、そのカテゴリのすべてのエンドポイントをグループ化します。これは、プラグインを使用してNuxtアプリでこのパターンを初期化する方法です (これは、標準の Vue アプリのプロセスと非常によく似ています)。

// プロジェクト: API
"@/api/auth" から Auth をインポートします。
「@/api/teams」からTeamsをインポートします。
「@/api/notifications」から通知をインポートします。
エクスポートデフォルト(コンテキスト、注入)=> {
  プロセスクライアントの場合{
    const トークン = localStorage.getItem("トークン");
    // 定義されたときにトークンを設定する
    if (トークン) {
      context.$axios.setToken(トークン、「ベアラー」);
    }
  }
  // APIリポジトリを初期化する
  const リポジトリ = {
    認証: Auth(context.$axios)、
    チーム: チーム(context.$axios)、
    通知: Notifications(context.$axios)
  };
  inject("api", リポジトリ);
}; 


エクスポートデフォルト$axios => ({
  パスワードを忘れた場合(メールアドレス)
    $axios.$post("/auth/password/forgot", { email }) を返します。
  },
  ログイン(メールアドレス、パスワード) {
    $axios.$post("/auth/login", { メールアドレス、パスワード }); を返します。
  },
  ログアウト() {
    $axios.$get("/auth/logout"); を返します。
  },
  レジスタ(ペイロード) {
    $axios.$post("/auth/register", ペイロード) を返します。
  }
}); 


これで、次のようにコンポーネントまたは Vuex アクションで簡単に呼び出すことができます。

エクスポートデフォルト{
  メソッド: {
    送信() {
      試す {
        this.$api.auth.login(this.email, this.password);
      } キャッチ(エラー){
        コンソールエラー(エラー);
      }
    }
  }
}; 


6. $config を使用して環境変数にアクセスする(特にテンプレートで便利)

おそらく、プロジェクトにはいくつかのファイルで定義されたグローバル構成変数があります。

設定
├── 開発.json
└── production.json 


特にテンプレートを使用している場合は、 this.$configヘルパーを使用してすばやくアクセスするのが好きです。いつものように、Vue オブジェクトの拡張は非常に簡単です。

// 非PM
「vue」からVueをインポートします。
// プロジェクト: コモンズ
「@/config/development.json」から開発をインポートします。
「@/config/production.json」からproductionをインポートします。
process.env.NODE_ENV === "production"の場合{
  Vue.prototype.$config = Object.freeze(production);
} それ以外 {
  Vue.prototype.$config = Object.freeze(開発);
} 

7. コミットコメントを書く際の慣例に従う

プロジェクトが拡大するにつれて、コンポーネントのコミット履歴を定期的に参照する必要が出てきます。チームがコミット メッセージの記述に関して同じ規則に従わない場合、各チーム メンバーが何をしているのか理解するのは難しくなります。

私は常にAngular commitメッセージ ガイドラインを使用し、推奨しています。私は取り組むすべてのプロジェクトでこれに従いますが、多くの場合、他のチームメンバーもこれに従う方が良いことにすぐに気づきます。

これらのガイドラインに従うと、メッセージが読みやすくなり、プロジェクト履歴を確認するときにコミットを追跡しやすくなります。簡単に言うと、仕組みは次のようになります:

git commit -am "<タイプ>(<スコー​​プ>): <件名>"
# ここにいくつかのサンプルがあります
git commit -am "docs(changelog): changelog を beta.5 に更新"
git commit -am "fix(release): 最新の rxjs と zone.js に依存する必要があります" 


規則の詳細については、 READMEファイルを参照してください。

8. プロジェクトを作成するときは常にパッケージのバージョンを固定する

わかっています...すべてのパッケージはセマンティック バージョン管理ルールに従う必要があります。しかし、現実には、そうではないものもあります。 :汗_笑顔:

依存関係の 1 つがプロジェクト全体を壊してしまい、夜中に目が覚めてしまうことを避けるために、すべてのパッケージのバージョンをロックダウンすると、朝のストレスが軽減されます。 :無実の:

意味は簡単です。 ^ で始まるバージョンの使用を避けてください。

{
  "名前": "私のプロジェクト",
  "バージョン": "1.0.0",
  「プライベート」:true、
  「依存関係」: {
    "axios": "0.19.0",
    "imagemin-mozjpeg": "8.0.0",
    "imagemin-pngquant": "8.0.0",
    "imagemin-svgo": "7.0.0",
    "nuxt": "2.8.1",
  },
  「devDependencies」: {
    "自動プレフィックス": "9.6.1",
    "babel-eslint": "10.0.2",
    "eslint": "6.1.0",
    "eslintフレンドリーフォーマッタ": "4.0.1",
    "eslint-loader": "2.2.1",
    "eslint-プラグイン-vue": "5.2.3"
  }
} 

9. 大量のデータを表示するときはVue仮想スクロールバーを使用する

特定のページに多数の行を表示したり、大量のデータをループしたりする必要がある場合、ページが非常に速くレンダリングされることに気付いたかもしれません。この問題を解決するには、 vue-virtual-scollerを使用できます。

npm で vue-virtual-scroller をインストールします 


リスト内の表示されている項目のみをレンダリングし、コンポーネントと DOM 要素を再利用して、可能な限り効率的にします。使い方はとても簡単で、滑らかに塗れます

<テンプレート>
  <リサイクルスクロール
    クラス="スクロール"
    :items="リスト"
    :item-size="32"
    キーフィールド="id"
    v-slot="{アイテム}"
  >
    <div class="ユーザー">
      {{アイテム名}}
    </div>
  </リサイクルスクロール>
</テンプレート> 


10. サードパーティのパッケージのサイズを追跡する

多くの人が同じプロジェクトに取り組んでいる場合、誰も監視していないと、インストールされるパッケージの数はあっという間に信じられないほどの数にまで達する可能性があります。アプリの速度低下を回避するために (特に低速のモバイル ネットワークの場合)、 Visual Studio Codeの import-expense パッケージを使用します。この方法により、インポートしたモジュール ライブラリの大きさをエディターから直接確認でき、インポートしたモジュール ライブラリが大きくなりすぎたときに何が問題になったかを確認できます。

たとえば、最近のプロジェクトでは、lodash ライブラリ全体(縮小すると約 24kB)をインポートしました。問題は、プロジェクトではcloneDeep 1 つのメソッドのみが使用されていることです。輸入経費パッケージでこの問題を特定した後、次の方法で解決しました。

npm 削除 lodash
npm をインストール lodash.clonedeep 


次に、必要な場所に clonedeep 関数をインポートします。

「lodash.clonedeep」から cloneDeep をインポートします。 
JavaScript

さらに最適化するには、 Webpack Bundle Analyzerパッケージを使用して、インタラクティブでズーム可能なツリーマップを通じてWebpack出力ファイルのサイズを視覚化することもできます。

大規模な Vue.js プロジェクトの構築と保守に関する 10 のベスト プラクティスに関するこの記事はこれで終わりです。Vue.js プロジェクトの構築と保守に関するより実践的なコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue.js+boostrapプロジェクト実践(事例詳細説明)
  • Vue.jsでタブ切り替えと色変更操作を実装する解説
  • Vue.js での $emit の使用に関する詳細な説明
  • Vue.js スロットにおけるスコープ付きスロットの使用法の詳細な説明
  • Vue.jsはカレンダー機能を実装します
  • Vue.jsはタイムライン機能を実装します
  • Vue.jsは背景テーブルコンポーネントのカプセル化を管理します
  • Vue.js フロントエンドプロジェクト向け多言語ソリューションのアイデアと実践

<<:  CentOS で yum を使用して rabbitmq-server をインストールする方法

>>:  MySQL 集計関数のネストされた使用操作

推薦する

NodeJSのモジュール性に関する詳細な説明

目次1. はじめに2. 本文2.1 モジュールとは何ですか? 2.2 解決2.3、require.r...

jsを使用してシンプルな弾幕スクリーンシステムを実装する

この記事では、弾幕効果を実現するためのネイティブjsの具体的なコードを参考までに共有します。具体的な...

VScode設定のリモートデバッグLinuxプログラムの問題を解決する

VScode リモートデバッグ Linux プログラムの問題について見てみましょう。具体的な内容は以...

Vue で debouce の手ぶれ補正機能を使用する方法

目次1. 手ぶれ補正機能2. Vueでdebouceの手ぶれ補正機能を使用する1. 手ぶれ補正機能2...

Vue-router は現在の場所 (/path) へのナビゲーションを許可しません。エラーの原因と修正

目次エラーメッセージ原因エラーのデモンストレーション回避策方法1方法2方法3エラーメッセージ現在の場...

MySQLデータベースの管理者パスワードを忘れた場合の解決策

1. コマンド mysqld --skip-grant-tables を入力します (前提条件: m...

CSS で要素を中央揃えにする N 通りの方法

目次序文インライン要素の中央揃えテキストを垂直に中央揃え要素を水平方向に中央揃えにするブロックレベル...

IDEA が Docker を統合してリモート展開を実現するための手順

1. Dockerサーバーへのリモートアクセスを有効にするdocker が配置されているリモート サ...

MySQL ログの設定と表示方法

MySQL には次のログがあります。エラーログ: -log-errクエリログ: -logスロークエリ...

JS でオブジェクト プロパティを簡単にトラバースするいくつかの方法

目次1. 自己列挙可能なプロパティ2. Object.values()はプロパティ値を返します3. ...

Dockerでパラメータ変数を外部から指定する方法

この記事は主にDockerでパラメータ変数を外部から指定する方法を紹介します。この記事のサンプルコー...

IframeとFRAMEの違いの分析

1. Iframe タグの使用<br />Iframe については、「忘れられた隅」に放...

Web プロジェクト開発 VUE の混合と継承の原則

目次ミキシンMixin ノート (重複名)ローカルミックスイングローバル ミックスイン定義とグローバ...

MySQL と Golan 間の従来の分散トランザクションのための 7 つのソリューション

目次1. 基本理論1.1 取引1.2 分散トランザクション2. 分散トランザクションソリューション2...

Nginx の add_header ディレクティブに注意する必要があるのはなぜですか?

序文ご存知のとおり、nginx 構成ファイルは add_header ディレクティブを使用して応答ヘ...