# szpp-judge フロントエンド開発をやってみよう【前半】 :::info 前半 40分くらい ::: ## 0. 概要 前半パートでは、Web アプリを作る時にやることをリクルートの資料を見ながら簡単に紹介したあと、szpp-judge の開発を進めるために知っておいた方がよいことを紹介します。途中で手を動かすハンズオンもやります。では行ってみましょう! このパートでは Web アプリケーションを作る上で React.js に期待される役目を紹介します。また szpp-judge のアーキテクチャも概説します。 --- 資料 <iframe class="speakerdeck-iframe" frameborder="0" src="https://speakerdeck.com/player/eb6c400e682e4df59f28967db3930a52" title="Next.js" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" style="border: 0px; background: padding-box padding-box rgba(0, 0, 0, 0.1); margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 560px; height: 315px;" data-ratio="1.7777777777777777"></iframe> ハンズオンはここから触ってみましょう [create-react-app codesandbox](https://codesandbox.io/s/x335plk7xo) ## 1. React のコードを見てみよう ※ Web 3層スキーマは分かっている前提。 ### 1-1. React 入門以前 React.js という大仰なものを使わなくても Web ページを作ることはできます。例えばこんな風に html を書くことによって。 ```htmlmixed= <!DOCTYPE HTML> <html> <head> <title>Sample</title> </head> <body> <h1>Sample heading1</h1> <section class="awesome-section"> <header class="nav-wrapper"> <nav class="navigation"> <ul> <li>contests</li> <li>standings</li> </ul> </nav> </header> <main> <div class="box"> <p> Challenge Szpp!! </p> </div> </main> </section> <p></p> </body> </html> ``` これでよいわけですが、ちょっと階層が深くて分かりづらいですね。 また、 `Challenge Szpp!!` と書いてありますが、ここを変更したくなったらもう一枚 html を書くんでしょうか?ちょっと面倒です。 ここにこういうページを**分割して、「ページ」を「構成部品」の集合として表現したい**という需要が発生しました。なお構成部品のことをコンポーネントと呼んだりします(呼んだりしない場合もあるのは、コンポーネントの単位が文脈ごとにまちまちだからです。ここでの「コンポーネント」はふわっと部品のことを指しています)。 React.js は UI をコンポーネントの集まりで記述するための様々な機能を提供してくれます。こうしたコンポーネントを使えば、表示したい情報を外部からデータを取得させたり、こちらから渡したりすることができます。 :::info :dart: React.js は Web ページの部品を書く目的で使うことができる。そのことによって利用する開発者が部品を再利用でき、似たような画面をゼロから書き直すことなく書けるようになる。 ::: ### 1-2. 登場人物紹介 - ブラウザ - トランスパイラ - React ランタイム - ソースコード React ランタイムは便宜上の名前です。JavaScript から DOM を操作しようという発想が UI フレームワークの世界にはあります。 DOM の変更を監視してネットワークリクエストを投げたり DOM を挿入したりする際に React そのものとでもいう存在(JavaScript で書かれたプログラムで僕らが書いたコードと同じくブラウザに届けられる)が必要になります。こいつをランタイムと呼んでいます。 ### 1-3. JSX の導入 React で部品を作る時には JavaScript のオブジェクトを使用して作りたい部品の形をランタイムに教えてやります。するとランタイムが DOM を更新します。 この辺、詳しくは「仮想 DOM」などで調べてみましょう。 例えばこの部品は ```htmlembedded= <div class="box"> <p> Challenge Szpp!! </p> </div> ``` ランタイムが解釈できる形で書くとこんな風になります(雰囲気)。 ```javascript= var e = React.createElement( "div", { className: "box" }, React.createElement( "p", null, "Challenge Szpp!!" ) ); ``` ただ、`React.createElement` を呼びまくるのは大変なので HTML っぽいものを書くと、それをランタイムが解釈できる形に変換してくれる仕組みが用意されています。 この、「HTMLっぽいコード」の書き方は JSX と呼ばれる記法としてルールが決められており、その JSX を「ランタイムが解釈できる形に変換する」仕事をするのがトランスパイラ(transpiler)です。 先ほどの構造を JSX を使って書くと、こんな感じになるでしょう。2つのファイルが必要になります。まず、index.js をこんな感じに書きます。 先ほどの HTML を部品に分解して doc のところで統合しています。 ```typescript= const Title = <title>Sample</title>; const Heading1 = <h1>Sample Heading</h1>; const Nav = ( <nav class="navigation"> <ul> <li>contests</li> <li>standings</li> </ul> </nav> ); const MsgBox = ( <div class="box"> <p> Challenge Szpp!! </p> </div> ); const doc = ( <> <head> <Title /> </head> <body> <Heading1 /> <section class="awesome-section"> <header class="nav-wrapper"> <Nav /> </header> <main> <MsgBox /> </main> </section> </body> </> ); // これは何???あとで説明 const root = ReactDOM.createRoot(document.getElementById("root")); root.render(doc); ``` そして今の index.js というファイルを読み込むための HTML ファイルをこんな感じに書きます。 トランスパイラがいないので実際にはエラーになりますが、概念的にはこんな感じです。 ```htmlmixed= <!DOCTYPE HTML> <html> <div id="root"></div> <script src="index.js" type="text/babel"></script> </html> ``` > Next.js ではトランスパイラによる変換が内部的に行われるので、開発者が明示的に text/babel とか書いたりしてトランスパイルそれ自体の設定をすることはありません。 ### 1-4. React の流儀 なぜ React を使うのかといえば UI をインタラクティブにしたいとかそういうことでしょ。そのためのベストプラクティス(を知る第一歩)を見に行きましょう↓ [React の流儀](https://ja.reactjs.org/docs/thinking-in-react.html) なるほどわからん。 ### 2. szpp-judge のアーキテクチャ いきなり話が変わりますが [szpp-judge](https://github.com/szpp-dev-team/szpp-judge) の話をします。 ここには 3つの登場人物がいます。 ```shell ❯ tree --dirsfirst -L 1 . . ├── backend ├── frontend ├── judge-server └── docker-compose.yaml 3 directories, 1 file ``` - backend ディレクトリ 競プロの問題を管理し judge-server に judge のリクエストを出し、 frontend 向けの API を提供するためのいろいろが入っている。 - frontend ディレクトリ ユーザが使う Web の画面を提供するためのいろいろが入っている。 - judge-server ディレクトリ 提出された競プロの回答を実行して採点するためのいろいろが入っている。 <!-- いくつか動作例を記述しています。 基本的に、frontend をユーザが操作する→それをトリガーにして他の2者が裏でごにょごにょして…というパターンがすべてなので frontend を使うユーザの目線でこれらの例を作成しました。ここから奴らの関係性を掴んでみましょう。 #### ログインする ```mermaid sequenceDiagram front->>back: GET: /api/contests back->>judge: Great! ``` -->