sam
(Sam Saffron)
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もの大規模なライブラリをダウンロードするのは無意味です。
私はこの問題を、以下の変更を踏まえてコンポーネント内で回避策を講じました。
具体的には以下のようにしました。
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)
2
JS でテーマのアップロードを参照できる機能は素晴らしい追加ですね!
これは非常に理にかなっていると思います。なぜなら、.js ファイルでできることは、すでにテーマの javascripts フォルダ内のファイルで実現可能だからです。したがって、デフォルトでテーマが .js アップロードを許可することによる害はないと考えられます。
Johani
(Joe)
3
テーマの js アップロードを許可するように CSP を教えることだけが残っています。js ファイルは、しばらくの間、テーマのアップロードとしてデフォルトで許可されています。
テーマの js アップロードが CSP によってブロックされない場合、Image Annotator - Allows you to annotate images in the previewer のようなコンポーネントは、ホームページで依存関係を読み込む必要がなくなります(gzip で約 170kb)。たとえば、そのコンポーネントは、コンポーザーが開かれた場合にのみ、それらの依存関係を読み込む必要があります。さらに、匿名ビューアには決して読み込む必要はありません。
また、この変更により、テーマはメインスレッドからオフで重い処理を実行できる Web Worker ファイルを持つことができるようになります。
上記の引用で「許可」したのは、それらをブロブとして持つことができるためですが、文字列で JavaScript をいじるよりも、個別のファイルで持つ方がはるかに便利です。
sam
(Sam Saffron)
4
良いニュースがあります。実装は少し複雑ですが、ついにテーマコンポーネントでWebワーカーを使用したい場合のために、ローカルJSアセットのサポートを開始します。
CSPを回避する他のクリーンな方法はありません。ワーカーファイルを同じドメインから提供することで、この巨大な問題を解決します。