sam
(Sam Saffron)
2019 年 8 月 21 日午前 7:45
1
@david さんのおかげで、テーマにおける「eager」読み込みの JavaScript に関する非常にクリーンなパターンができました。
つまり、*.js.es6 ファイルを javascripts ディレクトリに置くだけで、プラグインと同様に動作するようになります。これは素晴らしいことです。
例えば、以下のようにイニシャライザーを作成すると、プラグインと 100% 同等の機能を実現できます。
/javascripts/discourse/initializers/my-init.js.es6 という名前のファイルを作成します
import { withPluginApi } from "discourse/lib/plugin-api";
function initialize(api) {
// api を通じた初期化処理をここに記述
}
export default {
name: "discourse-otp",
initialize() {
withPluginApi("0.8.28", initialize);
}
};
これは非常に重要な機能です。これにより、大規模で複雑なテーマを多数の部品に分割できるようになり、リンティングや構文ハイライトなどの便利な機能を利用できます。
ただし、場合によっては JavaScript ペイロードをオプション で配信したいこともあります。
例えば、特定の Markdown を含む投稿のみを装飾する場合を考えてみましょう。使用するかどうか分からない時点で、100KB もの大規模なライブラリをダウンロードするのは無意味です。
私はこの問題を、以下の変更を踏まえてコンポーネント内で回避策を講じました。
committed 06:51AM - 21 Aug 19 UTC
This change allows themes and components access to theme assets.
This means tha… t inside theme js you can now get the URL for an asset with:
```
settings.theme_uploads.name
```
具体的には以下のようにしました。
import loadScript from "discourse/lib/load-script";
function generateOtp($elem) {
loadScript(settings.theme_uploads.jsotp).then(() => {
// ここに処理を記述
});
}
これにより、以下の対応が必要になりました。
theme authorized extensions に .js を追加する
content security policy script src で、特定のアセットに対する CSP のバイパスを追加する
about.json でアセット名を指定する
テーマコンポーネント作成者にとって、これはあまりにも手間がかかります。このレベルの高度な技術が必要では、配布競争において勝機がありません。
これを使いやすいものにするために、以下の 2 つの選択肢が考えられます。
システムに、アクティブなテーマ内の .js アセットを自動的に CSP 対象とし、デフォルトでテーマが .js をアップロードできるようにする
javascript_cache のような仕組みへ移行し、defer しないテーマ用 JavaScript で利用できるようにする
私は 1 の方に傾いています。.js をテーマの許可拡張子に追加するのは些細な変更であり、自動 CSP も不可能ではないはずです。
@pmusaraj / @Johani / @Osama さん、ご意見をお聞かせください。
Johani
(Joe)
2019 年 8 月 21 日午前 8:40
2
The ability to reference theme uploads in JS is a great addition!
This makes a lot of sense to me because anything you can do in a .js file can already be done in files in the javascripts folder of the theme. So, I don’t see any harm in allowing themes to have .js uploads by default.
Johani
(Joe)
2021 年 12 月 30 日午前 1:52
3
テーマの js アップロードを許可するように CSP を教えることだけが残っています。js ファイルは、しばらくの間、テーマのアップロードとしてデフォルトで許可されています。
テーマの js アップロードが CSP によってブロックされない場合、Image Annotator - Allows you to annotate images in the previewer のようなコンポーネントは、ホームページで依存関係を読み込む必要がなくなります(gzip で約 170kb)。たとえば、そのコンポーネントは、コンポーザーが開かれた場合にのみ、それらの依存関係を読み込む必要があります。さらに、匿名ビューアには決して読み込む必要はありません。
また、この変更により、テーマはメインスレッドからオフで重い処理を実行できる Web Worker ファイルを持つことができるようになります。
上記の引用で「許可」したのは、それらをブロブとして持つことができるためですが、文字列で JavaScript をいじるよりも、個別のファイルで持つ方がはるかに便利です。
sam
(Sam Saffron)
2022 年 3 月 29 日午前 6:59
4
良いニュースがあります。実装は少し複雑ですが、ついにテーマコンポーネントでWebワーカーを使用したい場合のために、ローカルJSアセットのサポートを開始します。
main ← local-theme-asset
opened 06:55AM - 29 Mar 22 UTC
Due to default CSP web workers instantiated from CDN based assets are still
trea… ted as "same-origin" meaning that we had no way of safely instansiating
a web worker from a theme.
This limits the theme system and adds the arbitrary restriction that WASM
based components can not be safely used.
To resolve this limitation a new type of asset can be registered about.json
```
{
"name": "Header Icons",
"local_js_assets" : {
"worker" : "assets/worker.js"
}
}
```
This can then be referenced in JS via:
`settings.local_js_urls.worker`
`local_js_assets` are unconditionally served from the site directly and
bypass the entire CDN, using the pre-existing JavascriptCache
Previous to this change this code was completely dormant on sites which
used s3 based uploads, this reuses the very well tested and cached asset
system on s3 based sites.
Note, when creating local_js_assets it is highly recommended to keep the
assets lean and keep all the heavy working in CDN based assets. For example
wasm files can still live on the CDN but the lean worker that loads it can
live on local.
CSPを回避する他のクリーンな方法はありません。ワーカーファイルを同じドメインから提供することで、この巨大な問題を解決します。