You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p>These days Single-Page-Apps (SPA) are becoming more popular and they work similarly only that instead of letting the Server decide which JS to include to Client does it by itself.</p>
3790
+
<p>The more dynamic your website gets, the more dynamic your requirements may get. The server may not always know what the client may end up needing. Therefore, it is possible to have the client load code dynamically when needed.</p>
3791
+
</div>
3792
+
<divclass="paragraph">
3793
+
<p>There are a couple ways of loading code dynamically. <code>shadow.lazy</code> is the most convenient and easiest.</p>
<p>As <ahref="https://clojureverse.org/t/shadow-lazy-convenience-wrapper-for-shadow-loader-cljs-loader/3841">announced here</a> shadow-cljs provides a convenience method for referring to potentially lazy loaded code.</p>
<p>Let’s assume that the <code>on-event</code> function above is called when something in your app happens, for example when the user clicked a button. The <code>lazy/loadable</code> configured what that thing will be. The <code>lazy/load</code> will actually load it. This may require an async network hop, so it will go async at this point. In the body of the <code>js-await</code> above <code>x</code> will be whatever <code>demo.thing/x</code> was at the time of loading it.</p>
<p>In this case it would be the function, which we can call directly.</p>
3826
+
</div>
3827
+
<divclass="paragraph">
3828
+
<p>You do not need to worry about specifying which module this code ended up in. The compiler will figure that out during compilation. The <code>loadable</code> macro also allows more complex references.</p>
<p>If you load <code>xy</code> the result will be a vector with two things. If you load <code>xym</code> it’ll be a map. You may include vars that span multiple modules that way. The loader will ensure all modules are loaded before continuing.</p>
This is the low level version, which the above is built upoin. Use it if you want to build your own abstraction for async loading. The above is much more convenient to use.
3852
+
</td>
3853
+
</tr>
3854
+
</table>
3855
+
</div>
3794
3856
<divclass="paragraph">
3795
3857
<p>The compiler supports generating the required data for using the <code>shadow.loader</code> utility namespace. It exposes a simple interface to let you load modules on-demand at runtime.</p>
3796
3858
</div>
3797
3859
<divclass="paragraph">
3798
3860
<p>You only need to add <code>:module-loader true</code> to your build config. The loader will always be injected into the default module (the one everything else depends on).</p>
3799
3861
</div>
3800
3862
<divclass="paragraph">
3801
-
<p>At runtime you may use the <code>shadow.loader</code> namespace to load modules. You may also load a module eagerly by just using a <code><script></code> tag in your page.</p>
3863
+
<p>At runtime you may use the <code>shadow.loader</code> namespace to load modules. You may also still load a module eagerly by just using a <code><script></code> tag in your page.</p>
<p>You can check if a module is loaded using <code>(loaded? "module-name")</code>.</p>
3857
3919
</div>
3920
+
<divclass="paragraph">
3921
+
<p>You can read more about a more practical example in this blog post about <ahref="https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html"> Code-Splitting ClojureScript</a>. This is only a basic overview.</p>
<h5id="_using_the_standard_clojurescript_api"><aclass="anchor" href="#_using_the_standard_clojurescript_api"></a><aclass="link" href="#_using_the_standard_clojurescript_api">Using the Standard ClojureScript API</a></h5>
3867
3932
<divclass="paragraph">
3868
-
<p>The generated code is capable of using the standard ClojureScript <code>cljs.loader</code> API. See the
3869
-
<ahref="https://clojurescript.org/news/2017-07-10-code-splitting">documentation</a> on the ClojureScript
3870
-
website for instructions.</p>
3933
+
<p>The generated code is capable of using the standard ClojureScript <code>cljs.loader</code> API. See the <ahref="https://clojurescript.org/news/2017-07-10-code-splitting">documentation</a> on the ClojureScript website for instructions.</p>
3871
3934
</div>
3872
3935
<divclass="paragraph">
3873
-
<p>The advantage of using the standard API is that your code will play well with others. This
3874
-
may be of particular importance to library authors. The disadvantage is that the dynamic module
3875
-
loading API in the standard distribution is currently somewhat less easy-to-use than the
3876
-
support in <code>shadow-cljs</code>.</p>
3936
+
<p>The advantage of using the standard API is that your code will play well with others. This may be of particular importance to library authors. The disadvantage is that the dynamic module loading API in the standard distribution is currently somewhat less easy-to-use than the support in <code>shadow-cljs</code>.</p>
Copy file name to clipboardExpand all lines: docs/target-browser.adoc
+49-10Lines changed: 49 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -102,7 +102,7 @@ Say you have a traditional website with actual different pages.
102
102
- `www.acme.com/login` - serving the login form
103
103
- `www.acme.com/protected` - protected section that is only available once the user is logged in
104
104
105
-
One good configuration for this would be to have one common module that is shared between all the pages. Then one for each page.
105
+
One possible configuration for this would be to have one common module that is shared between all the pages. Then one for each page.
106
106
107
107
.Example config with multiple `:modules`
108
108
```clojure
@@ -147,15 +147,57 @@ IMPORTANT: The `.js` files must be included in the correct order. The <<BrowserM
147
147
148
148
=== Loading code dynamically
149
149
150
-
These days Single-Page-Apps (SPA) are becoming more popular and they work similarly only that instead of letting the Server decide which JS to include to Client does it by itself.
150
+
The more dynamic your website gets, the more dynamic your requirements may get. The server may not always know what the client may end up needing. Therefore, it is possible to have the client load code dynamically when needed.
151
+
152
+
There are a couple ways of loading code dynamically. `shadow.lazy` is the most convenient and easiest.
153
+
154
+
==== Using shadow.lazy
155
+
156
+
As https://clojureverse.org/t/shadow-lazy-convenience-wrapper-for-shadow-loader-cljs-loader/3841[announced here] shadow-cljs provides a convenience method for referring to potentially lazy loaded code.
157
+
158
+
```clojure
159
+
(ns demo.app
160
+
(:require
161
+
[shadow.lazy :as lazy]
162
+
[shadow.cljs.modern :refer (js-await)]))
163
+
164
+
(def x-lazy (lazy/loadable demo.thing/x))
165
+
166
+
(defn on-event [e]
167
+
(js-await [x (lazy/load x-lazy)]
168
+
(x e)))
169
+
```
170
+
171
+
Let's assume that the `on-event` function above is called when something in your app happens, for example when the user clicked a button. The `lazy/loadable` configured what that thing will be. The `lazy/load` will actually load it. This may require an async network hop, so it will go async at this point. In the body of the `js-await` above `x` will be whatever `demo.thing/x` was at the time of loading it.
172
+
173
+
```clojure
174
+
(ns demo.thing)
175
+
(defn x [e]
176
+
"hello world")
177
+
```
178
+
179
+
In this case it would be the function, which we can call directly.
180
+
181
+
You do not need to worry about specifying which module this code ended up in. The compiler will figure that out during compilation. The `loadable` macro also allows more complex references.
If you load `xy` the result will be a vector with two things. If you load `xym` it'll be a map. You may include vars that span multiple modules that way. The loader will ensure all modules are loaded before continuing.
151
191
152
192
==== Using shadow-cljs's built-in Loader Support
153
193
194
+
IMPORTANT: This is the low level version, which the above is built upoin. Use it if you want to build your own abstraction for async loading. The above is much more convenient to use.
195
+
154
196
The compiler supports generating the required data for using the `shadow.loader` utility namespace. It exposes a simple interface to let you load modules on-demand at runtime.
155
197
156
198
You only need to add `:module-loader true` to your build config. The loader will always be injected into the default module (the one everything else depends on).
157
199
158
-
At runtime you may use the `shadow.loader` namespace to load modules. You may also load a module eagerly by just using a `<script>` tag in your page.
200
+
At runtime you may use the `shadow.loader` namespace to load modules. You may also still load a module eagerly by just using a `<script>` tag in your page.
159
201
160
202
```
161
203
{...
@@ -204,20 +246,17 @@ Then the following expressions can be used for loading code:
204
246
205
247
You can check if a module is loaded using `(loaded? "module-name")`.
206
248
249
+
You can read more about a more practical example in this blog post about https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html[ Code-Splitting ClojureScript]. This is only a basic overview.
250
+
207
251
===== Loader Costs
208
252
209
253
Using the loader is very lightweight. It has a few dependencies which you may not be otherwise using. In practice using `:module-loader true` adds about 8KB gzip'd to the default module. This will vary depending on how much of `goog.net` and `goog.events` you are already using, and what level of optimization you use for your release builds.
210
254
211
255
==== Using the Standard ClojureScript API
212
256
213
-
The generated code is capable of using the standard ClojureScript `cljs.loader` API. See the
214
-
https://clojurescript.org/news/2017-07-10-code-splitting[documentation] on the ClojureScript
215
-
website for instructions.
257
+
The generated code is capable of using the standard ClojureScript `cljs.loader` API. See the https://clojurescript.org/news/2017-07-10-code-splitting[documentation] on the ClojureScript website for instructions.
216
258
217
-
The advantage of using the standard API is that your code will play well with others. This
218
-
may be of particular importance to library authors. The disadvantage is that the dynamic module
219
-
loading API in the standard distribution is currently somewhat less easy-to-use than the
220
-
support in `shadow-cljs`.
259
+
The advantage of using the standard API is that your code will play well with others. This may be of particular importance to library authors. The disadvantage is that the dynamic module loading API in the standard distribution is currently somewhat less easy-to-use than the support in `shadow-cljs`.
0 commit comments