-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
248 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
--- | ||
title: On CDNs | ||
--- | ||
|
||
One of the objects which seems to crop up rather often when discussing this idea, is that | ||
|
||
> My users are now dependant on a CDN! | ||
This is true, although my invesigtaion makes this appear way less scary then it first looks. In fact on balance I've developed a strong preference for them... | ||
|
||
The reliability concern is dealt with in two ways. Firstly according to jsdelivr [status](https://status.jsdelivr.com), it's uptime was 100% in 2023. So, that's not too bad. | ||
|
||
And if you specifiy the explicit dependance of the module you are using... actually, it gets waaaay better ... because when the CDN responds to an explicitly versioned request, it includes a bunch of headers which say "This artifact is immutable. Don't bother me about this again. Ever". | ||
|
||
And the browser wqill respect that - next time you go ask for your dependancy, it simply loads it out of it's cache. There _is no network request_. Dependancy load time : 0ms, according to the browser network tools. | ||
|
||
It's tought to get faster than 0. Also, no request means no netork risk. | ||
|
||
So, under "ideal" conditions: | ||
|
||
- You are using a modern browser | ||
- You are making the request for a second+ time | ||
- You have explicitly specified the version of the dependancies you're using | ||
|
||
Dependancy resolution is both very reliable and very fast. What's cool - that cache survives redeployment. So your app is slow for the user the first time... but the cache survives a redeployment. It's fast afterwards. We can reword the statment as follows; | ||
|
||
> My users are now dependant on a CDN being available the first time they visit my site. | ||
Which is less scary given the historical uptime! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
--- | ||
title: Ummm... no Bundler? | ||
--- | ||
|
||
Yup, no bundler. | ||
|
||
Instead, consider using [ESModules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), and resolving NPM dependancies out of a [CDN](https://www.jsdelivr.com). | ||
|
||
It's less scary than it appears, and it feels _very_ good once it's up and going. An example that uses shoelace. [Sans Bundler](https://github.com/Quafadas/ShoelaceSansBundler). | ||
|
||
# Scala-CLI | ||
|
||
You'll need an `importmap.json` file. | ||
|
||
```json | ||
{ | ||
"imports": { | ||
"@shoelace-style/shoelace/dist/": "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.13.1/cdn/", | ||
} | ||
} | ||
``` | ||
|
||
and directives that tells scala-cli to use scala js, esmodules and where to find it. | ||
|
||
``` | ||
//> using platform js | ||
//> using jsModuleKind es | ||
//> using jsEsModuleImportMap importmap.json | ||
//> using jsModuleSplitStyleStr smallmodulesfor | ||
//> using jsSmallModuleForPackage frontend | ||
//> using dep com.raquo::laminar-shoelace::0.1.0 | ||
``` | ||
|
||
# Mill (0.11.8+) | ||
|
||
In your frontend module | ||
|
||
```scala sc:nocompile | ||
|
||
override def scalaJSImportMap = T { | ||
Seq( | ||
ESModuleImportMapping.Prefix("@shoelace-style/shoelace/dist/", "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.13.1/cdn/") | ||
) | ||
} | ||
``` | ||
|
||
Don't forget to depend on the facade too :-)... | ||
|
||
```scala sc:nocompile | ||
def ivyDeps = Agg( ivy"com.raquo::laminar-shoelace::0.1.0" ) | ||
``` | ||
|
||
# SBT | ||
|
||
I haven't personally used, but it would be possible, with this plugin; | ||
|
||
https://github.com/armanbilge/scalajs-importmap | ||
|
||
# Misc | ||
|
||
If you're walking on the bleeding edge with modules that aren't designed to be loaded out of a CDN (looking at you, SAP UI5 webcomponents), then things are not easy. You may need to give the browser some hints, on where it can resolve other parts of the module grap in your index.html; | ||
|
||
|
||
```json | ||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"@ui5/webcomponents-theming/": "https://cdn.jsdelivr.net/npm/@ui5/webcomponents-theming/", | ||
"@ui5/webcomponents-localization/": "https://cdn.jsdelivr.net/npm/@ui5/webcomponents-localization@1.24.7/", | ||
"@ui5/webcomponents/": "https://cdn.jsdelivr.net/npm/@ui5/webcomponents@1.24.7/", | ||
"@ui5/webcomponents-theming/": "https://cdn.jsdelivr.net/npm/@ui5/webcomponents-theming@1.24.7/", | ||
"@ui5/webcomponents-icons/": "https://cdn.jsdelivr.net/npm/@ui5/webcomponents-icons@1.24.7/", | ||
"@ui5/webcomponents-base/": "https://cdn.jsdelivr.net/npm/@ui5/webcomponents-base@1.24.7/", | ||
"@sap-theming/": "https://cdn.jsdelivr.net/npm/@sap-theming@1.24.7/", | ||
"@types/openui5/": "https://cdn.jsdelivr.net/npm/@types/openui5@1.24.7/", | ||
"@types/jquery/": "https://cdn.jsdelivr.net/npm/@types/jquery/", | ||
"lit-html": "https://cdn.jsdelivr.net/npm/lit-html", | ||
"lit-html/": "https://cdn.jsdelivr.net/npm/lit-html/" | ||
} | ||
} | ||
``` | ||
This actually got 95% of the way there... but localisation doesn't work. That means (for example) the date picker doesn't work. I have no good answer for this. Given that project explicitly recommends not using a CDN, it's not an obvious move to attempt this. | ||
|
||
The browser network tools are your friend. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--- | ||
title: Deployment | ||
--- | ||
|
||
This project targets the dev loop. When comes to deploy however, I always hit the same problem. From discord; | ||
|
||
|
||
> Ah, yeah, the classic SPA problem. While you develop, everything works because vite/react-scripts/... takes care of it. And when you deploy, everything seems to work fine, because navigation works via the history object and doesn't really send new requests. Only if you reload the page are you getting the 404. At least for modern SPAs and frameworks. There also was that brief period where most SPAs used the fragment for navigation, which didn't have that problem. | ||
> | ||
> The main thing complicating things is that - in most cases - you also need to serve resources, so neither "proxy /api, everything else to index.html" nor "everything /app to index html, rest proxied" work directly. | ||
> | ||
> What I've seen a few times is: | ||
> - Everything at /api gets proxied | ||
> - Everything else is resolved as is | ||
> - index.html is the fallback document that you get instead of a 404. | ||
This project provides a tiny helper library and an opinionated strategy to get over this hurdle, following exacltly the strategy laid out above. | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters