Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Production build fails for nextjs client #378

Open
JDruery opened this issue Mar 6, 2024 · 2 comments
Open

Production build fails for nextjs client #378

JDruery opened this issue Mar 6, 2024 · 2 comments

Comments

@JDruery
Copy link

JDruery commented Mar 6, 2024

API Platform version(s) affected: 3.2.16

Description
With a fresh installation, I was able to run the generator for the default Greeting entity. The app works in dev mode. When I try to build the app in production mode with http only, it fails with the following message:

9.052    Creating an optimized production build ...
38.73  ✓ Compiled successfully
38.73    Collecting page data ...
39.13 TypeError: Failed to parse URL from undefined/greetings
39.13     at node:internal/deps/undici/undici:12345:11
39.13     at async c (/srv/app/.next/server/pages/greetings/page/[page].js:1:7873)
39.13     at async c (/srv/app/.next/server/pages/greetings/page/[page].js:1:7119)
39.13     at async buildStaticPaths (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:786:33)
39.13     at async /srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1215:110
39.13     at async Span.traceAsyncFn (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/trace/trace.js:151:20) {
39.13   [cause]: TypeError: Invalid URL
39.13       at new URL (node:internal/url:775:36)
39.13       at new Request (node:internal/deps/undici/undici:5853:25)
39.13       at fetch (node:internal/deps/undici/undici:10123:25)
39.13       at Object.fetch (node:internal/deps/undici/undici:12344:10)
39.13       at fetch (node:internal/process/pre_execution:336:27)
39.13       at c (/srv/app/.next/server/pages/greetings/page/[page].js:1:7892)
39.13       at c (/srv/app/.next/server/pages/greetings/page/[page].js:1:7133)
39.13       at buildStaticPaths (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:786:39)
39.13       at /srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1215:116
39.13       at async Span.traceAsyncFn (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/trace/trace.js:151:20) {
39.13     code: 'ERR_INVALID_URL',
39.13     input: 'undefined/greetings'
39.13   }
39.13 }
39.13 TypeError: Failed to parse URL from undefined/greetings
39.13     at node:internal/deps/undici/undici:12345:11
39.13     at async o (/srv/app/.next/server/pages/greetings/[id].js:1:5312)
39.13     at async y (/srv/app/.next/server/pages/greetings/[id].js:1:4222)
39.13     at async buildStaticPaths (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:786:33)
39.13     at async /srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1215:110
39.13     at async Span.traceAsyncFn (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/trace/trace.js:151:20) {
39.13   [cause]: TypeError: Invalid URL
39.13       at new URL (node:internal/url:775:36)
39.13       at new Request (node:internal/deps/undici/undici:5853:25)
39.13       at fetch (node:internal/deps/undici/undici:10123:25)
39.13       at Object.fetch (node:internal/deps/undici/undici:12344:10)
39.13       at fetch (node:internal/process/pre_execution:336:27)
39.13       at o (/srv/app/.next/server/pages/greetings/[id].js:1:5331)
39.13       at y (/srv/app/.next/server/pages/greetings/[id].js:1:4236)
39.13       at buildStaticPaths (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:786:39)
39.13       at /srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1215:116
39.13       at async Span.traceAsyncFn (/srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/trace/trace.js:151:20) {
39.13     code: 'ERR_INVALID_URL',
39.13     input: 'undefined/greetings'
39.13   }
39.13 }
39.13
39.13 > Build error occurred
39.13 Error: Failed to collect page data for /greetings/page/[page]
39.13     at /srv/app/node_modules/.pnpm/next@14.1.2_@babel+core@7.24.0_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1258:15 {
39.13   type: 'Error'
39.13 }
39.15  ELIFECYCLE  Command failed with exit code 1.
------
failed to solve: process "/bin/sh -c pnpm install --frozen-lockfile --offline --prod && \tpnpm run build" did not complete successfully: exit code: 1

