Skip to content

Conversation

chr15m
Copy link
Contributor

@chr15m chr15m commented Aug 21, 2025

Fixes #95. This patch updates Scittle to support requiring already-loaded script tag JS deps off globalThis. Workflow:

<script src="https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js"></script>
(ns main
  (:require
    ["JSConfetti" :as c]))

(.addConfetti (c.))

You can also use esm imports in your index.html if you monkey-patch them onto globalThis/window before Scittle runs.

I'm not sure my naïve implementation is future proof so don't hesitate to reject or ask for changes. On #95 we spoked about David's plan to give globalThis requires a special syntax, and this patch should be forwards compatible with any future syntax I think.

In future it could also be adapted to load es modules using maybe sci.async. So it would try two loaders for a string require: 1. from globalThis 2. looking up the import map and doing an async esm import from the url specified. That's outside the scope of this PR though.


Please answer the following questions and leave the below in as part of your PR.

@borkdude
Copy link
Collaborator

borkdude commented Aug 21, 2025

You can also use esm imports in your index.html if you monkey-patch them onto globalThis/window before Scittle runs.

Nice!

I guess it's guaranteed that the type=module script tag always runs first?

<html>
  <head>
    <script type="module">
      import confetti from "https://esm.sh/canvas-confetti@1.6.0"
      globalThis.x = await(Promise.resolve(1));
      globalThis.JSConfetti = confetti;
    </script>
    <script src="https://cdn.jsdelivr.net/npm/scittle@0.7.26/dist/scittle.js" type="application/javascript"></script>
    <script type="application/x-scittle">
      (js/console.log js/x)
      (js/JSConfetti)
    </script>
  </head>
  <body>
  </body>
</html>

@borkdude
Copy link
Collaborator

Hmm, according to some sources (ChatGPT...) the type=module isn't guaranteed to finish before the "sync" script tag since it's always defer-ed by default

@borkdude
Copy link
Collaborator

borkdude commented Aug 21, 2025

Yeah here's a counter-example:

<html>
  <head>
    <script type="module">
      import confetti from "https://esm.sh/canvas-confetti@1.6.0"
      globalThis.x = await(new Promise((resolve) => setTimeout(resolve, 500)));
      console.log('hello')
      globalThis.JSConfetti = confetti;
    </script>
    <script src="https://cdn.jsdelivr.net/npm/scittle@0.7.26/dist/scittle.js" type="application/javascript"></script>
    <script type="application/x-scittle">
      (js/console.log js/x)
      (js/JSConfetti)
    </script>
  </head>
  <body>
  </body>
</html>

@chr15m
Copy link
Contributor Author

chr15m commented Aug 21, 2025

Ah ok so it would only work for non-modules scripts.

Maybe we could add something like scittle.js?wait-for-modules which would await for all module script tags on the page before running the Scittle boot up?

@chr15m
Copy link
Contributor Author

chr15m commented Aug 21, 2025

Although I don't think onload would wait for the setTimeout await. 🤔

@borkdude
Copy link
Collaborator

I think this should be the solution with async modules:

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/scittle@0.7.26/dist/scittle.js" type="application/javascript"></script>
    <script>scittle.core.disable_auto_eval()</script>
    <script type="module">
      import confetti from "https://esm.sh/canvas-confetti@1.6.0"
      globalThis.x = await(new Promise((resolve) => setTimeout(resolve, 500)));
      console.log('hello')
      globalThis.JSConfetti = confetti;
      scittle.core.eval_script_tags();
    </script>
    <script type="application/x-scittle">
      (js/console.log js/x)
      (js/JSConfetti)
    </script>
  </head>
  <body>
  </body>
</html>

@borkdude
Copy link
Collaborator

and this would work perfectly with your solution as well

@borkdude borkdude merged commit 7aebb5b into babashka:main Aug 21, 2025
@borkdude
Copy link
Collaborator

Exciting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ability to map require's to loaded JS deps
2 participants