🪺

WebpackのURLが思い通りにいかなくて怖かった話

2024/09/26に公開

前提

  • アプリケーション構成
    • フロントエンド → Vue.js
    • バックエンド → Laravel
  • ブランチに紐づく環境
    • develop → 検証環境
    • main → ステージ環境&本番環境

ビルドはCircle CIを使用しており、ビルドフローの諸々は .circleci/config.yml で記載

困ったこと

.circleci/config.yml で設定のうち、アセットを保管するパスを ASSET_PATH として環境変数に持っている

config.yml
  build_assets:
    environment:
      ASSET_PATH: [環境変数の初期値を設定]
    steps:
      - run:
          name: Set ASSET_PATH based on branch
          command: |
            if [ "$CIRCLE_BRANCH" == "master" ]; then
              echo 'export ASSET_PATH="[本番用のURL]"' >> $BASH_ENV
            else
              echo 'export ASSET_PATH="[検証用のURL]"' >> $BASH_ENV
            fi
            source $BASH_ENV

ただ、今回ステージ環境の ASSET_PATH を本番環境と分けたくなった。
新しくstagingブランチでも作るのがベストっぽいが、デプロイフローなどが大きく変わってしまうのでこのタイミングでは別の対応策を取りたい。

やってみたこと

以下のようにブランチ基準ではなくenvというパラメータを渡すことでstagingの時はステージ用のURLになるようにした

config.yml
  build_assets:
    parameters:
      env:
        type: string
    environment:
      ASSET_PATH: [環境変数の初期値を設定]
    steps:
      - run:
          name: Set ASSET_PATH based on env
          command: |
            echo << parameters.env >>

            if [ "develop" == << parameters.env >> ]; then
              echo 'export ASSET_PATH="[検証用のURL]"' >> $BASH_ENV
            elif [ "staging" == << parameters.env >> ]; then
              echo 'export ASSET_PATH="[ステージ用のURL]"' >> $BASH_ENV
            elif [ "production" == << parameters.env >> ]; then
              echo 'export ASSET_PATH="[本番用のURL]"' >> $BASH_ENV
            else
              exit 1
            fi
            source $BASH_ENV
            echo $ASSET_PATH

がうまくいかなかった

webpack.config.jsは以下のように設定してた

webpack.config.js
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
  // 省略
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'js/[name].js',
    publicPath: ASSET_PATH,
  },
  // 省略
};

現状のステージ環境&本番環境のフローとして

資産のビルド
↓
ステージ環境に反映
↓
本番環境に反映
※ 実際は開発者の操作をトリガーとしている

となっている
先ほど記載した build_assets はビルド時にのみ実行されるタスクだったのでステージ環境と本番環境のASSET_PATHを変更することができなかった

じゃあどうしたのか

publicPath というオプションを使って対応することにした
https://webpack.js.org/configuration/output/#outputpublicpath
元々参照したいパスは別の環境変数 ASSET_URL で指定しており、検証&ステージ&本番で使い分けできていたので
それを適用させるようにapp.jsに以下を追記した。

In cases where the publicPath of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the free variable webpack_public_path.

resources/app.js
__webpack_public_path__ = process.env.ASSET_URL;

Discussion