JavaScriptビューをサーバーサイドレンダリングするためのサービス
まず第一に、サーバーサイドレンダリングは、クライアントサイドレンダリングのみに比べて、より優れたユーザーエクスペリエンスを提供します。ユーザーはコンテンツをより速く取得でき、JSが失敗した場合や無効になっている場合でもWebページへのアクセスが可能になり、検索エンジンはより簡単にインデックスを作成できます。
第二に、より良い開発エクスペリエンスを提供します。サーバー側で好みのテンプレートライブラリとJavaScriptの両方で同じマークアップを2回記述するのは、面倒でメンテナンスが困難になる可能性があります。 Hypernovaを使用すると、ユーザーエクスペリエンスを犠牲にすることなく、すべてのビューコードを1か所に記述できます。
最初に、いくつかのパッケージをインストールする必要があります。サーバー、ブラウザコンポーネント、およびクライアントです。開発目的では、サーバーレンダリングするコードと一緒に、または同じアプリケーションにインストールすることをお勧めします。
ここからは、`hypernova-ruby`と、`hypernova-react`を使用した`React`を使用していると仮定します。
npm install hypernova --save
このパッケージには、サーバーとクライアントの両方が含まれています。
次に、開発サーバーを構成しましょう。物事をシンプルにするために、ルートフォルダに構成を配置できます。`hypernova.js`のような名前を付けることができます。
var hypernova = require('hypernova/server');
hypernova({
devMode: true,
getComponent(name) {
if (name === 'MyComponent.js') {
return require('./app/assets/javascripts/MyComponent.js');
}
return null;
},
port: 3030,
});
Hypernovaに必要なのは`getComponent`関数のみです。他のすべての構成オプションはオプションです。`getComponent`に関する注意事項は以下にあります。
このサーバーは、nodeで起動することで実行できます。
node hypernova.js
すべてがうまくいけば、「接続済み」というメッセージが表示されます。問題がある場合は、スタックトレースが`stderr`に表示されます。
サーバーコードがRuby以外の言語で記述されている場合は、Hypernova用の独自のクライアントを構築できます。仕様が存在し、クライアントがどのように機能する必要があるか、および障害が発生した場合のフォールバック方法について詳しく説明しています。
bundle install hypernova
それでは、Rails側でHypernovaのサポートを追加しましょう。最初に、イニシャライザを作成する必要があります。
config/initializers/hypernova_initializer.rb
Hypernova.configure do |config|
config.host = "localhost"
config.port = 3030 # The port where the node service is listening
end
コントローラーでは、ビューパーシャルのHypernovaレンダリングを選択できるように、`:around_filter`が必要です。
class SampleController < ApplicationController
around_filter :hypernova_render_support
end
そして、ビューで`render_react_component`をレンダリングします。
<%= render_react_component('MyComponent.js', :name => 'Hypernova The Renderer') %>
最後に、`MyComponent.js`をサーバーレンダリングするように設定しましょう。レンダリングにはReactを使用します。
const React = require('react');
const renderReact = require('hypernova-react').renderReact;
function MyComponent(props) {
return <div>Hello, {props.name}!</div>;
}
module.exports = renderReact('MyComponent.js', MyComponent);
ページにアクセスすると、Reactコンポーネントがサーバーレンダリングされていることがわかります。確認したい場合は、ページのソースを表示して、`data-hypernova-key`を探します。 HTMLでいっぱいの`div`が表示されている場合、コンポーネントはサーバーレンダリングされています。`div`が空の場合、問題があり、コンポーネントはフォールバック戦略としてクライアントレンダリングされました。
`div`が空だった場合は、ノードサービスを実行している`stderr`を確認できます。
開発者プラグイン for `hypernova-ruby`は、Hypernovaの問題とそのクライアントレンダリングへのフォールバックの理由をデバッグするのに役立ちます。コンポーネントがサーバー側でレンダリングに失敗するたびに、警告とスタックトレースがページに表示されます。
`examples/simple/config/environments/development.rb`に開発者プラグインをインストールできます
require 'hypernova'
require 'hypernova/plugins/development_mode_plugin'
Hypernova.add_plugin!(DevelopmentModePlugin.new)
サーバーの出力を確認することもできます。サーバーは`stdout`と`stderr`に出力するため、エラーが発生した場合は、`node hypernova.js`を実行したプロセスを確認すると、エラーが表示されます。
推奨されるアプローチは、サーバーコードを含むサーバーとHypernovaサービスを含むサーバーの2つの個別のサーバーを実行することです。 JavaScriptコードをHypernovaサービスを含むサーバーにもデプロイする必要があります。
`getComponent`の構成方法によっては、デプロイごとにHypernovaサービスを再起動する必要がある場合があります。 `getComponent`がコードをキャッシュする場合、Hypernovaが新しい変更を受け取るために再起動が不可欠です。キャッシュはサービスの高速化に役立つため、お勧めします。
HTTPリクエストの送信は遅いですか?
特にサーバーを互いに近接させておけば、オーバーヘッドやレイテンシはそれほど多くありません。多くのERBテンプレートをコンパイルするのと同じくらい高速で、ビューコードを統合するという利点があります。
インメモリのJS VMではないのはなぜですか?
これは有効なオプションです。 JSサービスが分離されたサイロ化されたエクスペリエンスを探しているなら、Hypernovaはあなたにぴったりです。このアプローチは、JS VMがまだ利用できない環境にも適しています。
サーバーが停止した場合はどうなりますか?
Hypernovaがコンポーネントをサーバーレンダリングしようとしているときに何か問題が発生した場合、デフォルトで障害モードになり、ページは代わりにクライアントレンダリングされます。これは快適なセーフティネットですが、目標はすべてのリクエストをサーバーレンダリングすることです。
これらは、JavaScriptコードをサーバーレンダリングする際の落とし穴であり、Hypernovaに固有のものではありません。
DOM関連の操作はすべて`componentDidMount`で行う必要があります。 `componentDidMount`はブラウザでは実行されますが、サーバーでは実行されません。つまり、そこにDOMロジックを配置しても安全です。コンポーネントの外側、コンストラクター内、または`componentWillMount`にロジックを配置すると、サーバーにDOMが存在しないため、コードが失敗します。
リクエストが真新しいJavaScript環境を取得するように、VMサンドボックスでコードを実行することをお勧めします。 VMを使用しないことを決定した場合、シングルトンパターンとグローバル変数は、リクエスト間でメモリリークやデータリークのリスクがあることに注意する必要があります。 `createGetComponent`を使用すると、デフォルトでVMが取得されます。