Nodejs アプリケーションのコンパイルと構築を高速化するための提案

ChatGPT は 160 日間急騰しており、世界はもはや以前のような状態ではありません。

新しい人工知能中国語 Web サイトhttps://ai.weoknow.com では、
中国で利用可能な chatGPT リソースが毎日更新されます


コンパイルとビルドの全体的なプロセス

  1. コンパイルされたイメージをプルします

  2. キャッシュイメージをプルする

  3. プロジェクトのソースコードをプルする

  4. キャッシュディレクトリをマウントする

  5. コンパイルコマンドの実行(ユーザー定義)

  6. 永続的なキャッシュ

  7. コンパイルした画像をアップロードする

ローカルでのビルドは速いのに、コンパイル マシンでは非常に遅いのはなぜですか

編集マシン上の各ビルド環境はまったく新しいもので、ビルドを完了するにはローカルの場合よりもいくつかの手順が必要です。

  1. 既製のグローバル パッケージ キャッシュ VS 再構築キャッシュ: npm を使用すると、単純にグローバル キャッシュ ディレクトリとして理解できます。エディターは、キャッシュのダウンロード、マウント、再構築を含む永続的なキャッシュ環境を準備する必要があります。サイズが大きすぎると、時間が比較的長くなり、ローカル ビルドでは安定したローカル ファイル システムが直接使用されます。

  2. 増分インストールの依存関係 VS 完全インストールの依存関係: インストールのプロセスは、ローカルで必要になることはあまりありません。必要な場合でも、node_modules ディレクトリが永続的に存在するため、完全にインストールする必要はありませんが、エディタ環境では、必要なものすべてを再インストールする必要があります。このプロジェクトは毎回頼ってます。

  3. インクリメンタル ビルド VS フル ビルド: ローカル ビルドでは、デフォルトでビルド キャッシュが node_modules ディレクトリに配置され、これらのビルドは 2 番目のビルド中に使用できるため、後続のビルドが高速になりますが、このビルドのデフォルトのキャッシュの場所は編集されません。つまり、毎回完全にビルドする必要があります。

  4. ネットワーク環境:依存パッケージのインストールには外部ネットワークや海外ネットワークを利用するものもありますが、ローカルネットワーク環境は比較的スムーズですが、編集機のネットワークは海外ネットワークへのアクセスを保証するものではありません。

  5. 活用するのが難しい利点: マルチコアの大容量メモリ、nodejs プロジェクトの構築における作業のほとんどが 1 つのスレッドで実行される、コンパイラのマルチコアの利点を直接使用するのは簡単ではない

  6. 追加の手順: コンパイラーはイメージをダウンロードし、実行イメージを作成してアップロードし、キャッシュされたコンテンツを永続化する必要がありますが、ローカルは通常、出力パッケージのみです。

したがって、上記の観点から始めて、次のようないくつかのアイデアに基づいて建設速度を最適化できます。

  1. 画像サイズを最適化します。

  2. 永続キャッシュを有効に活用して増分ビルドを実現します (/cache/ ディレクトリの内容を永続的にキャッシュする編集機会)

  3. マルチコアの利点を最大限に活用します。

    たとえば、ts-loader の型検証は他のプラグインを介して別のスレッドで実行できます。また、eslint-loader はマルチスレッドもサポートしています (ただし、現時点ではバグがあるため推奨されません)。

    別の例として、プロジェクトの機能モジュールを分離し、同時に複数のビルドに分割することができます。

  4. 不必要なビルドを削減します。

    たとえば、ビルド ファイルのスコープを簡素化するために除外を適切に構成します。

    頻繁に変更しないファイルの場合は、ファイルを取り出して一度ビルドし、次回再利用します。

  5. 外部ネットワークに依存するパッケージを削除する他の方法があるかどうかを判断する

ビルド速度を分析する方法

  1. /cache/ ディレクトリのサイズを確認します。

  2. du -sh /cacheビルド ログを通じてディレクトリ サイズを表示するには、コンパイル コマンドに次を追加します。

  3. コンパイルコマンド全体の前後に を追加すると date、プロジェクトの構築に時間がかかるプロセス、つまりコンパイルコマンドの実行時間がわかります。

  4. メインのコンパイル コマンドの各行の前に追加します time。例:time npm install インストール プロセスの実際の消費時間を確認できますが、ビルド プロセスは同じです。

  5. 全体のビルド時間 (Web ページに直接表示されるタスク時間) とコンパイル コマンドの実行時間 (終了時の日付時刻 - 開始時の日付時刻) を比較します (全体の時間がコンパイル コマンドの実行時間を超える場合)。多くの場合 (> 1 分 30 秒)、/cache/ ディレクトリであるか、画像が大きすぎる可能性があります。

