JSONデータではなくHTMLを返すエンドポイントの実際の問題は何ですか?


77

PHPの学習を始めたとき(約5〜6年前)、Ajaxについて学び、「フェーズ」を経ました。

  1. サーバーはHTMLデータを返し、DOMの innerHTML 内に配置します
  2. XMLなどのデータ転送形式について学習し(「ああ、そういうことです」と言ってから)、JSONを学びます。
  3. JSONを返し、バニラJavaScriptコードを使用してUIを構築します
  4. jQueryに移動します
  5. API、ヘッダー、HTTPステータスコード、RESTCORS、およびBootstrapについて学ぶ
  6. SPA、およびフロントエンドフレームワーク(ReactVue.js、およびAngularJS)およびJSON API標準を学びます。
  7. いくつかのエンタープライズレガシーコードを受け取り、検査すると、ステップ1で説明されていることを実行していることがわかります。

このレガシコードベースで作業していたので、HTMLを返すことができるとは考えていませんでした(つまり、私たちは今、プロですよね?)。そのため、 Ajax呼び出しが生成されます。「プログラマー」に尋ねたとき、彼はHTMLを返し、innerHTMLでDOMに直接追加されると言った。

もちろん、これは受け入れがたいものでした。これをJSONエンドポイントにリファクタリングする方法を考え始め、エンドポイントの単体テストなどを考え始めました。ただし、このコードベースにはテストがありません。単一ではありません。そして、それは20万行以上です。もちろん、私のタスクの1つには、すべてをテストするためのアプローチの提案が含まれますが、現時点ではまだ取り組んでいません。

だから私はどこにも、不思議に思っています:テストがまったくないのであれば、このJSONエンドポイントを作成する特別な理由はありません(「再利用可能」ではないため、文字通り、アプリケーションですが、HTMLデータを返すため、これはすでに暗示されていると思います)。

これを行うことで正確に何が間違っていますか?



3
関連:stackoverflow.com/questions/1284381/… <-SOで非常に良い答え。
マチャド

73
HyperTextを返すHyperText Transfer Protocolを使用するサーバー?!ホラー!
アンディ

3
@Andy正直に言うと、実際には汎用メッセージ転送プロトコルです。FTPとは対照的に、ハイパーテキストの転送に固有のものは何もありません。FTPはファイルやディレクトリに固有のことについて多くを語っています。
Joker_vD

4
@Joker_vD GMTPと呼ばれるプロトコルを聞いたことがありません。状況は進化しており、HTTPを介して他の種類のコンテンツを送信できますが、本来の目的ではありませんでした。私のポイントは、HTTPを使用してHyperText以外のコンテンツを送信できるからといって、本来の目的に使用することはもはや有効ではないと示唆するのは馬鹿げているようです。
アンディ

回答:


114

JSONデータではなくHTMLを返すエンドポイントの実際の問題は何ですか?

何もない、本当に。各アプリケーションには異なる要件があり、アプリケーションがSPAとして設計されていない可能性があります。

あなたが引用したこれらの美しいフレームワーク(Angular、Vue、Reactなど)は、開発時に利用できなかったか、組織で使用するエンタープライズの「承認済み」のものではなかった可能性があります。

これをお伝えします。HTMLを返すエンドポイントは、JavaScriptライブラリへの依存を減らし、DOMオブジェクトを作成するためにJSコードを解釈/実行する必要がないため、ユーザーのブラウザーの負荷を減らします。要素を解析してレンダリングするだけです。もちろん、これは合理的な量のデータについて話していることを意味します。10メガバイトのHTMLデータは妥当ではありません。

ただし、HTMLを返すことに何の問題もないので、JSON / XMLを使用しないことで失うのは、基本的にエンドポイントをAPIとして使用できる可能性です。そして、ここに最大の質問があります:それは本当にAPIである必要がありますか?

関連:JSON APIからHTMLを返すことはできますか?


4
それは単に「好み」だと言う前に一歩後退します。あなたがしなければならないいくつかの「大したこと」の決定があります:それはAPIであるかどうか、私はクライアント上のJSONデータとしてこれを扱う適切なライブラリを持っていますか、どのタイプのクライアントをサポートしますか(Javascriptのないブラウザ、たとえば、私のプログラマは、より良い活用した戦略のCPU対時間)、どのような音量私が使用するために利用できる持っている、などなどなど
マチャド

