The component system bridges React components to Python with auto-generated wrappers.
React/TypeScript Source
↓
extract-meta.js (Node.js)
├── react-docgen (for .js/.jsx - parses PropTypes)
└── TypeScript Compiler API (for .tsx - parses type definitions)
↓
metadata.json
↓
dash-generate-components (Python CLI)
↓
Python component classes (+ R/Julia if requested)
-
dash/extract-meta.js- Node.js script that extracts component metadata. For JavaScript components, usesreact-docgento parse PropTypes. For TypeScript components, uses the TypeScript Compiler API to parse type definitions and convert them to metadata format. -
dash/development/component_generator.py- CLI entry point (dash-generate-components). Orchestrates metadata extraction and code generation. -
dash/development/_py_components_generation.py- Generates Python class files from metadata. Creates typed__init__methods, docstrings, and prop validation. -
dash/development/_py_prop_typing.py- Maps JavaScript/TypeScript types to Python types (e.g.,arrayOf→typing.Sequence,shape→TypedDict). -
dash/development/_generate_prop_types.py- For TypeScript components, generates aproptypes.jsfile since TSX doesn't have runtime PropTypes.
Components serialize to {type, namespace, props} via to_plotly_json() in base_component.py:
# Python component
html.Div(id='my-div', children='Hello')
# Serializes to JSON
{
"type": "Div",
"namespace": "dash_html_components",
"props": {
"id": "my-div",
"children": "Hello"
}
}This JSON is sent to the frontend via /_dash-layout (initial load) and /_dash-update-component (callback responses).
Components must be available on the frontend at window[namespace][type]:
// Component packages register themselves
window.dash_html_components = {
Div: DivComponent,
Span: SpanComponent,
// ...
};
window.dash_core_components = {
Dropdown: DropdownComponent,
Graph: GraphComponent,
// ...
};The renderer resolves components via registry.js:
resolve: (component) => {
const {type, namespace} = component;
return window[namespace][type]; // Returns React component class
}Auto-generated by generate_imports() in _py_components_generation.py:
from .Dropdown import Dropdown
from .Graph import Graph
from .Input import Input
# ... one import per component
__all__ = [
"Dropdown",
"Graph",
"Input",
# ...
]Manually maintained, imports from _imports_.py:
from ._imports_ import * # Re-exports all components
from ._imports_ import __all__ as _components
# Read version from package-info.json
with open(os.path.join(_basepath, "package-info.json")) as f:
package = json.load(f)
__version__ = package["version"]
# Define JavaScript assets to serve
_js_dist = [
{
"relative_package_path": "dash_core_components.js",
"namespace": "dash",
},
# async chunks, source maps, proptypes.js for dev, etc.
]
# Attach _js_dist to each component class
for _component in _components:
setattr(locals()[_component], "_js_dist", _js_dist)dash/resources.py manages JavaScript and CSS asset loading for components.
{
"relative_package_path": "dcc/dash_core_components.js", # Path within package
"external_url": "https://unpkg.com/...", # CDN fallback
"namespace": "dash", # JS namespace
"async": True | "eager" | "lazy", # Async loading mode
"dynamic": True, # Loaded on demand (source maps)
"dev_package_path": "dcc/proptypes.js", # Dev-only path
"dev_only": True, # Only in dev mode
}- Each component class has
_js_dist(and optionally_css_dist) attribute set in__init__.py - When component is imported,
ComponentMetaregisters module inComponentRegistry.registry ComponentRegistry.get_resources("_js_dist")iterates registered modules, collects all_js_distlistsScripts/Cssclasses inresources.pyfilter resources based on config:serve_locally=True: Userelative_package_path, serve via/_dash-component-suites/serve_locally=False: Useexternal_url(CDN)eager_loading=True: Load async resources immediatelydev_bundles=True: Includedev_package_pathresources
async: True- Dynamic unlesseager_loadingis enabledasync: "lazy"- Always loaded dynamically (on-demand)async: "eager"- Loaded dynamically only if server isn't in eager mode
- Write React component with PropTypes (JS) or TypeScript props interface (TSX)
- Run
dash-generate-components src/lib/components -p package_name - Generated Python wrapper goes to
package_name/ComponentName.py _imports_.pyis auto-generated with imports for all components- For TSX,
proptypes.jsis also generated for runtime prop validation - Bundle with webpack, register on
window[namespace] - Update
__init__.pyto set_js_diston components
Managed as a Lerna monorepo in components/:
components/dash-core-components/- Interactive components (Dropdown, Slider, Graph, Input, etc.)components/dash-html-components/- HTML element wrappers (Div, Span, H1, etc.)components/dash-table/- DataTable component (deprecated in favor of dash-ag-grid)
Use dash-update-components "component-name" to rebuild after changes.