[SPA] TypeScript 소스 파일 하나에 백엔드와 프런트 엔드 코드를 집계

[SPA] TypeScript 소스 파일 하나에 백엔드와 프런트 엔드 코드를 집계



1. 이번 내용



이번 소스는 TypeScript 파일 하나뿐입니다. 그냥 프런트 엔드와 백엔드 SPA 프로그램을 동시에 짜는 내용입니다. 그리고 실행에 ts-node는 사용하지만, 수동 컴파일은 일절 실시하지 않습니다. 물론 .js 파일도 출력하지 않습니다.

통상이면, 백엔드는 ts-node에 의해 뒤로 컴파일되는 형태를 만들 수 있습니다만, 프런트엔드는 그렇게 되지 않습니다. 브라우저가 TypeScript를 직접 해석할 수 없는 이상 .ts를 .js로 변환하여 해당 파일을 준비해 두어야 합니다.

프런트엔드와 백엔드는 같은 언어를 사용해도 완전히 다른 환경에서 실행됩니다. 소스 코드 하나로 둘 다 움직이는 등 보통이 될 수 없습니다. 이번에는 그 불가능을 가능하게하는 방법을 소개하고 싶습니다.

2. 준비


  • Node.js 설치
  • 적절한 디렉토리 만들기
  • 만든 디렉토리에 다음 명령을 입력합니다.
     npm -y init
     npm i @types/express express ts-node typescript
     npx tsc --init
    

    3. 소스 코드 작성



    ※소스 코드를 짧게 하기 위해, 본래 필요한 체크를 여러가지 생략하고 있습니다

    Test01.ts
    import express from "express"; 
    import * as bodyParser from "body-parser"; 
    
    interface Message { 
      id: number; 
      name: string; 
      msg: string; 
    } 
    /** 
     * フロントエンド側(スクリプト送信時には文字列に変換される) 
     */
    function front() { 
      //ページ読み込み後に処理する内容 
      addEventListener("DOMContentLoaded", () => { 
        //データ送受信処理 
        const send = (name?: string, msg?: string) => { 
          const req = new XMLHttpRequest(); 
          req.open("POST", "/", true); 
          req.setRequestHeader("Content-Type", "application/json"); 
          req.addEventListener("loadend", () => { 
            if (req.readyState == 4) { 
              if (req.status == 200) { 
                const values = <Message[]>JSON.parse(req.responseText); 
                let output = ""; 
                for (const value of values) { 
                  output = 
                    `<div>[${value.id}]${value.name}:${value.msg}</div><hr>\n` + 
                    output; 
                } 
                div.innerHTML = output; 
              } 
            } 
          }); 
          req.send(JSON.stringify({name,msg})); 
        }; 
        //各インスタンスの作成 
        const inputName = document.createElement("input"); 
        inputName.value = "名前"; 
        document.body.appendChild(inputName); 
        const inputMessage = document.createElement("input"); 
        inputMessage.value = "メッセージ"; 
        document.body.appendChild(inputMessage); 
        const button = document.createElement("button"); 
        button.innerHTML = "送信"; 
        document.body.appendChild(button); 
        const div = document.createElement("div"); 
        document.body.appendChild(div); 
        //ボタンのイベント 
        button.addEventListener("click", () => { 
          send(inputName.value, inputMessage.value); 
          inputMessage.value = ""; 
        }); 
        //初期データ要求 
        send(); 
      }); 
    } 
    
    /** 
     * バックエンド側 
     */ 
    const app = express(); 
    app.get("/", (req, res) => { 
      //スクリプトデータを返す 
      //「(${front.toString()})();」がフロントエンド側での実行トリガーとなる
      res.send( 
    `<!DOCTYPE html> 
    <html> 
    <head> 
      <title>TS-Test</title> 
      <script> 
    (${front.toString()})(); 
      </script> 
    </head> 
    <body></body> 
    </html>` 
      ); 
    }); 
    
    //POSTデータの処理 
    const messageData: Message[] = []; 
    app.use(bodyParser.json()); 
    app.post("/", (req, res) => { 
      if (req.body.name && req.body.msg) 
        messageData.push(Object.assign({ id: messageData.length + 1 }, req.body)); 
      res.send(JSON.stringify(messageData)); 
    }); 
    
    //待ち受けポート 
    app.listen(8080); 
    

    4. 실행


     ts-node Test01
    

    5. 확인



    http://localhost-8080.com/



     SPA의 게시판풍 프로그램입니다. 데이터를 파일이나 DB에 출력하고 있는 것은 아니기 때문에, 백엔드가 정지한 시점에서 소실합니다.

    6. 해설



    하는 일은 간단합니다.

    function front()

    이 백엔드측에서 자동 컴파일된 function의 내용을, 프런트엔드측에 보내고 있을 뿐입니다. 이번에는 생성 코드를 <script> 태그에 끼워넣고 있습니다만, express와 제휴시켜 파일로서 돌려주는 편법도 가능합니다. 또 이번에는 소스 코드가 하나입니다만, 하려고 하면 다른 파일로 분리하는 것도 가능합니다.

    이번 내용을 할 수 있는 것은, 프런트 엔드와 백엔드의 실행시의 언어가 일치하고 있는 덕분입니다. 물론 다른 언어로도 백엔드에서 프런트 엔드로 스크립트를 흘려 넣는 것은 가능하지만, 그것은 어디까지나 생성 끝난 문자열로서입니다. 일반적으로 프로그램을 짜는 것을 단순한 변환으로 건네줄 수 있는 것은, 같은 언어고의 혜택입니다.

    물론 이것만으로도 괜찮은 시스템을 만드는 것은 어렵습니다. 그러나 이것을 부분적으로 이용해, 특정의 동작을 커스터마이즈 하는 것과 같은 용도라면 사용할 수 있을지도 모릅니다. 어떤 것도 발상하면서 가능성이 퍼지는 것입니다. 물론 TypeScript 연습이나 SPA 프로그램 실험 등에도 사용할 수 있습니다.

    7. 요약



    이번 내용은 프런트 엔드의 TypeScript의 프로그램을 컴파일 없이 만들 수 없는지, 그런 것을 생각해 실험한 결과입니다. 생각해 낸 것은 바로 실험용 코드를 만들어 시험하고 있습니다. 그 장애물을 낮추는 것은 쉬운 실행 환경입니다.
  • TypeScript를 부담없이 쉽게 시험할 수 있는 환경을 정돈한다

  • 이것을 사용하고 있습니다. 코드를 써 F5 키로 즉시 실행할 수 있으므로, 약간의 동작 검증으로부터, DB 액세스의 확인, 외부 API의 실험등을 부담없이 실시할 수 있습니다. 그래서. 다양한 코드가 이것으로 만든 디렉토리에 모여 있습니다.

    생각나면 우선 코드를 쓰는, 앞으로도 그런 느낌으로 해 가고 싶습니다.

    좋은 웹페이지 즐겨찾기