テーマコンポーネントの優先順位

テーマコンポーネントがインストールされた順に実行されているように見受けられます。例えば、A をインストールした後 B をインストールすると、生成されたページには B よりも A のスクリプトが先に含まれます。

これは信頼できる仕様でしょうか?この順序を表示するビューは存在しますか?インストール済みコンポーネントを表示すると、アルファベット順にリストされているようです。

特定のコンポーネントよりも前にアクションを実行する明確な方法があれば良いのですが。私の場合は、TOC コンポーネントより前にアクションを実行したいと考えています(このトピックに関連)。Ember のドキュメントによると、特定のキューにスケジュールされた関数は、スケジュールされた順に実行されるようです。そのため、私のケースではスケジュールの順序が不可欠です。

「いいね!」 2

これに頼ることはできません。代わりに、適切な API でこれを制御すべきです。Ember のイニシャライザーを使って、ある程度は制御可能です。@eviltrout さんは、スケジュールしようとしているコードの例を貼り付けていただければ、具体的なアイデアを持っているかもしれません。

「いいね!」 7

実行しているコードは以下の通りです:

<script type="text/discourse-plugin" version="0.8">
    const { run } = Ember;
    
    api.decorateCooked($elem => {
        run.scheduleOnce("actions", () => {
          // TOC コンポーネントからのスケジュール済みアクションより前に実行する必要があります。
        });
    })

TOC コンポーネントは、アクションをスケジュールするために同じインターフェースを使用しています。

Ember のドキュメントによると、schedule インターフェースは以下のように定義されています:

渡されたターゲットとメソッド、および任意の引数を、指定されたキューに追加し、RunLoop の終了時に実行します

この「追加」という表現は、スケジュールされたアクションが FIFO(先入れ先出し)順序で処理されることを示唆しています。したがって、schedule の呼び出し順序がここで重要になります。

TOC コンポーネントを再インストールしてアンインストールすることで、JavaScript の実行順序を変更しようとしたところ、どうやら幸運な副作用として、TOC の JavaScript が最後に実行されるようになりました。その結果、CSS ルールがこの順序で適用されるようになりました :slight_smile:

テーマのコンポーネントコード配置における順序付けの話題は、非常に重要だと感じています。順序が公式に「未定義」であれば、コンポーネント同士の相互作用を期待することはできません。

もしかすると、コンポーネント間の相互作用は目標外なのかもしれません。しかし、順序付けのヒューリスティック(例えば、同じ名前の他のコンポーネントのファイルに対して、コンポーネントファイルが「前に」または「後に」存在することを宣言する。これはおそらく about.json で定義されるでしょう)があれば、この問題はそれほど難しくないと思います。

私の場合、私が行おうとしていることから考えると、TOC コンポーネントをフォークすることが正しい選択だと考え始めています。

テーマまたはコンポーネントを作成・インストールするたびに、Discourse はそれに ID を割り当てます。そのコンポーネントのページにアクセスすると、URL の末尾(最後の数字)にその ID が表示されているはずです。

component id in the URL

そのコンポーネントがテーマに追加されると、その実行順序は基本的に ID に基づいて決まります(遅延なしでコンソールログを出力する場合など)。つまり、233 は 234 よりも先に実行され、以下同様に続きます。

これは、後続の変更が通常は新しいコンポーネントとして追加されるため、ほとんどの場合問題なく機能します。

長期的には、テーマに追加したコンポーネントのリストの順序を尊重する仕組みにすることも可能ですが、現時点ではロードマップには含まれていません。

本当に必要なのは、イニシャライザーの順序制御です。コードを テーマの JavaScript を作成する新しい方法 に移行しない限り、これは実現できないと思います。この方法を使えば、イニシャライザーに名前と実行順序を指定できます。例えば、次のようなファイルがあるとします。

/javascripts/discourse/initializers/initialize-for-foo.js

内容は以下の通りです。

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "foo",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("foo")
    });
  }
}

また、次のような別のイニシャライザーがあるとします。

/javascripts/discourse/initializers/initialize-for-bar.js

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "bar",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("bar")
    });
  }
}

barfoo の後に実行されるようにしたい場合、after: 引数を追加することで、指定したイニシャライザー名よりも後に実行されるように設定できます。したがって、barfoo の後に実行させるには、initialize-for-bar.js ファイルで以下のようにします。

/javascripts/discourse/initializers/initialize-for-bar.js

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "bar",
+ after: "foo",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("bar");
    });
  }
};
「いいね!」 6

詳しいご指摘をいただき、本当にありがとうございます!TOCコンポーネントに関連する問題(これもご返信いただき、ありがとうございます)を踏まえ、TOCをフォークして依存コードをそのコンポーネント内に移動させました。これは見出しIDに関連するもので、特に重複やコア要素IDとの競合を処理するために、投稿側から制御する必要があるためです。

ドキュメント作成において、私の対応が一部標準から外れていることもありますが、このアプローチが正しいと考えています。

「いいね!」 1