Repository: reflex-dev/reflex

Issue:
Timeout when exporting production JS/HTML bundle on slow machines
**Describe the bug**
When running `reflex export --frontend-only --no-zip` on a slow machine (e.g. in a Docker build where QEMU emulation is used), the build fails. This is the output of such a failed Docker build:

```
....
#26 24.41 ────────────── Compiling production app and preparing for export. ──────────────
#26 56.69 [08:32:39] Compiling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 15/15 0:00:05
#26 2105.7 Creating Production Build failed with exit code 1
#26 2105.7 
#26 2105.7 > export-sitemap
#26 2105.7 > next build && next-sitemap
#26 2105.7 
#26 2105.7 Attention: Next.js now collects completely anonymous telemetry regarding usage.
#26 2105.7 This information is used to shape Next.js' roadmap and prioritize features.
#26 2105.7 You can learn more, including how to opt-out if you'd not like to participate in
#26 2105.7 this anonymous program, by visiting the following URL:
#26 2105.7 https://nextjs.org/telemetry
#26 2105.7 
#26 2105.8   ▲ Next.js 14.2.13
#26 2105.8 
#26 2105.8    Linting and checking validity of types ...
#26 2105.8    Creating an optimized production build ...
#26 2105.8  ✓ Compiled successfully
#26 2105.8    Collecting page data ...
#26 2105.8    Generating static pages (0/5) ...
#26 2105.8    Generating static pages (1/5) 
#26 2105.8    Generating static pages (2/5) 
#26 2105.8    Generating static pages (3/5) 
#26 2105.8  ✓ Generating static pages (5/5)
#26 2105.8    Finalizing page optimization ...
#26 2105.8    Collecting build traces ...
#26 2105.8  ⚠ Sending SIGTERM signal to static worker due to timeout of 60 seconds. 
#26 2105.8 Subsequent errors may be a result of the worker exiting.
#26 2105.8  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2105.9  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2105.9  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2105.9  ⚠ Restarted static page generation for /404 because it took more than 60 
#26 2105.9 seconds
#26 2105.9  ⚠ See more info here 
#26 2105.9 https://nextjs.org/docs/messages/static-page-generation-timeout
#26 2105.9  ⚠ Restarted static page generation for /details/[...image_name] because it took
#26 2105.9 more than 60 seconds
#26 2105.9  ⚠ Restarted static page generation for / because it took more than 60 seconds
#26 2105.9  ⚠ Restarted static page generation for /status because it took more than 60 
#26 2105.9 seconds
#26 2105.9  ⚠ Restarted static page generation for /404.html because it took more than 60 
#26 2105.9 seconds
#26 2105.9  ⚠ Sending SIGTERM signal to static worker due to timeout of 60 seconds. 
#26 2105.9 Subsequent errors may be a result of the worker exiting.
#26 2105.9  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2105.9  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2106.0  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2106.0  ⚠ Restarted static page generation for /404 because it took more than 60 
#26 2106.0 seconds
#26 2106.0  ⚠ Restarted static page generation for /details/[...image_name] because it took
#26 2106.0 more than 60 seconds
#26 2106.0  ⚠ Restarted static page generation for / because it took more than 60 seconds
#26 2106.0  ⚠ Restarted static page generation for /status because it took more than 60 
#26 2106.0 seconds
#26 2106.0  ⚠ Restarted static page generation for /404.html because it took more than 60 
#26 2106.0 seconds
#26 2106.0  ⚠ Sending SIGTERM signal to static worker due to timeout of 60 seconds. 
#26 2106.0 Subsequent errors may be a result of the worker exiting.
#26 2106.0  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2106.0  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2106.0  ⨯ Static worker exited with code: null and signal: SIGTERM
#26 2106.0 
#26 2106.0 > Build error occurred
#26 2106.1 Error: Static page generation for /404 is still timing out after 3 attempts. See
#26 2106.1 more info here https://nextjs.org/docs/messages/static-page-generation-timeout
#26 2106.1     at onRestart (/app/.web/node_modules/next/dist/build/index.js:279:27)
#26 2106.1     at /app/.web/node_modules/next/dist/lib/worker.js:95:40
#26 2106.1     at process.processTicksAndRejections 
#26 2106.1 (node:internal/process/task_queues:95:5)
#26 2106.1     at async /app/.web/node_modules/next/dist/export/index.js:450:20
#26 2106.1     at async Span.traceAsyncFn 
#26 2106.1 (/app/.web/node_modules/next/dist/trace/trace.js:154:20)
#26 2106.1     at async /app/.web/node_modules/next/dist/export/index.js:448:24
#26 2106.1     at async Promise.all (index 0)
#26 2106.1     at async exportAppImpl 
#26 2106.1 (/app/.web/node_modules/next/dist/export/index.js:440:21)
#26 2106.1     at async /app/.web/node_modules/next/dist/export/index.js:623:16
#26 2106.1     at async Span.traceAsyncFn 
#26 2106.1 (/app/.web/node_modules/next/dist/trace/trace.js:154:20)
#26 2106.1 npm notice 
#26 2106.1 npm notice New major version of npm available! 9.6.7 -> 10.9.0
#26 2106.1 npm notice Changelog: <https://github.com/npm/cli/releases/tag/v10.9.0>
#26 2106.2 npm notice Run `npm install -g npm@10.9.0` to update!
#26 2106.2 npm notice 
#26 2106.2 Run with --loglevel debug  for the full log.
#26 2106.2 Creating Production Build:  ━━━━━━━━━━━━━━━━━━━                  56% 5/9 0:33:57
```

