同型アプリケーション。 Reactで未来を見つめる

オリジナル: 同型アプリで未来に反応



同型アプリケーション。 Reactで未来を見つめる



ソフトウェア開発では、物事はしばしば元の状態に戻ります。 そのため、たとえば、インターネットの開発の夜明けに、サーバーはクライアント側ですぐにコンテンツをロードしました。 最近、AngularJSやEmberなどの最新のWebフレームワークの開発に伴い、クライアント側でリクエストを処理し、APIのみにサーバーを使用する傾向が見られます。 ただし、これは唯一の傾向からはほど遠いものです。 現在、これらの2つのアーキテクチャはゆっくりと戻ってきています。



Reactとは何ですか?


公式サイトの定義を使用する場合、



「Reactは、ユーザーインターフェイスの作成に使用されるJavaScriptライブラリです。」


Reactを使用すると、Web開発で再利用可能なコンポーネントを作成できます。 さらに、コンポーネントは簡単かつ簡単に作成されます。 これは実際、Reactの目標です。



Reactが特別な理由は何ですか?


ReactはJavaScript開発者の間で急速に人気を博しましたが、これにはいくつかの理由があります。 その1つ-ReactはFacebookによって開発され、現在では積極的に宣伝および使用されています。 これは、Facebookで作業する開発者が積極的にReactを使用することを意味します。彼らはプログラムを作成し、バグを修正し、新機能を開発します



画像



Reactが急速に人気を博したもう1つの理由は、AngularJS、Backbone.js、Ember、Knockout、および過去数年にわたって雨の後にキノコのように見えた他の有名なMV * JavaScriptフレームワークとは非常に異なることです。 これらのフレームワークのほとんどは、DOMとダブルリンクし、イベントに基づいて更新することで機能します。 これらを使用するには、DOMの存在が必須です。したがって、これらのフレームワークのいずれかを使用してサーバーでマークアップをレンダリングする場合、PhantomJSまたはそれに類似したものを使用する必要があります。



仮想DOM


略語MVC(model-view-controller)を考慮すると、React-むしろ「V」、つまり「view」に帰することができます。 ただし、Reactは他のMV *フレームワークとは異なる方法でビュー機能を実行します。 たとえば、Handlebars、Underscore、AngularJSテンプレートとは関係ありません。 Reactの作業は、「仮想DOM」の概念に基づいています。 Reactは仮想DOMをメモリ内に保持し、変更されるたびにすばやく区別し、1つの更新に結合して、データのパケット全体を実際のDOMに送信します。



このアプローチには多くの利点があり、その主なものはパフォーマンスの大幅な改善です。 他のJavaScriptフレームワークのように、DOMを常に更新する必要はありません。 さらに、Reactはサーバー側とクライアント側の両方で問題なくリクエストを処理できます。



Reactは、React.renderToString()というメソッドを使用します。 コンポーネントを渡すことができます。コンポーネントは、使用された子要素とともにコンポーネントを処理し、コードを返します。 このHTMLコードを取得して、クライアント側に送信するだけです。





次のコンポーネントは、JSXに基づいています。 一見すると、JSXはHTMLとJavaScriptのハイブリッドのように思えるかもしれません。

var HelloWorld = React.createClass({ displayName: "HelloWorld", render() { return ( <h1>Hello {this.props.message}</h1> ); } }); React.render(<HelloWorld message="world" />, document.body);
      
      





ここで、webpack、grunt、gulp、または代替エンジンを介して.jsxをスキップ(または転置)し、次のようなJavaScriptコードを出力として取得する必要があります。

 var HelloWorld = React.createClass({ displayName: "HelloWorld", render: function() { return ( React.createElement("h1", null, "Hello ", this.props.message) ); } }); React.render(React.createElement(HelloWorld, {message: "world"}), document.body);
      
      





HelloWorld.jsxを使用して取得するコードを次に示します。 ご覧のとおり、これは単純なJavaScriptです。 もちろん、HTMLとJavaScriptを混在させることはできない、これは間違いだと主張することもできます。 ただし、一見しただけのようです。 Reactを使用した後、マークアップコンポーネントが近接しているため、コードをより速く記述し、よりボリュームがあり、不可欠なものにできることを理解しています。 HTMLファイルとJavaScriptファイルを絶えず切り替える必要はありません。開発中のコンポーネントのコードはすべて1か所にあります。



