Ability to choose partial plotly.js bundles
See original GitHub issueGreat library 💃 One small improvement 💡 : Currently dcc
is shipped with the full plotly.min.js
bundle. Do you see an easy/elegant way of enabling the user to specify one of the partial plotly.js bundles, and let e.g. the full bundle be the default?
I currently see two use cases:
- Reduced size (full
plotly.min.js
2.8 MB, while e.g.plotly.cartesian.js
, covering many applications, is 0.9 MB). - Make it possible to enforce a strong CSP configuration (useful for applications where increased security is wanted).
Regarding 2), Dash alone works beautifully with a strong CSP configuration. You can e.g. do
pip install dash dash_html_components dash_core_components flask-talisman
and then run
import dash
import dash_html_components as html
import dash_core_components as dcc
from flask_talisman import Talisman
app = dash.Dash(__name__)
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True
csp = {
'default-src': '\'self\'',
'prefetch-src': '\'self\'',
#'script-src': ['\'self\'', '\'unsafe-eval\''], # [1]
#'style-src': ['\'self\'', '\'unsafe-inline\''], # [2]
'navigate-to': '\'self\'',
'base-uri': '\'self\'',
'form-action': '\'self\'',
'frame-ancestors': '\'none\'',
'object-src': '\'none\''
}
# [1]: https://github.com/plotly/plotly.js/issues/897
# [2]: https://github.com/plotly/plotly.js/issues/2355
Talisman(app.server, content_security_policy=csp, force_https=False)
app.layout = html.Div(children=['Hello Dash!'])
#app.layout = html.Div(children=['Hello Dash!', dcc.Graph()])
if __name__ == '__main__':
app.run_server(host='localhost')
This works beautifully in Dash.
However if dcc.Graph()
is added to app.layout
you will in the browser get “Error loading dependencies” due to violation of CSP directives script-src
and style-src
(these comes from https://github.com/plotly/plotly.js/issues/897 and https://github.com/plotly/plotly.js/issues/2355 respectively).
This can be “solved” by adding unsafe-eval
and unsafe-inline
, but the script-src
part can be solved in a safer way by using one of the partial bundles of plotly.js
instead, for applications where you don’t need gl3d
and gl2d
.
I quickly tested overwriting the [...]/lib/python3.7/site-packages/dash_core_components/plotly[...].min.js
installed in the environment with one of the partial plotly.js
bundles, and that enabled (as expected) a stricter CSP without opening for eval()
and its relatives.
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
As discussed in https://github.com/plotly/dash/issues/655, since we added async resources you can simply put the
plotly.js
bundle you want into your assets folder - or a link to a CDN version indash.Dash(external_scripts=[...])
- and the built-in version will not be loaded, only your new one will. Documentation to follow https://github.com/plotly/dash-docs/issues/723The only additional piece to consider is if we want to include a predefined set of plotly.js bundles with the package; I don’t think we should do that though, there are just too many different possibilities users may want.
@mjclawar that’s a good point. At the moment I’m not sure where else this would be used, I don’t see anything offhand, but there could certainly be cases added in the future either within the core or in additional components folks write.
The challenge is that these resources aren’t named, they’re currently just collected as a list of urls/paths. So the plotlyjs bundle is currently brought in here:
https://github.com/plotly/dash-core-components/blob/83a3ea07fd8af9ee3ca57c8da8ed32483e96f87c/dash_core_components/__init__.py#L36-L41
If we were to add a name/id to this, something like
'resource_name': 'plotly.js'
, then we could imagine adding a feature like: