Techioz Blog

Ruby で Node.JS サーバーを実行 - Kramdown 数学エンジン

概要

こんにちは、私は Jekyll と Kramdown を使用して、マークダウンで書かれた投稿を HTML にレンダリングしています。私の投稿には多くの数学が含まれています。 KaTeX gemを使用しています。これは私の _config.yml ファイルにあります。

kramdown:
  math_engine: katex

これはコードの一部です。それは機能しますが、これは非常に遅いです。ブログ全体のレンダリングには約 250 秒かかります。これは、execjs ライブラリを使用して katex.js を実行することが原因で発生します。

ExecJS.compile(open(PATH_TO_JS).read).call("katex.renderToString", toRender, {displayMode: dm))

Node.JS を繰り返し作った人を github で見つけました。彼のソリューションを実装したところ、レンダリング時間が 250 秒から 6 秒に短縮されました。しかし、コード自体を見たとき、私の目は血を流し始めました。彼のソリューションは、stdio を使用して Node.JS サーバーと通信します。これは彼のコードの例です:

_plugins/katex.rb:

require 'execjs'

module Jekyll
  module Tags
    class KatexBlock < Liquid::Block

      def initialize(tag, markup, tokens)
        super
        @markup = markup
      end

      def render(context)
        File.open("scripts/katex_server/in", 'w') {
          |file| file.write("#{@markup}\n" + super(context))
        }

        return File.read("scripts/katex_server/out")
      end
    end
  end
end

Liquid::Template.register_tag('latex', Jekyll::Tags::KatexBlock)

スクリプト/katex_server/サーバー:

#!/bin/node

const katex = require('./katex.min.js');
const readline = require('readline');
const fs = require('fs');
const path = require('path');

function recursive_stream() {
    var is = fs.createReadStream(path.join(__dirname, 'in'));

    is.on("data", function(data) {
        request = data.toString();
        parameters = request.split("\n")[0];
        request = request.substring(parameters.length + 1);
        parameters = parameters.trim().split(/\s"/);

        os = fs.createWriteStream(path.join(__dirname, 'out'))
        os.end(katex.renderToString(request, {
            displayMode: parameters.includes("display")
        }));

        recursive_stream();
    }); 
}

recursive_stream();

Ruby スクリプト内で Node.JS サーバーを実行するにはどうすればよいですか? katex.js を使用してラテックスをレンダリングするためにそれを使用するにはどうすればよいですか?

助けてくれてありがとう

解決策

説明からあなたの問題を理解した限りでは、Ruby アプリで katex.js を使用する方法を見つける必要があります。

このために、Ruby アプリケーション内で Node.js を実行する必要はありません。代わりに、このライブラリを使用するための HTTP エンドポイントを提供する別の Web サービスを Node.js で作成できます。将来、docker と kubernetes を使用することにした場合、このアプローチを使用すると、すぐに優れた水平スケーラビリティを得ることができます。また、このアプローチでは、Ruby サーバーに多くの依存関係が生じる一方を他方に埋め込むソリューションとは異なり、サービスを非常にうまく分離できます。

このような Web サービスを作成するには、コードを大幅に変更する必要さえなく、エンドポイントを定義してコードをそれにラップするだけです。

次に、Ruby 側で、Faraday.get(‘url_of_your_service’).body のような http 呼び出しを実行して、レンダリングされたテンプレートを取得します。 kubernetes/aws などを使用する場合、nodejs Web サーバーはほとんど同じマシンまたは同じクラスター内にあるため、これは高速に機能します。