7
「JSコードを解釈してDOMオブジェクトを作成する必要はありません。DOMオブジェクトは既に存在します。単にレンダリングするだけです」-HTMLは既に存在します(ネットワークに到着したら)。ブラウザはHTMLを解析し、そこからDOMオブジェクトを作成する必要があります。
ポールD.ウェイト

7
HTMLがAPIとして機能できない理由はありません。ゼロ。無し。実際、HAL + JSONとHAL + XMLは、HTMLと非常によく似ています。RESTについての優れた講演です。エンドポイントからHTMLを返すことに関する関連部分は、終わり近くです。youtu.be/pspy1H6A3FM個人的には、すべてのエンドポイントがjsonとHTMLの両方を返すようにします。発見可能なサービスを作成している場合、それは本当に簡単に閲覧できます... 息をのむ ...ブラウザー。
ラバーダック

4
それはあなたが実際に新しい方法でそれを使用しようとすることを本当に気にしているデータを抽出するのは完全な雌犬だからです?
DeadMG

4
HTML over HTTPを提供していますか?これは何ですか?ウェブサイト?
Ant P

50

JSONとHTMLは、2つの異なる意味上の目的を果たします。

Webページにデータを入力する場合は、JSONを使用します。Webページの一部からWebページを構築する場合は、HTMLを使用します。

彼らは同じもののように聞こえるかもしれませんが、そうではありません。1つには、サーバーから返されたHTMLを使用してWebページの一部を構築するとき、サーバー側で作業していることですWebページにデータをバインドしているときは、クライアント側で作業しています。

また、特定のページに緊密にバインドされないように、HTMLに注意する必要があります。この方法で部分ページをレンダリングするポイントは、部分ページを再利用できるようにすることです。部分ページを具体的にしすぎると、他のページに合成されません。JSONはWebページ構造ではなく単なるデータであるため、この問題はありません。


1
「1つには、HTMLを使用してWebページの一部を構築しているとき、サーバー側で作業しています。」どうして?なぜそうなのか、理由はわかりません。クライアントは必要なデータを要求できるので、最初のページの読み込みについてはもちろん、間違いなくそうです。
DeadMG

3
@DeadMG「サーバーから返されたHTMLを使用してWebページの一部を構築しているとき」(サーバーから返されたJSONを使用するのではなく)
-user253751

確かに、しかしそれが事実であるという動機はほとんどないので、私はその点を見ません。
DeadMG

6
@DeadMGこれまでのケースに対する小さな動機は?サーバーがHTMLを返すには?これが文字通り、このSEの質問全体の目的です。
user253751

問題は、HTMLを返す必要があるかどうかです。最初の応答はHTMLでなければならないことは明らかですが、他のAPIがHTMLを返す必要がある明確な理由はありません。
DeadMG

22

主な問題は、サーバーとクライアントを緊密に結合することです。クライアントはHTML構造を知っている必要があります。また、エンドポイントを新しい方法または新しいアプリケーションで再利用することがより困難になります。

プレーンデータを返し、クライアントにレンダリングさせると、結合が減少し、柔軟性とテスト容易性が向上します。クライアントでモックデータの単体テストを実行し、サーバーで単体テストを実行して目的のデータをテストできます。


11
HTMLは合理的に汎用化できます。たとえば、箇条書きリストを返し、それをdivに詰め込むと、一般的なCSSによるスタイル設定の対象になります。
ロバートハーヴェイ

10
今回スパンに詰め込む必要がある場合、それはそれほど便利ではありません。または、HTMLでレンダリングされていない別のアプリケーションでレンダリングします。
DeadMG

2
常に HTMLを作成するように言い直しますが、そのHTMLの形式はすべての使用法で常に完全に一貫している必要がありますが、これは非常に役立つ保証ではありません。例えば、我々のアプリでは、我々はリストを持っているが、我々は実際には使用しませんでしたulし、li代わりに各1作るに変更div(理由は覚えていません)。サーバーがulsとlis を含む大量のHTMLを返した場合は注意が必要でした。
DeadMG

