I love that the Python module reloads automatically on save but I still need to refresh my browser when I make a change to the Python code, which means I lose the state I was in and need to fiddle with the UI to get the view back to how it was before I made the change. It would be great if we could leverage a system like React Hot Loader or something similar for totally seamless multi-monitor development. Just type code on one monitor, save, and turn your head to to see the changes on the other monitor ;)
Definitely! Would love to add this.
If any company out there would like to help sponsor and prioritize this work, please reach out.
I thought about this a little bit more last night and I think we can get pretty close with just dash_core_components.Interval and debug=True. Check this out 馃樅

Here's the code:
import dash
from dash.dependencies import Event, Input, Output
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash()
# Edit this object!
layout = html.Div([
html.H1('Hello Dash!'),
html.H3('Dash with live-reload'),
])
# Barebones layout
app.layout = html.Div([
dcc.Interval(id='refresh', interval=200),
html.Div(id='content', className="container")
])
# Update the `content` div with the `layout` object.
# When you save this file, `debug=True` will re-run
# this script, serving the new layout
@app.callback(
Output('content', 'children'),
events=[Event('refresh', 'interval')])
def display_layout():
return layout
app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})
if __name__ == '__main__':
app.run_server(debug=True)
oooh nice :)
OK so I tried this with some actual statefulness in the app (sliders etc) and a couple of notes:
app.config.supress_callback_exceptions=True as per the helpful warning :)It doesn't seem like this approach preserves/respects the state of the sliders in my little app, which is a large part of the value of hot-reload (although quick-preview of default state is already a big step!) ... am I interpreting this wrong? I'll try to make a toy example.
Yes, I think that is true. Dang! Almost there. It sounds like there is still precedent for a proper hot-reload.
Here's a stripped-down example that shows the issue... I should add that it blinks/flickers pretty noticeably on my screen, also :) But it's a good start!
# -*- coding: utf-8 -*-
import dash, dash_core_components as dcc, dash_html_components as html
import plotly.graph_objs as go
import math, pandas as pd, numpy as np
data = np.random.normal(0,1,10000)
layout = html.Div([
dcc.Slider(id='spread', min=0.5, max=5.0, value=2.5, step=0.5),
dcc.Graph(id='hist'),
])
app = dash.Dash()
app.config.supress_callback_exceptions=True
app.layout = html.Div([
dcc.Interval(id='refresh', interval=200),
html.Div(id='content', className="container")
])
@app.callback(
dash.dependencies.Output('content', 'children'),
events=[dash.dependencies.Event('refresh', 'interval')])
def display_layout():
return layout
@app.callback(
dash.dependencies.Output('hist', 'figure'),
[dash.dependencies.Input('spread', 'value')])
def update_hist(spread):
kwargs = dict( opacity=0.75, autobinx=False,
xbins=dict( start=-10.0, end=10, size=0.1 )
)
return dict(
data = [
go.Histogram(x=data, **kwargs),
go.Histogram(x=data*spread, **kwargs)
],
layout = go.Layout(
barmode='overlay',
xaxis=dict( range=[-10, 10] ),
yaxis=dict( range=[0, 500] )
)
)
if __name__ == '__main__':
app.run_server(debug=True)
Good news! The development for this issue has been sponsored by an organization as part of our "Pleasant and Productive Developer Experience" initiative.
I came across this issue and had an idea on how to implement it.
I thought that flask already reload itself when it detect changes in debug mode.
Let's use that with a hash generated at startup and periodically request the
server for the hash, if it has changed, it's time to reload. Put that request loop code
in a webworker so it won't tamper with the rest of the app.
So I made a quick prototype with flask only, it worked. But I needed to change
the index rendering of dash to use jinja2 so I could put a context and load the
worker only if hot-reload is enabled. This didn't take long and I had a working
prototype of dash with hot-reload.
I now plan to separate the integration of hot-reload into several components which
can be useful in other parts of dash.
Dash should use jinja2 for its index. #281
Dash static files and templates must be structured so they work from the lib and can be
customized by the user. #265
I'm curious about the coupling of your solution to Jinja... is there a specific dependency on Jinja or do you just need some kind of access to the index.html, i.e. by overriding Dash's index() function?
Most helpful comment
I thought about this a little bit more last night and I think we can get pretty close with just
dash_core_components.Intervalanddebug=True. Check this out 馃樅Here's the code: