Middleman v4のExternal Pipelineてpreprocess全般に使えるのでは?

ちょっと試しに 4.2.1 でやってみたんだけど、

activate :external_pipeline, {
  name:    :dumb_command,
  command: 'echo "dumb command ..."',
  source:  ''
}

みたいな設定が可能ということが分かった。

つまり、

  • External Pipeline は名前をつけて外部コマンドを呼ぶだけなので、build 前になんでもさせられる
  • ただし、source 指定は必須なので空文字を入れておけば ok
    • nil はダメ

ということか。

外部の API からデータを取得するとかもこれでイケるんだな。Data Files を保存する何かを作ってしまえばなんでもできる。Headless CMS との連携とか。無理に内部構造を理解して Extension を作る必要もない。1

これ、いいんじゃないか?

順番はどうなる?

複数の External Pipeline を指定した場合、

  • 実行する順番は activate した順番
  • ただし build 時以外は default ではスレッドで動くので external pipeline の 実行結果を得る順番は保証できない
    • disable_background_execution: true 指定を加えると制御可能

ということは

  1. 順番に依存する処理を watch 時に行わないのが基本
    • どうしてもという場合は disable_background_execution: true 指定を追加
    • その場合は hot reload / live reload 系はたぶん無理
  2. 順番に依存する処理はそれを起動する sh script などの方で制御する

といった工夫が必要になる。

ちなみにコードで言うとこの辺

class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
  self.supports_multiple_instances = true

  option :name, nil, 'The name of the pipeline', required: true
  option :command, nil, 'The command to initialize', required: true
  option :source, nil, 'Path to merge into sitemap', required: true
  option :latency, 0.25, 'Latency between refreshes of source'
  option :disable_background_execution, false, "Don't run the command in a separate background thread"
..
    if app.build? || options[:disable_background_execution]
      watch_command!(false)
..
  def watch_command!(async)
    @current_thread = ::Servolux::Child.new(
      command: options[:command],
      suspend: 2
    )

    @current_thread.start

    watch_thread = Thread.new do
  1. もちろん CMS 提供側としては gem で配布できることはアピールポイントになるのでちゃんと Extension 作った方がいいけど。 

More