Weird app.layout behavior only on IE (example included)

The behavior I expect:

  1. Point app.layout to some function “foo”
  2. Generate layout by calling “foo”
  3. Have a callback at some point update the URL
  4. “foo” is called to regenerate the layout

Frustrating this works in Chrome but in IE the original layout is used and foo is not called on step 4.

Here is an example, I have simplified my code by using global variables but in my real web-site I am basing this on cookies:

import time

# Third Party Library
import flask
from dash.exceptions import PreventUpdate

## Dash and Plotly Libraries
import dash
import dash_core_components as dcc
import dash_html_components as html

url_update = False


def get_layout():
    children = [dcc.Location(refresh=True, id='URL_OUTPUT'),
                dcc.Location(refresh=True, id='URL_INPUT')]
    global url_update

    if flask.has_request_context() and url_update:
        url_update = False
        children.append('Redirected')
    else:
        children.append('Original URL')

    return html.Div(children)


# App
app = dash.Dash(__name__)
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True
app.layout = get_layout


@app.callback(output=dash.dependencies.Output('URL_OUTPUT', 'pathname'),
              inputs=[dash.dependencies.Input('URL_INPUT', 'pathname')])
def login_callback(pathname):
    if pathname is None:
        raise PreventUpdate

    time.sleep(10)

    if pathname != '/redirect':
        global url_update
        url_update = True
        return '/redirect'

    raise PreventUpdate


if __name__ == '__main__':
    app.run_server(port=8050, host='0.0.0.0')

In this example using Chrome the page updates to “redirected” after 10 seconds, but for IE even though the URL is updated to “/redirect” the page still only says “Original URL”

OK, I think I’ve found somewhat the cause of the issue. When I turn developer tools on I don’t get this issue which lead me to this discussion https://stackoverflow.com/a/47576621 and think that IE doesn’t always refresh content from the server.

But even changing the meta tags to remove all cache I’ve not found a solution.

I finally figured out a solution, set the HTTP headers to have no cache like so:

# App
server = flask.Flask(__name__)

app = dash.Dash(__name__, server=server)
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True
app.layout = get_layout


@server.after_request
def add_header(response):
    response.cache_control.max_age = 0
    response.cache_control.public = True
    return response

That will remove all cache for the bundles when you serve locally. I recommend instead to subclass Dash and override serve_layout to disable the cache for only that route.

1 Like

Like this?

class DashLimitCache(dash.Dash):
    def serve_layout(self):
        response = super().serve_layout()
        response.cache_control.max_age = 0
        response.cache_control.public = True

        return response


# App
app = DashLimitCache(__name__)
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True
app.layout = get_layout

Also seems to work :grinning:

1 Like

Exactly :slight_smile:

2 Likes