詳細な紹介は次のとおりです。

小さい実行イメージを使用する

それより大きな画像がある場合は、運用保守に連絡して最適化することをお勧めします。

永続キャッシュを上手に活用する

キャッシュによりアプリケーションの構築を高速化できますが、キャッシュ ディレクトリが増大し続けると、速度がある程度低下する可能性があります。

キャッシュのメカニズムを理解します。

1. 缓存目录: /cache/

2. 默认行为: 对于 nodejs 的应用, 目前持久缓存会为 npm, pnpm 提供安装包的缓存, 以加快 npm install / pnpm install 的过程

3. 工作原理: 

    3.1 /cache/ 目录下的内容会构建成功后自动上传到服务器进行存储, 并在下次构建任务执行前进行挂载

    3.2 /cache/ 与 当前工作目录(即 './', 拉取的源码存放位置) 不在同一个文件系统(相当于是缓存在C盘而源码在D盘), pnpm install的行为将从 hark link回退为文件复制(硬链接的方式相对于大量小文件的拷贝, 速度要快很多)

    3.3 /cache/ 的工作涉及上传、下载过程, 如果过大也将会影响整个构建过程的速度

ビルド速度に対するグローバル キャッシュの影響を除外する

/cache/ のサイズを確認します。コンパイル コマンドに追加できます。du -sh /cacheログを確認します。フォルダーが 1G を超える場合 (参考のみ)、J-one に問い合わせてアプリケーション キャッシュをクリーンアップすることをお勧めします。

クロスディスクキャッシュによって引き起こされるパフォーマンス損失を解決する

主なアイデア: ソース コードと /cache/ を同じファイル システムに作成します。現在、この方法は pnpm アプリケーションに推奨されています。

原則: ソースコードと /cache/ を同じファイルシステムに作成することで、pnpm のハードリンク方式が有効となり、数万の小さなファイルを node_modules にコピーする場合に比べて、実行効率が大幅に向上します。参考: Pnpm は複数のドライブまたはファイルシステムで動作しますか?

方法: 現在の作業ディレクトリのコードを /cache/ にコピーし、インストールおよびビルド コマンドを実行します。