The log output already indicates how to solve the problem ([increasing the timeout](https://nextjs.org/docs/messages/static-page-generation-timeout))

**To Reproduce**
Steps to reproduce the behavior:
[Code/Link to Repo:](https://github.com/MShekow/docker-tag-monitor/actions/runs/11200338860/job/31133849029)

**Expected behavior**
Either you increase the timeout by default (within Reflex), or you expose that property to Reflex users

**Specifics (please complete the following information):**
 - Python Version: 3.12
 - Reflex Version: 0.6.1
 - OS: Linux




Discussion:
The way to fix this would be to able to modify `staticPageGenerationTimeout` value inside of `next.config.js`. The link in the issue is 404-ing for some reason.



Patch:
diff --git a/reflex/config.py b/reflex/config.py
index 5edd9906ab1..12cc0916ab3 100644
--- a/reflex/config.py
+++ b/reflex/config.py
@@ -451,6 +451,9 @@ class Config:
     # The bun path
     bun_path: ExistingPath = constants.Bun.DEFAULT_PATH
 
+    # Timeout to do a production build of a frontend page.
+    static_page_generation_timeout: int = 60
+
     # List of origins that are allowed to connect to the backend API.
     cors_allowed_origins: List[str] = ["*"]
 
diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py
index 33165af0e94..d70e7706f74 100644
--- a/reflex/utils/prerequisites.py
+++ b/reflex/utils/prerequisites.py
@@ -677,6 +677,7 @@ def _update_next_config(
         "compress": config.next_compression,
         "reactStrictMode": config.react_strict_mode,
         "trailingSlash": True,
+        "staticPageGenerationTimeout": config.static_page_generation_timeout,
     }
     if transpile_packages:
         next_config["transpilePackages"] = list(


Test patch:
diff --git a/tests/units/test_prerequisites.py b/tests/units/test_prerequisites.py
index c4f57a9984a..2497318e73d 100644
--- a/tests/units/test_prerequisites.py
+++ b/tests/units/test_prerequisites.py
@@ -24,7 +24,15 @@
                 app_name="test",
             ),
             False,
-            'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true};',
+            'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true, staticPageGenerationTimeout: 60};',
+        ),
+        (
+            Config(
+                app_name="test",
+                static_page_generation_timeout=30,
+            ),
+            False,
+            'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true, staticPageGenerationTimeout: 30};',
         ),
         (
             Config(
@@ -32,7 +40,7 @@
                 next_compression=False,
             ),
             False,
-            'module.exports = {basePath: "", compress: false, reactStrictMode: true, trailingSlash: true};',
+            'module.exports = {basePath: "", compress: false, reactStrictMode: true, trailingSlash: true, staticPageGenerationTimeout: 60};',
         ),
         (
             Config(
@@ -40,7 +48,7 @@
                 frontend_path="/test",
             ),
             False,
-            'module.exports = {basePath: "/test", compress: true, reactStrictMode: true, trailingSlash: true};',
+            'module.exports = {basePath: "/test", compress: true, reactStrictMode: true, trailingSlash: true, staticPageGenerationTimeout: 60};',
         ),
         (
             Config(
@@ -49,14 +57,14 @@
                 next_compression=False,
             ),
             False,
-            'module.exports = {basePath: "/test", compress: false, reactStrictMode: true, trailingSlash: true};',
+            'module.exports = {basePath: "/test", compress: false, reactStrictMode: true, trailingSlash: true, staticPageGenerationTimeout: 60};',
         ),
         (
             Config(
                 app_name="test",
             ),
             True,
-            'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true, output: "export", distDir: "_static"};',
+            'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true, staticPageGenerationTimeout: 60, output: "export", distDir: "_static"};',
         ),
     ],
 )