React.renderは、HelloWorldコンポーネントを本文に添付します。 当然、任意の要素をそこに追加できます。 コンポーネントのrenderメソッドを呼び出すため、結果はbodyタグ内のDOMに追加されます。



Reactコンポーネントでは、属性を渡したかどうかにかかわらず(たとえば、HelloWorld message = `` world '')、コンポーネントのthis.propsにアクセスできます。 したがって、HelloWorldコンポーネントでは、this.props.messageはworldになります。 そのため、JSXのコードの次の部分に注意してください。

 return ( <h1>Hello {this.props.message}</h1> );
      
      





HTMLが括弧で囲まれていることがわかります。 次に、this.props.messageを中括弧で囲む必要があります。これにより、コンポーネントへのアクセスが許可されます。



さらに、各コンポーネントはその「状態」にアクセスできます。 Reactでは、各コンポーネントは、getState、setState、getInitialStateなどのいくつかの単純なAPIメソッドを使用して状態を管理できます。 後者は、コンポーネントを初期化するときに使用されます。 状態が変化するたびに、renderメソッドはコンポーネントをレンダリングします。 例:

 var Search = React.createClass({ getInitialState() { return { search: "" }; }, render() { return ( <div className="search-component"> <input type="text" onChange={this.changeSearch} /> <span>You are searching for: {this.state.search}</span> </div> ); }, changeSearch(event) { var text = event.target.value; this.setState({ search: text }); } }); React.render(<Search />, document.body);
      
      





上記の例では、getInitialState関数は、コンポーネントの初期状態を含む単純なオブジェクトリテラルを返します。



レンダリング関数は、要素に対してJSXを返します。つまり、入力とスパンの両方がdivでラップされていることを意味します。 JSXでは、1つのアイテムのみが親として返されることに注意してください。 つまり、divを2回返すことはできません。 多くの子を持つ1つのアイテムのみを返すことができます。



onChange = {this.changeSearch}に注意してください。 このコマンドを使用すると、コンポーネントはデータを入力するときにchangeSearch関数を実行できます。



changeSearch関数は、DOMイベントによってトリガーされたイベントを受け取り、入力されたテキストを受け取ります。 次に、setStateにリクエストを行い、レンダーを起動するテキストを渡します。{this.state.search}は、表示された変更を表示します。



ReactはさまざまなAPIで動作します。 ただし、高レベルで作業する場合、単純なコンポーネントを作成するには上記の方法で十分です。



同形JavaScript


Reactを使用すると、いわゆる「同形」アプリケーションを作成できます。 「同形」という言葉は、2015年にすでに人気を集めています。 簡単に言えば、「同型」とは、クライアント側とサーバー側の両方で同じコードを使用できることです。 明らかに、このアプローチには多くの利点があります。



FOUCを取り除く


AngularJS、Ember、およびSPAアーキテクチャを使用する場合、ユーザーが最初にページにアクセスすると、そのすべての要素がロードされます。 SPAアプリケーションでは、ロードに数秒かかることがあり、今日のほとんどのユーザーは少なくとも2秒を期待しています。 コンテンツのロード中、ページのレンダリングは開始されません。 この遅延はFOUC(スタイルのないコンテンツのフラッシュ)と呼ばれます。 同形の開発の主な利点の1つは、サーバー側とクライアント側の同時レンダリングにより、要素の読み込み速度が大幅に加速されることです。



同形アプリケーションのタスクは、使い慣れたサーバーAPIを置き換えることではなく、スタイルが設定されていないコンテンツの流れを取り除くことであり、それによってユーザーがページを操作するエクスペリエンスを改善します(そして、リクエストは常に増え続けています)。



同じコード


同型アプリケーションの大きな利点は、サーバー側とクライアント側で同じコードを使用できることです。 必要なコンポーネントを作成するだけで、あちこちで機能します。 Rails、Asp.NET MVCなど、他のほとんどのシステムでは、サーバー側レンダリング用にerbとcshtmlがあります。 さらに、ハンドルバーやHogan.jsなどのテンプレートを使用する必要がありますが、これらは多くの場合ロジックを複製します。 Reactでは、サーバー側とクライアント側の両方で同じコンポーネントが同等に機能します。



プロセス改善


サーバー側のレンダリングにより、クライアントがサイトを表示するために必要なHTMLスケルトンをすばやく転送できます。 その後、クライアント側でより多くの要素を処理することにより、状況を改善できます。



原則として、アフリカの最もシンプルな「クラムシェル」を使用するユーザーと、Retinaディスプレイを備えた最新のMcBook Proを使用し、最新の4kモニターに接続するユーザーに、ページを表示したりアプリケーションを使用したりするのと同じ快適さを提供することは簡単な作業ではありません。



Reactでは、物事は単純に異なるコンポーネントを渡すよりも少し複雑です。 サーバー側でReactコンポーネントを処理し、HTMLコードのスケルトンをクライアントに送信すると、クライアント側のReactは同じHTMLコードを見つけ、既存の要素にイベントコンテナを添付します。 出来上がり!



つまり、ページをレンダリングするために必要なHTMLコードの部分のみを送信すれば十分です。 すべての追加アイテムは、クライアント側で取得および処理できます。 サーバー側からの高速ロードの利点と、同じコンポーネントを再利用できる可能性があります。



Expressで同形アプリケーションを作成する


Expressは、最も人気のあるNode.js Webサーバーの1つです。 Reactを使用してExpressでアプリケーションを起動および実行することは問題ではありません。



ExpressにReactレンダリングを追加するには、いくつかの手順が必要です。 最初に、node-jsxを追加し、次のようにプロジェクトに反応します。

 npm install node-jsx --save npm install react --save
      
      





次に、public / javascripts / componentsディレクトリにベースapp.jsxファイルを作成する必要があります。 これを行うには、前に使用した検索コンポーネントが必要です。

 var React = require("react"), Search = require("./search"); var App = React.createClass({ render() { return ( <Search /> ); } }); module.exports = App;
      
      





ここでは、reactとSearch.jsxコンポーネントが必要です。 Appコンポーネントのrenderメソッドでは、単にSearchでコンポーネントを使用できます。



次に、Reactを使用してレンダリングする予定のルーターの1つに次のコードを追加する必要があります。

 require("node-jsx").install({ harmony: true, extension: ".jsx" });
      
      





これにより、.jsxファイルの使用が必要になります。 そうしないと、Node.jsはそれらの解析方法を理解できません。 ハーモニーオプションを使用すると、ECMAScript 6コンポーネントを使用できます。



次に、コンポーネントを要求し、それをReact.createFactoryに転送する必要があります。React.createFactoryは、コンポーネントを呼び出すことができる関数を返します。

 var React = require("react"), App = React.createFactory(require("../public/javascripts/components/app")), express = require("express"), router = express.Router();
      
      





次に、ルート自体でReact.renderToStringを記述し、コンポーネントを渡します。

 router.get("/", function(req, res) { var markup = React.renderToString( App() ); res.render("index", { markup: markup }); });
      
      





最後に、[表示]タブでマークアップ出力を取得します。

 <body> <div id="content"> {{{markup}}} </div> </body>
      
      





サーバー側のコードについては以上です。 次に、クライアント側で何をする必要があるかを見てみましょう。



Webpack


Webpackは、さまざまなローダーを使用してファイルを処理するだけでなく、静的オブジェクト(JavaScript、CSS、画像など)を単一のファイルに収集できるJavaScriptパッカーです。 CommonJSまたはAMDモジュール構文を使用してJavaScriptコードを記述できます。



React .jsxファイルの場合、webpack.configureファイルを少し構成して、すべてのjsxコンポーネントをコンパイルする必要があります。



Webpackを使い始めるのは簡単です:

 npm install webpack -g # Install webpack globally npm install jsx-loader --save # Install the jsx loader for webpack
      
      





次に、webpack.configure.jsファイルを作成します。

 var path = require("path"); module.exports = [{ context: path.join(__dirname, "public", "javascripts"), entry: "app", output: { path: path.join(__dirname, "public", "javascripts"), filename: "bundle.js" }, module: { loaders: [ { test: /\.jsx$/, loader: "jsx-loader?harmony"} ] }, resolve: { // You can now require('file') instead of require('file.coffee') extensions: ["", ".js", ".jsx"], root: [path.join(__dirname, "public", "javascripts")], modulesDirectories: ["node_modules"] } }];
      
      





次に、上記のコードを検討します。 ここにあります:



モジュールオブジェクトを使用すると、ブートローダーを構成できます。 ローダーを使用すると、ファイル拡張子をテストしてからローダーを介して転送できます。 CSS、Sass、HTML、CoffeeScript、JSXには多くのダウンローダーがありますが、この場合、必要なのはjsx-loaderだけですか?Harmony。 「クエリ文字列」などのオプションをブートローダー名に添付できます。 この場合、?Harmonyでは、モジュールでECMAScript 6構文を使用できます。 testは、拡張子が.jsxのファイルをjsx-loaderに転送するようWebpackに指示します。



解決には、わずかに異なる画像が表示されます。 まず、拡張機能は、Webpackがrequireを指定したときに特定の種類の拡張子を持つファイルをスキップするように指示します。 このため、require(“ ./file.js”)ではなくrequire(“ ./ file”)を使用できます。 さらに、ルートを指定します。これは、本質的には、ファイルが抽出されるルートです。 最後に、modulesDirectoriesを使用して、Webpackがnode_modulesディレクトリからモジュールを取得できるようにします。 そのため、たとえばNode.jsのアプリケーションの場合と同様に、npm install handlebarsおよびrequire(「handlebars」)を使用してHandlebarsをインストールできます。



クライアント側コード


public / javascripts / app.jsの場合、Expressで使用したものと同じAppコンポーネントが必要です。

 var React = require("react"), App = React.createFactory(require("components/app")); if (typeof window !== "undefined") { window.onload = function() { React.render(App(), document.getElementById("content")); }; }
      
      





typeof window!==” undefined”コマンドを使用して、ブラウザにいることを確認してください。 次に、ウィンドウイベントをonloadにアタッチし、React.renderを呼び出してApp()に転送します。 次に、ロード用のDOM要素が必要です。 サーバー側のReactマークアップで使用したものと同じ要素、つまり#contentでなければなりません。



上記の例の検索コンポーネントはサーバーで処理され、クライアントに送信されました。 クライアント側のReactは、レンダリングされたマークアップを受け入れ、それにイベントコンテナーを添付します! これは、JavaScriptのロード中にページを簡単に表示できることを意味します。



この記事に記載されているすべてのコードはGitHubで入手できます



おわりに


Webアーキテクチャは周期的に進化しています。 最初は、サーバー側でのみレンダリングが行われ、その後クライアントにデータが送信されました。 その後、JavaScriptが登場し、ページ上の簡単な操作に使用するようになりました。 最後に、JavaScriptが大きく進化したため、JavaScriptを使用してクライアント側でレンダリングし、サーバーを使用してAPIを介してデータを取得する大規模なアプリケーションを作成できるようになりました。



2015年に、ほとんどすべてのデータを処理するのに十分なプロセッサとメモリを備えた強力なサーバーが自由に使えることに気付き始めました。 アプリケーション開発への同型アプローチは、2つの世界のベストを提供します。サーバー側とクライアント側の両方でJavaScriptを使用できます。これにより、読み込み速度が向上し、追加の要素が読み込まれるとページの情報をより速く表示できますクライアント側。



Reactは最初のフレームワークの1つであり、この種類の動作を実装するフレームワークは間違いなく既に多数あります。 Ember開発者はすでに同型アプリケーションに取り組んでいます。 これらのフレームワークの開発を見るのは非常に興味深いと確信しています!



著者について


画像

Jonathan Creamerは、Lonely PlanetのシニアWeb開発者です。 彼はJavaScript、特にWebアプリケーションアーキテクチャとNode.js開発が好きです。 さらに、彼はASP.NET MVC、Ruby on Rails、ColdFusionで豊富な経験を持っています。 ジョナサンは13歳でテネシー州フランクリンのスタートアップの1つで仕事を始めたときにWeb開発を開始しました。 その後、彼はミドルテネシー州立大学で開発者として学びました。 彼は現在、妻と娘と一緒にテネシー州マーフリーズボロに住んでいます。



翻訳作業: greebn9k (セルゲイグリブニャック)、 セニンロムローマセニン )、 シルマリオン (アンドレイハカレフ)

シングリー



All Articles