参考コマンド:

    # 记下当前工作目录
    CUR_WORKSPACE=`pwd`
    # 存放源码
    # 咱统一用 /cache/source 放源码就好, 虽然也可以改成其它目录的名字
    mkdir -p /cache/source
    # 拷贝当前目录的代码, 到 /cache/source 下
    rsync -r ./ /cache/source --exclude=node_modules --exclude=.git
    # 切换 workspace
    cd  /cache/source
    ########## 这里替换成自己需要的内容  ###########
    # 执行 install
    pnpm i
    # 执行 build
    pnpm run build
    ########## 这里替换成自己需要的内容  ###########

    # 将构建结果拷贝到抽包地址
    ########## 如果不是 dist, 请根据需要换成其它目录, 就是你项目构建完生成的目标代码目录
    cp -r ./dist/* ${CUR_WORKSPACE}/.build
    # 删除不需要被缓存的文件
    cd ../ && rm -rf /cache/source

上記のコンパイルコマンドは、Xingyun デプロイメントフロントエンドプロジェクト自体に基づいて簡略化されていますので、
原則と考え方を理解した上で、必要に応じて修正してください。

ビルド結果をキャッシュする

webpack とそのプラグインはビルド結果をキャッシュします。/cache/ の永続キャッシュを使用して、コード ビルド キャッシュを実装できます。他のビルド ツールでは、構成に関する関連ドキュメントを参照することもできます。

webpack4 または webpack4 に依存するビルド ツール (@vue/cli-service など) を使用する場合は、通常、cache-loader を使用してビルド結果をキャッシュします。babel-loader にも独自のビルド キャッシュがありますが、キャッシュ ディレクトリの下に、関連ドキュメントを参照して、キャッシュ ディレクトリを /cache/build (または /cache/ の他のサブディレクトリ) に設定することをお勧めします。

webpack5ではキャッシュ機能が統合され、キャッシュローダーなどのプラグインを削除することで無駄な作業を軽減できます。参考:webpackキャッシュ

モノリポジトリ アプリケーションの場合、サブプロジェクト レベルのキャッシュも実装できます。たとえば、nx を使用してモノリポジトリを管理すると、キャッシュ アドレスを設定するように NX_CACHE_DIRECTORY を構成できます。

export NX_CACHE_DIRECTORY=/cache/jdos3-console-ui/.nx

Eslint は非常に時間のかかる操作でもあります。キャッシュもサポートしていますが、デフォルトでは有効になっていません。必要に応じてキャッシュを有効にすることもできますが、各ビルド ファイルの createTime が異なるため、キャッシュ戦略では「コンテンツ」を使用する必要があります。変更すると、メタデータ戦略は失敗します。参考:eslintキャッシュ

通常、ローカル開発とクラウド展開の両方に互換性がある必要があり、これは環境変数によって実現できます。

webpack5 のキャッシュ構成:

{
    cache: {
        type: 'filesystem',
        profile: true,
        cacheDirectory: process.env.BUILD_CACHE_DIRECTORY,
        compression: 'gzip',
    },
}

同時に、Xingyun デプロイメントのコンパイル コマンドに追加します。

export BUILD_CACHE_DIRECTORY=/cache/.webpack

キャッシュを使用する別の方法: キャッシュnode_modules

(コンパイル チームがこのアイデアを提案しました。私はまだ試していません。製品に関するこのアイデアの一般的な解決策は検討中です。) 主なアイデア: ローカル ビルドをシミュレートする (ローカル ビルドでは、
node_modules ディレクトリが永続的に保持されます)
利点:
1. 高速化インストール 2. コードを使用して
キャッシュを構築します。通常、webpack5 または babel-loader は、node_modules/.cache ディレクトリにビルド キャッシュを保存します。これが、多くのアプリケーションのローカル ビルドの方が高速である理由です。もちろん、.cache ディレクトリは成長し続けるため、定期的にクリーンアップする必要があります。興味がある場合は、このディレクトリがローカル コードに存在するかどうか、およびこのディレクトリがどれくらいのスペースを占有しているかを確認できます。

参考コマンド:
上記の「クロスディスクキャッシュによるパフォーマンス損失を解決する」プロセスとほぼ同じですが、最後のrmプロセスが次回の使用のためにnode_modulesディレクトリを保持する点が異なります。

    ####### 与上面 解决缓存跨盘造成的性能损失 一致 #########
    # 记下当前工作目录
    CUR_WORKSPACE=`pwd`
    # 存放源码
    mkdir -p /cache/source
    # 拷贝当前目录代码到 /cache/ 下
    rsync -r ./ /cache/source --exclude=node_modules --exclude=.git
    # 切换 workspace
    cd  /cache/source
    # 执行 install
    npm i
    # 执行 build
    npm run build
    # 将构建结果拷贝到抽包地址
    cp -r ./dist/* ${CUR_WORKSPACE}/.build
    
    ####### 差异: 删除时排除 node_modules 目录 #########
    # 删除不需要被缓存的文件
    ls -A | grep -vE "^\.$|^\.\.$|^node_modules"|xargs rm -rf

ソースコードを減らす

コーディング中に、node_modules やさまざまな大きなバイナリ ファイルを送信しないようにします。

コンパイルプロセスを最適化する

依存パッケージのインストールプロセスを最適化する

  1. 一部のプロジェクトでは画像圧縮ツールであるimage-minimizer-webpack-pluginを利用しており、このリソースが依存するcwebp-binなどのリソースは海外サイトからダウンロードする必要があり、処理が遅くなったり、失敗する場合があります。可能であれば、圧縮イメージをコード リポジトリに直接送信し、同時にこのプラグインへの参照を削除することをお勧めします。

  2. たとえば、コンパイル コマンドの前に時間を追加して、 time pnpm install このステップの時間がかかることを確認できます。このステップが非常に長い場合は、削除できる依存関係があるかどうかを確認したり、オプションの依存関係のインストールを無効にしたりできます。場合によってはビルドをアップグレードする ツールを使用すると、パッケージの依存関係を最適化することもできます。

ビルドプロセスを最適化する

  1. Webpack によって構築されたアプリケーションの場合は、不必要なファイル構築を減らすために、ルールとプラグイン (サポートされている場合) が除外するように正しく設定されているかどうかを確認してください。

  2. ビルド キャッシュを有効にします (ただし、キャッシュの継続的な増加には依然として注意が必要で、過剰なキャッシュの問題は後で製品レベルから最適化される可能性があります)

  3. ts-loader は通常、transpileOnly: true を有効にし、fork-ts-checker-webpack-plugin を通じて型チェックを実行できます。

  4. eslint の最適化によりルールを最適化できます。一部の検証ルールは非常に時間がかかりますが、同時にメリットは大きくないため、それらをオフにすることを検討できます。具体的には、次のようにすることができます。

4.1 __TIMING__ 環境変数を設定して、各 eslint ルールのパフォーマンス分析を有効にする; export TIMING = 14.2
ローカルで通常どおりビルドを実行し、eslint ルールのパフォーマンスの出力を検出し、時間のかかるルールを分析し、必要かどうかを確認する

補充:

  • eslint のマルチスレッドの問題について: eslint のマルチスレッドを有効にすると、ビルド プロセスで見つかったルール例外をスローできなくなり、ルールが実際には無効になります。この質問については「問題」を参照してください。この質問は長い間存在しており、効果的に解決されていません。

  • 同時に、非標準コードの送信を避けるために、eslint 検証を git フックとして実装することも検討できます。この時点では、ビルド プロセス中にこの手順を省略できます。

5. コードの縮小処理には、webpack で設定できる esbuild を使用することをお勧めします。

{
   optimization: {
       minimize: true,
       minimizer: [
           new TerserPlugin({
               minify: TerserPlugin.esbuildMinify,
           }),
       ],
   }
}

6. 頻繁に変更しない部分については、事前にコンパイルするか、DllPlugin による最適化を行うことをお勧めします。たとえば、Xingyun デプロイメント プロジェクト自体は monaco エディターに依存していますが、毎回ソース コードをビルドするのは時間がかかるため、プリコンパイルされたコードが直接送信され、後で直接使用されます。

7. プロジェクトが複数回ビルドされないよう注意してください。例:
7.1 v5.0.0-beta.0 以降、vue-cli-service を使用するアプリケーションの場合、ブラウザー リストの構成に従って異なるパッケージが生成される場合があります。複数のビルドにつながる
7.2 一部のプロジェクトではマイクロ フロントエンド アクセスが必要で、独立したランタイム モードとサブアプリケーション モードに異なるエントリ ポイントを使用するため、プロジェクトを 2 回ビルドする場合があります。たとえば、JModule のユーザーは、非常に初期のバージョンの webpack-jmodule-plugin ではエントリ ファイルをカスタマイズできないため、通常はエントリ ファイルを 2 回ビルドします。最新の @jmodule/plugin-webpack にアップグレードし、同じエントリを使用することをお勧めします。一度ビルドするファイル。

8. 比較的単純なアプリケーションの場合は、esbuild、swc などの他のビルド ツールに切り替えることを検討できますが、プログラミング言語によってもたらされるパフォーマンスの違いが、実際に次元削減に打撃を与える可能性があります。

9. 可能であれば、プロジェクト コード間の依存関係を分析し、複数のビルドに分割して並列実行するコンパイラの最大の利点はマルチコアであり、それを最大限に活用できます。

10. webpack やその他のビルド プラグインをアップグレードすると、通常、ある程度の速度向上がもたらされ、jci プロジェクトのコンパイルはアップグレードの恩恵を受けました。

補充:

  1. Webpack の最適化の詳細については、https://webpack.docschina.org/configuration/cache/ を参照してください。

  2. time npm run build同様に、このステップの時間を観察しやすくするために、ビルド コマンドの前に時間を追加することも検討できます (例: )  。

  3. 「speed-measure-webpack-plugin」を使用して、Webpack の構築時間を分析することもできます。

フロントエンド構築の高速化は比較的複雑で詳細なプロジェクトです。現在、製品はビルドの遅いアプリケーションを継続的に追跡し、コンパイル速度の最適化を試みています。ただし、フロントエンド自体は、比較的自由な技術環境を持っています。さらに、言語自体の実行効率やシングルスレッド構築はコンパイラの能力を最大限に発揮するには十分ではないため、現在のグローバルな一般的な最適化手法はまだ比較的限定的であり、依然として依存しています。プロジェクト自体の最適化について。皆様が力を合わせて、より良い明日を築いていきたいと思います。


ChatGPT は 160 日間急騰しており、世界はもはや以前のような状態ではありません。

新しい人工知能中国語 Web サイトhttps://ai.weoknow.com では、
中国で利用可能な chatGPT リソースが毎日更新されます

おすすめ

転載: blog.csdn.net/zyqytsoft/article/details/131075929