2
そもそもデータを返して、クライアントがそれを適切と思われるHTMLとしてレンダリングできるようにする場合(最初にレンダリングする場合でも)、最初に保証を得るのは無意味なようです
-DeadMG

1
HTMLを返すことが望ましいと思われる唯一のシナリオは、クライアントがレンダリング自体を実行するのに十分なリソースを持っていない場合です。
DeadMG

14

少し後方にあると思います。あなたは言う:

テストがまったくないため、このJSONエンドポイントを作成する特別な理由はありません

あなたがそのよう適切なエンドポイントを使用する理由は次のようになります可能性があり、それをテストします。テストを行わないことが、いくつかの記事を書き始める非常に良い理由だと思います。つまり、テストに適したロジックがある場合。

20万行のコードはリファクタリングするのが多く、おそらく維持するのが難しいでしょう。いくつかのエンドポイントを分割してテストすることは、開始するのに適した場所です。

別の理由は、サーバーをクライアントから分離することです。将来、アプリケーションの設計やレイアウトが変更された場合、HTML出力よりも適切なデータ形式で作業する方が簡単です。理想的な世界では、クライアントを変更するだけで、サーバーにまったく触れる必要はありません。


レイアウトの変更に関するポイントは、基になるデータからテンプレートを分離する必要があるように聞こえますが、これらのテンプレートがクライアント上にある必要はありません。実際、それらが存在しない理由はたくさんあります。たとえば、レンダリングがクライアント上にある場合、クライアントからデータを隠すことはできません。HTMLパーシャルは、完全なHTMLページと同じテンプレートシステムによって出力されている場合、正常にスキン変更できます。
IMSoP

6

Webページを構築するには、少なくとも3つの方法があります:

  • ページサーバー側全体を生成します。
  • サーバーから単純な骨組みページとコード(JavaScript)を返し、ページにそのデータをフェッチさせ、HTMLクライアント側にレンダリングさせます。
  • 部分的なページとコードを返し、コードがページにドロップできるHTMLの事前にレンダリングされたブロックを取得するようにします。

最初のものは大丈夫です。2番目も問題ありません。最後の問題です。

理由は簡単です。HTMLページの構成を完全に切り離された部分に分割したことになります。問題はメンテナンスの1つです。これで、UIの詳細の管理を担当する2つの独立したエンティティができました。したがって、CSSと他の同様の詳細を2つの別々の部分の間で同期させておく必要があります。サイドバーの幅を変更しましたか?すばらしいです。サイドバーの幅に関する仮定が保持されなくなったため、戻ってくるHTMLフラグメントによって水平スクロールが発生するようになりました。そのブロックの背景色を変更しましたか?素晴らしい、今ではあなたのHTMLフラグメントのフォントの色は衝突します。なぜなら、それは異なる背景色を想定し、誰かがそのエンドポイントをテストするのを忘れたからです。

ポイントは、1か所(つまり、プレゼンテーションロジック)に集中する必要がある知識を分割したことです。これにより、すべての要素を正しく組み合わせることがより困難になります。JSON APIを使用することにより、代わりにフロントエンドですべてのロジックを保持することも、最初からデータをHTMLにレンダリングする場合はサーバーサイドテンプレートにすべて保持することもできます。プレゼンテーションの知識/ロジックを単一の場所に保持することであるため、一貫して、単一のプロセスの一部として管理できます。HTML / CSS / JSは、多くの小さな断片に分割せずにまっすぐに保つのに十分なほど困難です。

JSON APIには、プレゼンテーションロジックから完全に独立してデータを利用できるという追加の利点もあります。これにより、モバイルアプリとWebページの両方など、複数の異なるプレゼンターが同じデータを使用できます。特に、ブラウザなしでデータを消費できるようにします(モバイルアプリや夜間のcronジョブなど)。これらの消費者はHTMLを解析することさえできません。(もちろん、これは必然的にデータが異なる消費者間で同じであるか、一方が他方のサブセットを使用できる状況に依存しています。)この機能が必要かどうかは、特定のアプリケーションの要件によって異なります。関係なく、ロジックが必要です。ただし、事前に実装すれば、将来の成長に備えることができます。


2
重複する表示ロジックを避けることは、HTMLページフラグメントレンダリングする正当な理由なると実際に考えています。サーバー上のページの一部(ヘッダーと基本レイアウトなど)をレンダリングし、クライアント上のJSONデータに基づいて他のパーツを生成すると、 2つの異なるテンプレートセットがあります。サーバーでパーシャルをレンダリングすると、このロジックが中央のプレゼンテーションレイヤーに戻り、ページ全体を静的にアセンブルする場合と同じテンプレートを使用して個々のコンポーネントをレンダリングできます。
IMSoP

1
私はあなたにそのための千upvotesを与えたい、モバイルに言及一つだけだ
ロヴィス

1
@IMSoP 動的ページが必要場合は、フロントエンドロジックが必要です。それでもフラグメントをサーバー側でレンダリングする場合は、フロントエンドの前提条件がフラグメントを構築するサーバーの前提条件と一致することを確認する必要があります。その依存関係を破ることはできません。完全に分割されたシステムに分割されている場合、その知識を同期させることは困難です。フロントエンドでレンダリングするだけの場合、これらの仮定は集中化されます。サーバー側のテンプレートで動的フロントエンドと初期状態を混在させることも避けたいと思います。フロントエンドを起動する「ブートストラップ」の方が簡単です。
jpmc26

4

私は、サーバーがHTMLフラグメントを返し、UIがそれを何らかの要素の.innerHTMLに割り当てることに何の問題もないと言うでしょう。私の意見では、これが非同期JavaScriptコードを開発する最も簡単な方法です。利点は、JavaScriptを使用してできる限り少なくし、制御されたバックエンド環境でできる限り多くすることです。ブラウザでのJavaScriptサポートはさまざまですが、バックエンドは常に同じバージョンのバックエンドコンポーネントを使用していることを忘れないでください。つまり、バックエンドで可能な限り多くのことを行うと、バージョンの非互換性が最小限に抑えられます。

さて、たまにHTMLフラグメント以上のものが必要になることがあります。たとえば、ステータスコードとHTMLフラグメント。次に、statusCodeとHTMLの2つのメンバーを持つJSONオブジェクトを使用できます。2番目のメンバーは、statusCodeを確認した後、いくつかの要素の.innerHTMLに割り当てることができます。したがって、JSONを使用し、innerHTMLを使用することは、代替の排他的アプローチではありません。それらは一緒に使用できます。

JSONを使用することで、同じ応答に複数のHTMLフラグメントを含めることもでき、それらは複数の要素の.innerHTMLに割り当てられます。

要約すると、.innerHTMLを使用してください。コードを可能な限り多くのブラウザバージョンと互換性があります。さらに必要な場合は、JSONと.innerHTMLを一緒に使用します。XMLを避けます。


4

原則として何も悪いことはありません。問題は、何を達成したいですか?

JSONはデータの送信に最適です。代わりにHTMLを送信し、クライアントがHTMLからデータを抽出することを期待する場合、それはゴミです。

あなたは一方、欲しい HTMLとしてレンダリングされようとしているHMTLを送信するために、その後、HTMLとして送信-代わりに、文字列にHTMLをパックJSONに文字列を回し、JSONを送信するので、他の側でそれをデコード、文字列を取得し、文字列からHTMLを抽出します。

そしてちょうど昨日、2つの項目を配列に入れ、配列をJSONに変え、JSONを文字列に入れ、文字列を配列に入れ、配列全体をJSONに変え、それをクライアントに送信するコードに遭遇しました。 JSONは、文字列を含む配列を取得し、文字列を取得し、文字列からJSONを抽出し、JSONをデコードし、2つの項目を持つ配列を取得しました。しないでください。


+1正確に。最初の質問は、何を受け取る必要があるかです。エンドポイントがサイドバー広告をHTMLの一部、またはフッター、または同様の要素として返す場合、ほとんど問題はありません。
SQB

3

これはすべてAPIの目的に依存しますが、一般的にあなたが説明するのは懸念分離のかなり強い違反です:

