Thanks to @david we have a very clean pattern for “eager” loading JavaScript in themes.
This means you just put *.js.es6
files into the javascripts
directory and it works exactly like plugins do, this is glorious.
For example this is how you do an initializer now, which has 100% parity with plugins:
- Create a file called
/javascripts/discourse/initializers/my-init.js.es6
import { withPluginApi } from "discourse/lib/plugin-api";
function initialize(api) {
// init via api here
}
export default {
name: "discourse-otp",
initialize() {
withPluginApi("0.8.28", initialize);
}
};
This is an enormously important feature cause we can now split up large complex themes into a lot of pieces, get linting, syntax highlighting and all the good stuff.
However, in some cases we may want to optionally ship a JS payload.
For example, say we are decorating posts, but only posts with very specific markdown. There is no point downloading a 100KB fancy library till we know we are going to use it.
I worked around this in my component following this fancy change:
https://github.com/discourse/discourse/commit/719a93c312b9caa6c71de22d67f1ce1a78c1c8b2
With:
import loadScript from "discourse/lib/load-script";
function generateOtp($elem) {
loadScript(settings.theme_uploads.jsotp).then(() => {
// stuff goes here
});
}
This meant
- I needed to add
.js
totheme authorized extensions
- I needed to add a bypass to the CSP for the particular asset in
content security policy script src
- I needed to name the asset in my about.json
As a theme component writer, this is just too much friction cause you have no chance in the distribution game requiring this level of ninja.
I am thinking to make this usable there are 2 alternatives we can pick from
-
We can teach the system to auto CSP the
.js
assets in active themes and by default allow themes to upload.js
-
We can shift towards something like javascript_cache that non defer theme js uses.
I am kind of leaning on 1 cause adding .js
to theme authorized extensions seems trivial and auto CSP should not be impossible.