Skip to content

fix: dist ディレクトリに HTML 付き production ビルドを出力する #44

Description

@takaokouji

概要

smalruby.app (本番環境) へのデプロイ用に、最適化された production ビルドを dist/ ディレクトリに HTML 付きで出力する仕組みを追加する。

背景

現在のビルド構成:

  • build/: 開発ビルド(HTML + JS、圧縮なし、ソースマップあり)
  • dist/: JS ライブラリのみ(HTML なし)

デプロイ先と使用ディレクトリ:

  • smalruby.app (本番): dist/ を使用(最適化されたビルド)
  • smalruby3-editor (develop): build/ を使用(プレビュー用)
  • PR ブランチ: build/ を使用(プレビュー用)

問題

webpack で dist/ に HTML を出力しようとすると、TerserPlugin の段階でビルドが失敗する。

<s> [webpack.Progress] 92% sealing asset processing TerserPlugin
npm error Lifecycle script `build:dist-html` failed with error:
npm error code 1

エラーメッセージの詳細が表示されないため、原因の特定が困難。

調査内容

試したアプローチ

アプローチ 1: buildWithPwaConfig.clone() をベースに作成

const distWithHtmlConfig = buildWithPwaConfig.clone()
    .merge({
        output: {
            path: path.resolve(__dirname, 'dist')
        }
    });

結果: TerserPlugin でビルド失敗

アプローチ 2: buildConfig.clone() をベースに作成

const distWithHtmlConfig = buildConfig.clone()
    .merge({
        output: {
            path: path.resolve(__dirname, 'dist')
        }
    })
    .addPlugin(new WorkboxPlugin.GenerateSW({...}))
    .addPlugin(new WebpackPwaManifest({...}));

結果: TerserPlugin でビルド失敗

考えられる原因

  1. output 設定の競合: distConfig に clean: false が設定されており、継承した設定と競合している可能性
  2. library 設定の干渉: distConfig の output.library 設定が HTML 出力時に干渉している可能性
  3. ScratchWebpackConfigBuilder の .clone() の挙動: 内部状態が正しくコピーされていない可能性
  4. TerserPlugin の設定: 本番モードでの圧縮処理中にエラーが発生している
  5. publicPath の違い: buildConfig ('') と distConfig ('auto') の違いが影響している可能性

次のステップ(デバッグ候補)

1. エラーログの詳細を確認

docker compose run --rm app bash -c "cd packages/scratch-gui && NODE_ENV=production BUILD_TYPE=dist-html npx webpack --stats=errors-only"

2. TerserPlugin を無効化してテスト

webpack.config.js で一時的に TerserPlugin を無効化して、HTML が生成されるか確認。

3. mode を development に変更してテスト

NODE_ENV=production の代わりに development でビルドして、問題を切り分ける。

4. output 設定を明示的に指定

const distWithHtmlConfig = buildConfig.clone()
    .merge({
        mode: 'production',
        output: {
            path: path.resolve(__dirname, 'dist'),
            publicPath: '',
            clean: true,
            library: undefined
        }
    })

5. 別のアプローチ: build/ を dist/ にコピー

webpack の設定を変更せず、CI/CD で build/ を dist/ にコピーする方法:

- name: Prepare deployment files for smalruby.app
  if: github.ref == 'refs/heads/develop'
  run: |
    cp -r packages/scratch-gui/build packages/scratch-gui/dist
    touch packages/scratch-gui/dist/.nojekyll

メリット:

  • webpack の設定を変更しないので、upstream とのマージが容易
  • エラーが発生しない
  • シンプルで理解しやすい

関連ファイル

  • packages/scratch-gui/webpack.config.js
  • packages/scratch-gui/package.json
  • packages/scratch-gui/src/playground/index.jsx
  • packages/scratch-gui/src/playground/render-gui.jsx
  • .github/workflows/ci-cd.yml

詳細調査レポート

詳細な調査内容は別途ドキュメントにまとめてあります。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions