-
Notifications
You must be signed in to change notification settings - Fork 199
Description
Current Situation
Historically, the Graph class is the main entry point in maxGraph. It automatically loads default plugins and style elements. This behavior simplifies evaluation and prototyping by reducing initial setup complexity. However, it is suboptimal for production use, as it bundles unused features, thus increasing the application's bundle size.
For example, many applications might not require all provided shapes, connectors, cell selection features (especially visualization-only apps), panning, or tooltips. Currently, even if these features are unused, they are still bundled due to their defaults being deeply integrated into the Graph class constructor parameters, making them impossible to tree-shake effectively.
Proposed Solution
We must retain the current behavior of the Graph class to maintain compatibility for evaluation purposes. Instead, we propose introducing a new class, provisionally named BaseGraph, that replicates the behavior of Graph without loading any default plugins or styles.
Currently, the Graph class loads defaults through a dedicated method invoked within its constructor. The BaseGraph could override this method with an empty implementation.
Alternative:
Another solution would be moving default style registration into a dedicated plugin, included by default in the Graph class plugin list. Users who wish to exclude defaults can simply omit this plugin.
Caution
This alternative impacts all stories and applications that redefine the plugin list. Further investigation is necessary to evaluate the ease of use and possible side effects.
Additional Enhancements Required
- Export the factory methods used to create default edge markers (not currently available in v0.17.0). This will allow selective registration of defaults.
- Expose internal utility functions currently used for default style loading (e.g., perimeter, edge styles) to facilitate easier integration.
Impact on Current Usage
We need to audit existing instances of Graph within the package, notably in components such as:
- Outline: there is probably no need for plugins, as the interactions with the Graph of the Outline are not managed by plugins
- Editor
To accommodate flexibility, provide mechanisms to configure or override the instantiated class via dependency injection, factory functions, or constructor parameters.
Constructor Improvements for Future-proofing
To immediately avoid potential breaking changes and simplify future enhancements, implement now a single configuration object parameter in constructors instead of multiple parameters. This approach makes it easier to extend configuration without altering method signatures significantly.
- Reference: Proposal for initiators in maxGraph feat: restore remaining non-"Editor" examples to Storybook #150 and Discussion regarding the proposed additional GraphInstantiators argument #151
Compatibility Strategy
Optionally, experiment with implementing a new DefaultGraph class using a configuration object constructor. The existing Graph class could extend this new class to assess ease of backward compatibility and practical benefits.
Existing Experiments and Impacts
Previous experiments on removing unused defaults:
- chore: measure impact of the default configuration on tree-shaking [POC] #432 (v0.10.3): Reduction of ~85.37 kB (Rollup), ~75 kB (Webpack)
- feat: let efficiently not load default plugins and style builtins [POC] #754 (v0.17.0): Reduction of ~103 kB (Rollup), ~105 kB (Webpack). This PR also explores an initial implementation of the proposed
BaseGraphclass using the new constructor approach and bridging compatibility with existingGraphusage.
Tasks
✔ Style Registration Functions
- Create functions to register default style elements by category (feat: let register and unregister default style elements #757)
- Create corresponding unregister functions (feat: let register and unregister default style elements #757)
✔ Marker Functions
- Create helper functions for registering individual marker factories (feat: let register and unregister default style elements #757)
- Expose functions to create the marker factories registered by default (feat: let register and unregister default style elements #757)
✔ Update Examples
Create a new selected-features example that mimics the existing js-example and ts-example but configures only the minimal set of features required for the use cases by explicitly opting into:
- only needed plugins (e.g., fit, panning, rubberband, cell selections - note: CellEditorHandler alone adds ~12KB!)
- minimal styling (e.g., perimeter and shape; for edges: only EdgeStyle.OrthConnector))
Tasks:
- Register only the required global styles (feat: introduce examples that not rely on default plugins and styles #774)
- Use a limited list of plugins (feat: introduce examples that not rely on default plugins and styles #774)
- Apply the same to the
maxgraph-integration-examplesrepository. This will provide a comparison whith the future use ofBaseGraph(refactor: optimize by loading only required graph features maxgraph-integration-examples#214)
Note
The current without-defaults examples demonstrate the maximum size reduction by removing all optional features i.e they show the absolute minimal footprint of using maxGraph.
The new selected-features examples will show what happens when some optional features are used (especially related to EdgeStyle, see #759 and #767).
Having those now will make it easier to show the gains when BaseGraph is available, and later when new improvements are added.
These examples will also help track future improvements. For example, today, importing just one static property from EdgeStyle or Perimeter still bundles the entire object. These examples will demonstrate the impact of migrating them to namespaces or other optimizable forms.
✔ Core Architecture Changes
See #776
- Introduce
AbstractGraph, with a constructor that accepts a singleoptionsparameter - Create
BaseGraphclass that extendsAbstractGraphbut doesn’t register any defaults - Update
Graphclass to:- extend
AbstractGraph - keep all factory methods that configures properties of the graph, the other (mainly vertex and edge handler stay in AbstractGraph, as they will later move to a plugin, see Refactor Graph class and mixins to improve modularity and tree-shaking #762)
- register default styles for backward compatibility
- extend
- Update
Outlinecomponent to useBaseGraph -
Editorwill keep usingGraphat least for now. It is not usable for now because of Editor.setGraphContainer generates an error as it calls a non existing Graph.int method #367. The usage of the Graph implementation could be reviewed later.
✔ Examples and Integration: use BaseGraph
- Update repository examples (
selected-featuresandwithout-defaults) to useBaseGraph. See feat: let efficiently not load default plugins and style builtins #776 - Update
maxgraph-integration-examplesrepo to useBaseGraph. See feat: use new features of maxGraph 0.18.0 maxgraph-integration-examples#215