最新のアプリケーションでは、APIコードがデータを担当し、クライアントコードがプレゼンテーションを担当する必要があります。

APIがHTMLを返すとき、データとプレゼンテーションを密接に結合しています。APIがHTMLを返す場合、そのHTMLで(簡単に)できることは、それを大きなページの一部として表示することだけです。別の角度から見ると、APIに適しているのは、ページにHTMLを提供することだけです。さらに、クライアントコードとサーバーコードの両方にHTMLを広げました。これにより、メンテナンスが頭痛になります。

APIがJSONまたは他の形式の純粋なデータを返す場合、より便利になります。既存のアプリは引き続きそのデータを消費し、適切に提示できます。ただし、今では、他のことはAPIを使用して同じデータにアクセスできます。繰り返しますが、メンテナンスも簡単です。すべてのHTMLが1か所にあるため、サイト全体のスタイルを変更する場合は、APIを変更する必要はありません。


5
「最新のアプリケーションでは、APIコードがデータを担当し、クライアントコードがプレゼンテーションを担当する必要があります。」なぜこれが常に当てはまるのでしょうか?私はこれが一般的なパターンであり、特定のことを簡単にすることに同意しますが、それを「すべき」のレベルに上げる理由はないと思います...状況によっては、別の決定をしたい理由が確かにあります。
ジュール

@Jules。なぜなら、APIとクライアントを持っている場合、両方のレンダリングを担当することは懸念の分離に違反するからです。(現在、必ずしもAPIとクライアントを持っている必要はありません。1つのコンポーネントのみを持ち、プレゼンテーション全体を実行できます。しかし、APIはありません)
-njzk2

@ njzk2 APIがHTMLデータを配信するからといって、それがレンダリングされたわけではありません。たとえば、HTMLをblobとして扱い、データベースに保存する場合があります。また、クライアントではなくサーバー上でいくつかのレンダリングが必要になる場合があり(検索エンジンに静的ページを提供するなど)、その機能を再利用することで重複を排除することができます。
ジュール

1
また、すべてのレンダリングがサーバーで行われ、クライアントが配信されたHTMLをDOMの事前定義されたスロットに差し込むだけのクライアントとAPIのペアを作成することも完全に可能です。Jqueryには、この種のクライアント専用のモジュール全体があります。これは、かなり一般的でなければならないことを示唆しています。
ジュール

1
@Julesの多くのものはかなり一般的ですが、それが合理的である理由ではありません。
njzk2

2

HTMLは特定の設計と使用に結び付けられています。

HTMLでは、ページレイアウトを変更する場合は、サーバー呼び出しによるHTMLの生成方法を変更する必要があります。通常、これにはバックエンドのプログラマが必要です。これで、これらの更新を処理するバックエンドプログラマがいます。定義上、最高のhtmlライターではありません。

JSONでは、ページレイアウトが変更されても、既存のJSONサーバー呼び出しは必ずしも変更する必要はありません。代わりに、フロントエンド開発者、またはデザイナーでさえ、テンプレートを更新して、同じ基本データから必要な異なるHTMLを生成します。

さらに、JSONは他のサービスの基盤にもなります。同じ基本データをさまざまな方法で表示する必要があるさまざまな役割がある場合があります。たとえば、注文ページに製品に関するデータを表示する顧客Webサイトや、一般的な顧客が利用できない他の情報と並んで、同じデータを非常に異なるレイアウトで表示する営業担当向けの内部販売ページがあるとします。JSONを使用すると、両方のビューで同じサーバー呼び出しを使用できます。

最後に、JSONのスケーラビリティが向上します。近年、クライアント側のjavascriptフレームワークを使いすぎてしまいました。実際に一歩下がって、どのJavaScriptを使用しているのか、それがブラウザのパフォーマンスにどのように影響するのか、特にモバイルデバイスの場合について考え始める時だと思います。つまり、単一のサーバーではなく、サーバーファームまたはクラスターを必要とするほど大きなサイトを実行している場合、JSONはより優れた拡張性を発揮できます。ユーザーはブラウザで処理時間を無料で提供します。これを利用すれば、大規模な展開でサーバーの負荷を軽減できます。また、JSONは使用する帯域幅が少ないため、十分な大きさであれば適切に使用すれば、JSONはかなり安くなります。もちろん、2KBのデータを7KBのhtmlに解析するために40KBのライブラリをフィードすることになった場合、さらに悪化する可能性もあります。しかし、JSONがパフォーマンスとコストを改善する可能性があります。