How to reproduce

  • Download the 3.2.16 distribution
  • docker compose build --no-cache
  • docker compose up --wait
  • docker compose exec pwa pnpm create @api-platform/client --resource greeting -g next
  • go to localhost/greetings to verify that the greetings page works
  • docker compose down
  • SERVER_NAME=:80 APP_SECRET=ChangeMe CADDY_MERCURE_JWT_SECRET=ChangeThisMercureHubJWTSecretKey docker compose -f compose.yaml -f compose.prod.yaml up --build
  • TypeError: Failed to parse URL from undefined/greetings
@J3m5
Copy link

J3m5 commented Mar 12, 2024

Hello @JDruery,

Thank you for reporting this issue.
The problem you're encountering during the production build appears to be related to the Next.js client's inability to access the API, which is essential for server-side generation (SSG) during the build process. Here's how to resolve it:

1. Set the API Endpoint in the .env file

First, we need to ensure that the Next.js client knows where to find the API. Create a .env file in the pwa directory and add the following line:

NEXT_PUBLIC_ENTRYPOINT=http://php

This environment variable (NEXT_PUBLIC_ENTRYPOINT) tells the Next.js client the base URL of your API, enabling it to make requests during the build and runtime.

2. Configure Docker Compose for Network Access

In the compose.prod.yaml file, we'll adjust the pwa service to ensure it can communicate with the php service during the build. Here's the modification:

  pwa:
    build:
      context: ./pwa
      target: prod
      network: host
      extra_hosts:
        - "php=127.0.0.1"

These changes allow the pwa build process to access the php service by mapping the php hostname to the local machine, facilitating SSG.

3. Adjust Environment Variables for the PHP Service

For seamless operation of the API and Mercure Hub on a local setup without HTTPS, we need to tweak the php service configuration in the compose.yaml file. This adjustment ensures they can properly handle requests from localhost. The changes below include modifications to the environment variables, with the original settings preserved as comments for easy reference and reversal if needed:

  php:
    image: ${IMAGES_PREFIX:-}app-php
    depends_on:
      - database
    restart: unless-stopped
    environment:
      PWA_UPSTREAM: pwa:3000
      SERVER_NAME: ${SERVER_NAME:-localhost}, php:80
      MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
      MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
      TRUSTED_PROXIES: ${TRUSTED_PROXIES:-127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16}
      # TRUSTED_HOSTS: ^${SERVER_NAME:-example\.com|localhost}|php$$
      TRUSTED_HOSTS: ^localhost|php$$
      DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}
      MERCURE_URL: ${CADDY_MERCURE_URL:-http://php/.well-known/mercure}
      # MERCURE_PUBLIC_URL: https://${SERVER_NAME:-localhost}/.well-known/mercure
      MERCURE_PUBLIC_URL: http://localhost/.well-known/mercure
      MERCURE_JWT_SECRET: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}

4. Build and start the php service

Let's start the php service to make it accessible:

SERVER_NAME=http://localhost APP_SECRET=!ChangeMe! CADDY_MERCURE_JWT_SECRET=ChangeThisMercureHubJWTSecretKey POSTGRES_PASSWORD=!ChangeMe! docker compose -f compose.yaml -f compose.prod.yaml up -d --build --wait php

5. Build the pwa service

docker compose -f compose.yaml -f compose.prod.yaml build pwa

6. Bring up the full project

SERVER_NAME=http://localhost  APP_SECRET=!ChangeMe! CADDY_MERCURE_JWT_SECRET=ChangeThisMercureHubJWTSecretKey POSTGRES_PASSWORD=!ChangeMe! docker compose -f compose.yaml -f compose.prod.yaml up -d --wait

With these adjustments, your production build should succeed, and the Next.js client will be able to access the API during the build process and at runtime.

@J3m5
Copy link

J3m5 commented Mar 13, 2024

I've updated my initial post due to additional issues encountered during runtime. For the API and Mercure to function correctly without HTTPS, it's necessary to revise the TRUSTED_HOSTS and MERCURE_PUBLIC_URL environment variables in the compose.yaml file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants