ここのspaはシングルペ―ジアプリケーションの略称ですよね?
自分の認識が正しいかどうかわかりませんが、シングルにこだわりすぎるとよくないでしょうか。以下の画面分け方はいかがですか。
アプリをメイン画面で分けて、一つずつのシーンにします。そのシーンに必要なサブ画面を全部メイン画面にインポートします。そして、ログイン画面、メインメニュー画面、業務画面1,業務画面2,など。
エラーについて、回復可能のエラーはメイン画面内で表示します。回復不可のエラーは、共通システムエラーメイン画面で表示します。
spaはajaxの思想を画面設計での運用ですが、100画面を一つにまとめることではないです。業務か機能かの単位で分けて、操作の便利さと作りの便利さとバランスを取れば良いでしょうと思います。
SPA開発についての疑問
質問したいこと
-
JavaとJavaScriptのみでSPAの作成を考えています。
SPAの開発について、色々な記事を見ているとhtmlを取得して、特定の要素を書き換えるみたいなことをどこでも見るのですが、htmlやcss、jsは全て最初のhtmlに含めてしまい、セキュリティ的に問題がある情報など(データベースの情報など)のみをサーバーからその都度取得して、ページを更新するのではダメなのでしょうか?
正直ページ構造なんかは見られてもいいと思っていて、表示する中身さえ守っていればいいのでは?と思ってしまっています。 -
SPAでエラーページを設定する場合、最初に表示するhtmlにエラーページを埋め込もうと思っているのですが、例えばユーザーが存在しないURLにアクセスした場合などの時用に、静的なhtmlを埋め込むエラーページとは別に用意する必要があるのでは?と考えています。
そうすると同じようなエラーページを複数作成することになり、なんか嫌だなと思うのですが、なにかいい方法や、SPAでの実装の仕方などあるのでしょうか?
2Answer
Comments
@019_takorice_
Questioner解答ありがとうございます。
SPAはシングルペ―ジアプリケーションの略称のことを指してる認識で相違ないです。解答頂いた内容は、アプリごとに柔軟に対応していいということでしょうか?
イメージは以下のような感じですかね?<section id="main"> <div>ようこそ</div> ~~~以下省略~~~ </section> <section id="login"> <div id="userId">ユーザーID</div> ~~~以下省略~~~ </section> ~~~以下省略~~~
エラー画面の設計についても、やはり回復可能かどうかで画面を分ける必要があるということですかね。
なかなか骨の折れる設計になりそうな予感ですね。。。ちょっと違います。
ユーザマスタメンテ機能サンプルの画面ソースとイメージを貼り付けていますが、画面デザインはJQuery UIを利用しています。JQueryUIのダイアログを部品にしています。画面設計自体は、全然新しくなくてどこでも見えるものです。SPAの考え方を取り込む箇所は、ユーザ一覧・ユーザ登録・ユーザアップロード、この3点は従来WEB開発に3つのメイン画面に分けるものを1つのメイン画面に纏めることだけです。- 自分の言ったメイン画面とは、URLから呼び出すjspファイルと理解すればよいです。画面デザイン部品のsectionではありません。
- 機能分けはいろいろの切口がありますが、ユーザメンテとログインは一般的に別々のものとします。そして、ログイン機能は単独な「メイン画面」になります。
だが、ログアウトは、どのメイン画面にも利用されるから、head.jsp部品に取り込んでいます。それぞれの開発は別タスクにします。 - ユーザ登録サブ画面「MST01_inputdialog.jsp」、ユーザアップロードサブ画面「MST01_uploaddialog.jsp」とページング部品「paging.jsp」が含まれます。
- SPAは、一つページの「機能」の考えでページ分けしています。開発便利、ソース流用など観点で、サブ画面ごとに別ファイルにしています。
もし、一つ画面のシステムでSPAの反映を拡大して、1つ小さいシステムの全機能を1つページにしたい場合、別に不可能ではありません。適用範囲を「小」システムと位置づけしたほうがよいです。ちょっと大きいシステム場合、機能わけとソース分けを考慮しないとうまく進まないので、全部の機能をひとつ大きいJSPに入れるのは、多人作業はどうするか問題になりそうですね。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="efw" uri="efw"%> <!DOCTYPE HTML> <HTML> <HEAD> <TITLE>ユーザ管理</TITLE> <META CONTENT="TEXT/HTML;CHARSET=UTF-8" HTTP-EQUIV="CONTENT-TYPE"> <LINK REL="SHORTCUT ICON" HREF="img/favicon.png" /> <LINK REL=STYLESHEET TYPE=TEXT/CSS HREF="css/style_efw.css"> <efw:Client lang="jp" mode="jquery-ui" theme="mytheme" /> <SCRIPT> function selectRow(row) { $("#tbl_data tr").removeClass("SELECTED"); $(row).addClass("SELECTED"); $("#hdn_selected").val($("td:eq(0)",row).html()); } function dblclickRow(row) { selectRow(row); Efw("MST01_edit", {"selectId" : getSelectId()}); } function keepRowSelected(){ var serifno=$("#hdn_selected").val(); if (serifno!=""){ $("#tbl_data tr").removeClass("SELECTED"); $("#tbl_data tr").each(function(){ if($("td:eq(0)",this).html()==serifno){ $(this).addClass("SELECTED"); } }); } } function getSelectId(){ var selectId = $("#tbl_data tr.SELECTED>td:eq(0)").html(); return selectId==null?"":selectId ; } </SCRIPT> </HEAD> <BODY onload="Efw('MST01_init')"> <efw:Part path="MST01_inputdialog.jsp"/> <efw:Part path="MST01_uploaddialog.jsp"/> <DIV CLASS=MAIN> <DIV CLASS=TOP> <efw:Part path="head.jsp" title="EFW DEMO ユーザ管理" /> <TABLE STYLE="HEIGHT:43px;"> <COLGROUP> <COL WIDTH=100PX> <COL WIDTH=220PX> <COL> <COL WIDTH=250PX> </COLGROUP> <TR> <TD>フリーワード</TD> <TD><INPUT TYPE="TEXT" ID="txt_freeWord" STYLE="WIDTH: 300PX; IME-MODE: ACTIVE" MAXLENGTH=50></TD> <TD></TD> <TD STYLE="TEXT-ALIGN: RIGHT;"> <BUTTON ONCLICK="Efw('MST01_clear')" data-shortcut="F4">F4 クリア</BUTTON> <BUTTON ONCLICK="Efw('MST01_search')" data-shortcut="F5">F5 検索</BUTTON> </TD> </TR> </TABLE> <TABLE CLASS=TABLE-HEAD> <COLGROUP> <COL WIDTH=100PX> <COL WIDTH=220PX> <COL> <COL WIDTH=250PX> </COLGROUP> <TR> <TH CLASS="SORT SELECTED ASC" DATA-SORT="user_id" STYLE="BACKGROUND-POSITION-Y: center">ユーザID</TH> <TH CLASS="SORT" DATA-SORT="user_name" STYLE="BACKGROUND-POSITION-Y: center">ユーザ名</TH> <TH CLASS="SORT" DATA-SORT="eMail" STYLE="BACKGROUND-POSITION-Y: center">メールアドレス</TH> <TH CLASS="SORT" DATA-SORT="bikou" STYLE="BACKGROUND-POSITION-Y: center">コメント</TH> </TR> </TABLE> </DIV> <TABLE ID="tbl_data" CLASS="TABLE-BODY" style="margin-top:135px"> <COLGROUP> <COL WIDTH=100PX> <COL WIDTH=220PX> <COL> <COL WIDTH=250PX> </COLGROUP> </TABLE> <INPUT type="hidden" id="hdn_selected"> <BR> <DIV CLASS=FOOTER> <BUTTON ONCLICK="Efw('MST01_add')" data-shortcut="F1">F1 新規</BUTTON> <BUTTON ONCLICK="Efw('MST01_edit', {'selectId' : getSelectId()})" data-shortcut="F2">F2 修正</BUTTON> <BUTTON ONCLICK="Efw('MST01_delete', {'selectId' : getSelectId(),'doConfirm' : true})" data-shortcut="F3">F3 削除</BUTTON> <span style="width:50px;display:inline-block"></span> <IMG src="img/btn_download.png" class="BTN_ICON" ONCLICK="Efw('MST01_download')" data-shortcut="F6" title="F6 ダウンロード"> <IMG src="img/btn_upload.png" class="BTN_ICON" ONCLICK="Efw('MST01_upload')" data-shortcut="F7" title="F7 アップロード"> <efw:Part path="paging.jsp" id="paging" eventId="MST01_search" head=".MAIN .TABLE-HEAD" /> </DIV> </DIV> </BODY> </HTML>
@019_takorice_
Questionerあー何となく理解できました!
ソースまでありがとうございます!SPAといっても、すべての画面を一つのhtmlで表示するわけではなく、
各機能ごとに一つのhtmlとしてまとめることで、
従来のMPAに比べて、サーバーとの通信回数を減らせるアプリケーションということですね!
確かにログイン機能などどうやって分けるか悩んでいましたが、
難しく考えすぎてたようです。closeですが横レスで補足します。
SPAもMPAもajaxを利用した技術ですがSPAと称されるReact, Vueが古いajaxと決定に異なる点は
仮想DOM
と従来のDOMを同期させる点です。但し、従来のDOMで十分とする考えもあります。
私も仮想DOM
の考えは革新的と思いましたが、今ではajaxを制限して生産性を阻害する仮想DOMはどうかと思います。React, Vueについて、うちの会社は見積作業のために、一回勉強したことがあります。従来のDOMとJquery技術と大きく違っているから分かりにくいと感じます。その複雑さは新人にとってまず無理です。javascript、css、htmlを精通してからじゃないとだめです。だが、javascript、css、htmlを精通したら、もう一般的な仕事は十分堪能で、なぜ、わざわざreactとvueを利用しないといけないですか。どこに代替できないメリットがあるか、そのメリットは、一般的な仕事にどのぐらいの割合か、いまだわかっていません。一般的な仕事には、facebookのような画面を作るチャンスがないですね。
結局、見積作業が終わって、reactとvueの勉強も終わりです。最近別チームは、web画面でhtml画面デザインツールを利用&カスタマイズしようのため、vueを勉強し初めています。どこまで進めるか楽しみに見守ります。
技術のための技術は普及困難です。以下の特徴の技術は普及しやすいです。
- 生産性をアップする、
- 難易度を下げる、
代表的なものは、Jqueryとか、springとかです。jqueryの代替技術がすでにありました。springを嫌がる人が結構います(自分もspringのサイズに嫌です。)でも、上記特徴は結構なメリットをもたらすから、いまだ業界標準ポイの立場です。
jquery ajax単独で利用する場合、コールバック地獄になりそうですが、なにかのframeworkあるいは自作frameworkを導入して、そのコールバックの書き方を隠蔽すべきです。だが、reactとvueでその役割にすると、勉強コストが高くて、本末になるかと思います。
うちの会社は、ajaxなら自作フレームワークを利用しています。上記ソースのEfw関数の中に、ajax機能を利用しています。jspソースは結構よく複雑さを隠蔽しているでしょう。ユーザ一覧、ユーザ登録、excelダウンロード、ユーザアップロードの機能は、jsp・サーバイベント・SQLまで691行です。もしreact・vue+node.jsなどで類似機能を作ると3-4倍のソースになるでしょう。また、ひとつは1年の若手で十分、もう一つは5年以上のベテランが必要です。多分これからも、私のチームにはreactとvueの出番がないでしょう。
@019_takorice_
Questionerお二方とも補足等ありがとうございます!
仮想Domについて知識がありませんでしたので、簡単に調べて来ましたが、仮想Domは表示速度が早いというふうに書かれてる記事が多くありました。
ですが、必要最低限のリアルDomを直接書き換えれば、jqueryやJavaScriptの方が仮想Domの比較が入らない分早いのでは?と思ってしまいました。
仮想Domについては少し質問内容から脱線してしまうので、もう少し調べてみた上で、分からなければ質問に上げさせて頂こうかと思います。
本当にありがとうございました!
- JavaとJavaScriptのみでSPAの作成を考えています。
そもそも「JavaとJavaScriptのみ」という話の出だしから見当違いのように思えるのですが・・・
フロントエンド、バックエンドという言葉は分かりますか?
バックエンドは Java のアプリでやるとして、フロントエンドを JavaScript のみで質問者さんが独自実装するつもりではないですよね。SPA のフロントエンドのフレームワークの有名どころは React, Angular, Vue ですが、それを使うことを考えてください。自力で JavaScript で SPA のフロントエンドを実装するのは非現実的です。
で、質問者さんが気にしているアクセス制限などのセキュリティはバックエンドに実装します。例えばアクセス制限のあるバックエンドのリソースにアクセスする場合は、ログインして認証を受けたユーザーのみを許可するようにします。
具体例を書きます。
Visual Studio 2022 のテンプレートで作る認証システム込みの React (フロントエンド) + Web API (バックエンド) の例ですが、初期画面は以下のようになっています。メニューバーにある Fetch data にはアクセス制限がかかっており、認証を受けたユーザーでないとデータは表示できないように設定されています。
で、Fetch data をクリックすると以下のようにログイン画面に遷移します。
ログイン画面で、認証システムの DB に事前に登録済みの有効な id (上の例では email) と password を入力して、ログインに成功(ユーザー認証を受ける)すると以下のようにデータが表示されるという仕組みになっています。
Comments
@019_takorice_
Questionerご回答ありがとうございます。
残念ながら、フレームワークは環境上使えません泣
インターネット接続が出来ず、また新規インストールの許可はおりません泣ただ、アプリケーションが小規模開発なので、SPAで何とか開発出来ないか?と要望を受けてる為、検討してるといった流れになっています。
ご回答頂いた内容拝見しました。
MPAの場合はブラウザからリクエストを行い、SPAの場合はフロントエンドからリクエストを行う認識ですが、それ以外の処理の流れとしては、MPAと同じような以下の流れの認識であっていますでしょうか?
クライアント(ログイン画面) → サーバー(認証処理) → クライアント(受信したページを特定要素に差し替え)「小規模開発なので、SPAで何とか」とか「MPAの場合はブラウザからリクエストを行い、SPAの場合はフロントエンドからリクエストを行う」とか、失礼ながら、基本的なことがよく分かってないようで、見当違いのことを言ってるようにしか思えません。
何にせよ、SPA のフレームワークが使えなければ、普通に MPA でやるほかないのでは?
@019_takorice_
Questioner基本的にSPAと言われるreactやvueはあくまでフレームワークです。
フレームワークと言われるものは、開発効率をあげるための既存の言語をサポートするような役割であるため、なくても同じような機能は実装できます。
SPAなら仕組みはAjax通信なので、JavaScriptで十分開発を行えます。
これでも見当違いであるというのなら、他の回答者さんのコメントも全て見当違いでしょうか?
それとこの質問は既に他の回答者さんからの回答によりクローズさせて頂いていますので、これ以上の議論は必要ありません。
ご回答頂きありがとうございました。