Repository: plotly/dash

Issue:
[Feature Request] Make app validation optional when using `pages`
When using `pages` to make a multi page app, one of the nice features is that it automatically validates the layout.  However as pointed out in [this forum post](https://community.plotly.com/t/examples-of-multi-page-apps-with-dash-pages/66489/4?u=annmariew) it can make the initial load of an app slow if some of the layout functions are slow.

A possible solution is to make the validation optional, then [this section](https://github.com/plotly/dash/blob/dev/dash/dash.py#L2078:L2092) would be skipped.  (I tried it and it seems to work)

Validation could be turned off like this:

```
app = das.Dash(__name__, use_pages=True, set_validation_layout=False,  suppress_callback_exceptions=True)
```

or maybe if `set_validation_layout=False`, it could automatically set `suppress_callback_exceptions=True`

Any downside to doing this?


Discussion:

Resolving patch:
diff --git a/dash/dash.py b/dash/dash.py
--- a/dash/dash.py
+++ b/dash/dash.py
@@ -2075,20 +2075,21 @@ def update(pathname, search):
             _validate.validate_registry(_pages.PAGE_REGISTRY)
 
             # Set validation_layout
-            self.validation_layout = html.Div(
-                [
-                    page["layout"]() if callable(page["layout"]) else page["layout"]
-                    for page in _pages.PAGE_REGISTRY.values()
-                ]
-                + [
-                    # pylint: disable=not-callable
-                    self.layout()
-                    if callable(self.layout)
-                    else self.layout
-                ]
-            )
-            if _ID_CONTENT not in self.validation_layout:
-                raise Exception("`dash.page_container` not found in the layout")
+            if not self.config.suppress_callback_exceptions:
+                self.validation_layout = html.Div(
+                    [
+                        page["layout"]() if callable(page["layout"]) else page["layout"]
+                        for page in _pages.PAGE_REGISTRY.values()
+                    ]
+                    + [
+                        # pylint: disable=not-callable
+                        self.layout()
+                        if callable(self.layout)
+                        else self.layout
+                    ]
+                )
+                if _ID_CONTENT not in self.validation_layout:
+                    raise Exception("`dash.page_container` not found in the layout")
 
             # Update the page title on page navigation
             self.clientside_callback(


Test patch:
diff --git a/tests/integration/multi_page/test_pages_layout.py b/tests/integration/multi_page/test_pages_layout.py
--- a/tests/integration/multi_page/test_pages_layout.py
+++ b/tests/integration/multi_page/test_pages_layout.py
@@ -49,8 +49,8 @@ def get_app(path1="/", path2="/layout2"):
 
 
 def test_pala001_layout(dash_duo):
-
-    dash_duo.start_server(get_app())
+    app = get_app()
+    dash_duo.start_server(app)
 
     # test layout and title for each page in `page_registry` with link navigation
     for page in dash.page_registry.values():
@@ -93,6 +93,9 @@ def test_pala001_layout(dash_duo):
     dash_duo.wait_for_page(url=f"http://localhost:{dash_duo.server.port}/find_me")
     dash_duo.wait_for_text_to_equal("#text_not_found_404", "text for not_found_404")
 
+    # test `validation_layout` exists when suppress_callback_exceptions=False`
+    assert app.validation_layout is not None
+
     assert dash_duo.get_logs() == [], "browser console should contain no error"
     # dash_duo.percy_snapshot("pala001_layout")
 
diff --git a/tests/integration/multi_page/test_pages_order.py b/tests/integration/multi_page/test_pages_order.py
--- a/tests/integration/multi_page/test_pages_order.py
+++ b/tests/integration/multi_page/test_pages_order.py
@@ -4,7 +4,7 @@
 
 def test_paor001_order(dash_duo):
 
-    app = Dash(__name__, use_pages=True)
+    app = Dash(__name__, use_pages=True, suppress_callback_exceptions=True)
 
     dash.register_page(
         "multi_layout1",
@@ -64,4 +64,7 @@ def test_paor001_order(dash_duo):
         list(dash.page_registry) == modules
     ), "check order of modules in dash.page_registry"
 
+    # There should be no `validation_layout` when suppress_callback_exceptions=True`
+    assert app.validation_layout is None
+
     assert dash_duo.get_logs() == [], "browser console should contain no error"