1

そのようなエンドポイントが要件を満たしていれば、問題はありません。既知のコンシューマーが効果的に解析できるHTMLを吐き出す必要がある場合、確かに、なぜですか?

問題は、一般的な場合、エンドポイントが、標準のパーサーによって整形式で効果的に解析可能なペイロードを吐き出したいことです。そして、効果的に解析可能ということは、つまり、宣言的に解析可能ということです。

クライアントが強制的にペイロードを読み取り、そこからループとifステートメントを使用してオープン情報ビットをこじ開ける場合、事実上解析できません。また、HTMLはその方法であるため、整形式である必要はありません。

これで、htmlがxmlに準拠していることを確認すれば、ゴールドです。

とはいえ、これには重大な問題があります。

これをお伝えします。HTMLを返すエンドポイントは、JavaScriptライブラリへの依存を減らし、DOMオブジェクトを作成するためにJSコードを解釈/実行する必要がないため、ユーザーブラウザーの負荷を減らします。要素を解析してレンダリングするだけです。もちろん、これは合理的な量のデータについて話していることを意味します。10メガバイトのHTMLデータは妥当ではありません。

どのようにカットしても、それは悪い考えです。数十年にわたる産業の経験から、一般に、データ(またはモデル)をその表示(またはビュー)から分離することをお勧めします。

ここでは、JSコードを迅速に実行するために2つを統合しています。そして、それはミクロな最適化です。

非常に些細なシステムを除き、これを良いアイデアとは見ていません。

私のアドバイス?しないでください。HC SVNT DRACONES、YMMVなど


0

JSONは、構造化データの単なるテキスト表示です。クライアントには当然、データを処理するためのパーサーが必要ですが、事実上すべての言語にはJSONパーサー関数があります。JSONパーサーを使用する方が、HTMLパーサーを使用するよりもはるかに効率的です。フットプリントがわずかです。HTMLパーサーではそうではありません。

PHPで使用するのはjson_encode($data)、解析するのは相手側のクライアント次第です。また、WebサービスからJSONデータをフェッチするとき$data=json_decode($response)に使用するだけで、変数の場合と同様にデータの使用方法を決定できます。

モバイルデバイス用のアプリを開発する場合、モバイルアプリがデータの解析にWebブラウザーをほとんど使用しないのにHTML形式が必要なのはなぜですか?多くのモバイルアプリはJSON(最も一般的な形式)を使用してデータを交換します。

多くの場合、モバイルは従量制プランであると考えると、JSONよりもはるかに多くの帯域幅を必要とするHTMLを使用したいのはなぜですか?

HTMLの語彙が制限され、JSONがデータを定義できるのに、なぜHMTLを使用するのですか?{"person_name":"Jeff Doe"}HTMLがデータを定義するのではなく、HTMLパーサーの構造を定義するだけなので、HTMLがデータについて提供するよりも有益です。

JSONはHTTPとは関係ありません。JSONをファイルに入れることができます。構成に使用できます。ComposerはJSONを使用します。これを使用して、単純な変数をファイルに保存することもできます。


0

正しいか間違っているかを分類することは困難です。IMO、私が尋ねる質問は、「すべきか」、または「より少ない力でできるか?」です。

すべてのエンドポイントは、できるだけ少ないコンテンツで通信するよう努力する必要があります。信号対雑音比は通常、HTTPコード<JSON <XHTMLです。ほとんどの場合、最もノイズの少ないプロトコルを選択することをお勧めします。

@machadoによるクライアントブラウザーの負荷に関する点は異なります。これは、最新のブラウザーでは問題ではないためです。それらのほとんどは、HTTPコードとJSON応答を適切に処理する機能を備えています。また、現時点ではテストは行っていませんが、ノイズの少ないプロトコルの長期的なメンテナンスは、上記のプロトコルよりも安くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.