@@ -17,30 +17,53 @@ This can be accomplished in different ways for different reasons:
1717 * - Integration Method
1818 - Use Case
1919
20+ * - :ref: `Dynamically Loaded Components `
21+ - You want to **quickly experiment ** with IDOM and the Javascript ecosystem.
22+
2023 * - :ref: `Custom Javascript Components `
2124 - You want to create polished software that can be **easily shared ** with others.
2225
23- * - :ref: `Dynamically Install Javascript ` (requires NPM _)
24- - You want to **quickly experiment ** with IDOM and the Javascript ecosystem.
26+
27+ Dynamically Loaded Components
28+ -----------------------------
29+
30+ .. note ::
31+
32+ This method is not recommended in production systems - see
33+ :ref: `Distributing Javascript Components ` for more info.
34+
35+ IDOM makes it easy to draft your code when you're in the early stages of development by
36+ using a CDN _ to dynamically load Javascript packages on the fly. In this example we'll
37+ be using the ubiquitous React-based UI framework `Material UI `_.
38+
39+ .. example :: material_ui_button_no_action
40+
41+ So now that we can display a Material UI Button we probably want to make it do
42+ something. Thankfully there's nothing new to learn here, you can pass event handlers to
43+ the button just as you did when :ref: `getting started `. Thus, all we need to do is add
44+ an ``onClick `` handler to the component:
45+
46+ .. example :: material_ui_button_on_click
2547
2648
2749Custom Javascript Components
2850----------------------------
2951
30- For projects that will be shared with others we recommend bundling your Javascript with
52+ For projects that will be shared with others, we recommend bundling your Javascript with
3153`rollup <https://rollupjs.org/guide/en/ >`__ or `webpack <https://webpack.js.org/ >`__
3254into a
3355`web module <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules >`__.
3456IDOM also provides a
3557`template repository <https://github.com/idom-team/idom-react-component-cookiecutter >`__
3658that can be used as a blueprint to build a library of React components.
3759
38- The core benefit of loading Javascript in this way is that users of your code won't need
39- to have NPM _ installed. Rather, they can use `` pip `` to install your Python package
40- without any other build steps because the bundled Javascript you distributed with it
41- will be symlinked into the IDOM client at runtime.
60+ To work as intended, the Javascript bundle must provide named exports for the following
61+ functions as well as any components that will be rendered.
62+
63+ .. note ::
4264
43- To work as intended, the Javascript bundle must export the following named functions:
65+ The exported components do not have to be React-based since you'll have full control
66+ over the rendering mechanism.
4467
4568.. code-block :: typescript
4669
@@ -63,25 +86,17 @@ These functions can be thought of as being analogous to those from React.
6386.. |reactDOM.unmountComponentAtNode | replace :: ``reactDOM.unmountComponentAtNode ``
6487.. _reactDOM.unmountComponentAtNode : https://reactjs.org/docs/react-api.html#createelement
6588
66- And will be called in the following manner:
89+ And will be called in the following manner, where ``component `` is a named export of
90+ your module:
6791
6892.. code-block ::
6993
7094 // on every render
71- renderElement(createElement(type , props), container);
95+ renderElement(createElement(component , props), container);
7296 // on unmount
7397 unmountElement(container);
7498
75- Once you've done this, you can distribute the bundled javascript in your Python package
76- and integrate it into IDOM by defining :class: `~idom.client.module.Module ` objects that
77- load them from source:
78-
79- .. code-block ::
80-
81- import idom
82- my_js_package = idom.Module("my-js-package", source_file="/path/to/my/bundle.js")
83-
84- The simplest way to try this out yourself though, is to hook in simple a hand-crafted
99+ The simplest way to try this out yourself though, is to hook in a simple hand-crafted
85100Javascript module that has the requisite interface. In the example to follow we'll
86101create a very basic SVG line chart. The catch though is that we are limited to using
87102Javascript that can run directly in the browser. This means we can't use fancy syntax
@@ -91,58 +106,40 @@ like `JSX <https://reactjs.org/docs/introducing-jsx.html>`__ and instead will us
91106.. example :: super_simple_chart
92107
93108
94- .. Links
95- .. =====
109+ Distributing Javascript Components
110+ ----------------------------------
96111
97- .. _Material UI : https://material-ui.com/
98- .. _NPM : https://www.npmjs.com
99- .. _install NPM : https://www.npmjs.com/get-npm
100-
101-
102-
103- Dynamically Install Javascript
104- ------------------------------
105-
106- .. warning ::
107-
108- - Before continuing `install NPM `_.
109- - Not guaranteed to work in all client implementations
110- (see :attr: `~idom.config.IDOM_CLIENT_MODULES_MUST_HAVE_MOUNT `)
111-
112- IDOM makes it easy to draft your code when you're in the early stages of development by
113- using NPM _ to directly install Javascript packages on the fly. In this example we'll be
114- using the ubiquitous React-based UI framework `Material UI `_ which can be installed
115- using the ``idom `` CLI:
116-
117- .. code-block :: bash
118-
119- idom install @material-ui/core
112+ There are two ways that you can distribute your :ref: `Custom Javascript Components `:
120113
121- Or at runtime with :func: ` idom.client.module.install ` (this is useful if you're working
122- in a REPL or Jupyter Notebook):
114+ - In a Python package via PyPI _
115+ - Using a CDN _
123116
124- .. code-block ::
125-
126- import idom
127- material_ui = idom.install("@material-ui/core")
128- # or install multiple modules at once
129- material_ui, *other_modules = idom.install(["@material-ui/core", ...])
130-
131- .. note ::
117+ That can be subsequently loaded using the respective functions:
132118
133- Any standard javascript dependency specifier is allowed here.
119+ - :func: `~idom.web.module.module_from_file `
120+ - :func: `~idom.web.module.module_from_url `
134121
135- Once the package has been successfully installed, you can import and display the component:
122+ These options are not mutually exclusive though - if you upload your Javascript
123+ components to NPM _ and also bundle your Javascript inside a Python package, in principle
124+ your users can determine which option work best for them. Regardless though, either you
125+ or, if you give then the choice, your users, will have to consider the tradeoffs of
126+ either approach.
136127
137- .. example :: material_ui_button_no_action
128+ - Distribution via PyPI _ - This method is ideal for local usage since the user can
129+ server all the Javascript components they depend on from their computer without
130+ requiring a network connection.
138131
132+ - Distribution via a CDN _ - Most useful in production-grade applications where its assumed
133+ the user has a network connection. In this scenario a CDN's
134+ `edge network <https://en.wikipedia.org/wiki/Edge_computing >`__ can be used to bring
135+ the Javascript source closer to the user in order to reduce page load times.
139136
140- Passing Props To Javascript Components
141- --------------------------------------
142137
143- So now that we can install and display a Material UI Button we probably want to make it
144- do something. Thankfully there's nothing new to learn here, you can pass event handlers
145- to the button just as you did when :ref: `getting started `. Thus, all we need to do is
146- add an ``onClick `` handler to the component:
138+ .. Links
139+ .. =====
147140
148- .. example :: material_ui_button_on_click
141+ .. _Material UI : https://material-ui.com/
142+ .. _NPM : https://www.npmjs.com
143+ .. _install NPM : https://www.npmjs.com/get-npm
144+ .. _CDN : https://en.wikipedia.org/wiki/Content_delivery_network
145+ .. _PyPI : https://pypi.org/
0 commit comments