-
-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow panel plugins to load index.dev.mjs instead of index.js (needed by kirbyup) #4541
Conversation
Thank you very much for your contribution. I like the concept as it really feels like something that can just work™ without any need to think about the details as a user. Especially the idea to dynamically generate the A few comments:
|
Yeah, agree that this isn't optimal! But since the Another way would be to load both the plugin and panel JS from an inline module: <script type="module">
import '/media/plugins/index.mjs'
import('/media/panel/assets/js/index.js')
</script> Not sure if the browser's preload scanner detects these imports AOT, if yes it shouldn't make a difference perf-wise, otherwise we'd also need to add a
Makes sense! I think
...if we know the Gonna push some changes later today. :) Edit: |
Updated the loading behavior as described in my comment above. Let me know what you think! (the |
I added a few comments. Would be great to have more inline comments as well to understand why we are doing these extra jumps etc. also 2,3 years down the road. |
e9aa698
to
3c58a17
Compare
This reverts commit 782be53
@lukasbestle I noticed that behavior before: if a JS file contains less than 3 chars, the reported mime type isn't a) fix the test (use 'application/octet-stream' => [
'mjs' => 'text/javascript'
] (option b) is currently implemented) |
I think it's great. Just three things still to do IMO:
|
@lukasbestle All done! And another thing: just realized that this could actually be implemented without top level await, by using an async IIFE in the main |
Fully agree! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly coding style stuff, the rest looks really great. Thanks a lot for the extra code comments. 👍
This PR allows plugins to use a module-based
index.dev.mjs
as entryI'm currently doing work so Kirby plugins developed with
kirbyup
can use Vite features like HMR during development, which much improves the DX of authoring panel plugins that include Vue components: johannschopplich/kirbyup#17 (comment)However there are some constraints: Kirby plugins need to load in order (have to be registered on
window.panel.plugins
before the panel initializes), and the Vite dev server works with native JS modules, which execute asynchronously – so when panel and plugin are loaded separately, in-order execution can't be ensured.To work around that, Kirby would either need to support the async registration of plugins (which I expect to be quite the invasive and complex change), or include module-based plugins in the panel's module graph via an import to make sure they execute first, which is what this PR implements.
Implementation details
Instead of loading the panel code directly via
<script type="module" src="path/to/panel.js">
, it is now loaded like this:This allows us to inject imports for module-based plugins before the panel code is imported:
Note that the import of
panel.js
must be a dynamicimport()
: in-order-execution of static imports is only guaranteed for synchronous modules, so if the first import uses top level await, the second import can actually run before the first one.Loading the panel code through a dynamic import as part of the module body makes sure the panel runs after all plugins are loaded, since a module body executes after all static imports are done.
(in browsers supporting
link[rel=modulepreload]
the panel code is still fetched and compiled ahead of time)This leaves us with one last problem: a single failing plugin import can prevent the entire panel from loading as there's no way to
catch
errors from a static import. To solve this, plugin modules themselves are loaded through a dynamic import, which can be wrapped intry/catch
:As a perf enhancement and to avoid having to copy
index.dev.mjs
to/media
and then delete it again when the kirbyup development server is stopped and theindex.dev.js
is removed, the plugins are loaded inline, as data URIs:If a plugin has an
index.dev.mjs
which is loaded through the technique above, its regularindex.js
will be excluded from theplugins/index.js
bundle. Otherwise, itsindex.js
is loaded as part ofplugins/index.js
as it used to.Breaking changes
No, the only change is that
panel.js
is now loaded via a dynamicimport()
, which is covered by Kirby's minimum browser requirements. All other changes only have an effect if akirbyup
development server is running and created anindex.dev.mjs
.Ready?
For review team
Add to website docs release checklist (if needed)