前回=> vte.cxによるバックエンドを不要にする開発(6.採番)
今回はサーバサイドJavaScriptについて説明します。
vte.cxのアーキテクチャーとサーバサイドJavaScript
これまでのサンプルは、エンドポイント/d
に対してアクセスするもので、データの登録や参照だけを行うものでした。実は、vte.cxにはデータ登録/参照以外に、サーバサイドのJavaScript(以下、サーバサイドJS)を実行する機能があります。(下図のエンドポイント/s
がこれに該当します)
サーバサイドJSはサーバサイドで実行されますが、これはBFF(Backends for Frontends)といって概念的にはフロントエンドの範疇です。
つまり、実行される場所が異なるだけで、クライアントサイドで実行されるJavaScriptの機能と同等であるというわけです。ただ、VtecxAPIを使ってサーバリソースに直接アクセスしたり、PDF生成、メール送信といったバックエンド機能を利用できるというメリットがあります。また、/d
が返すリソースで不必要な項目が多い場合に通信量削減のためクライアントが必要とする最低限のものだけサーバサイドで編集して返したりすることはよくあります。集計などもサーバサイドJSを利用するとよいでしょう。
掛け算を行うサンプルプログラム
では実際にサーバサイドJSを実行するサンプルプログラムを作成してみましょう。
aとbの2つのパラメータを受け取り掛け算をして結果を返すサーバサイドのJavaScriptコードです。
serverフォルダ配下に以下のようにmultiply.tsxを作成してみましょう。
import * as vtecxapi from 'vtecxapi'
const a = Number(vtecxapi.getQueryString('a'))
const b = Number(vtecxapi.getQueryString('b'))
const result = a * b
const res = {
feed: {
title: result.toString()
}
}
vtecxapi.doResponse(res, 200)
クエリパラメーターを取得するためには vtecxapi.getQueryString()
を使用します。
これを使って a
と b
を取得して、これを数値に変換した上でかけ算に使用し、result
としてクライアントへ返します。クライアントに返すには、vtecxapi.doResponse()
を用います。
vtecxapiの関数については、詳しくはドキュメントを参照してください。
次に、以下のコマンドでサーバにデプロイしてください。
npm run watch:server -- --env entry=/server/multiply.tsx
以下のように実行されればデプロイ成功です。
(もし、webpack is watching the files…で止まったままなら、multiply.tsxファイルを一部更新してみてください)
webpack is watching the files…
Hash: 753d666827b92d455048
Version: webpack 4.39.1
Time: 9812ms
Built at: 2019-09-18 13:00:49
Asset Size Chunks Chunk Names
./server/multiply.js 17.8 KiB 0 [emitted] main
Entrypoint main = ./server/multiply.js
[0] ./src/server/multiply.tsx 322 bytes {0} [built]
+ 1 hidden module
dist/server/multiply.js --> http://{サービス名}.vte.cx/server/multiply.js
{"feed" : {"title" : "Put content."}}
このように、/src/server/
の配下に multiply.tsx
というファイル作成してデプロイするだけで、/s/multiply
というエンドポイントが自動的に作成されます。
実際にブラウザから実行してみます。
http://{サービス名}.vte.cx/s/multiply?a=3&b=2&x
と入れて開いてみてください。最後のxパラメータはXMLで表示させるという意味です.
(※ vte.cxは基本的にユーザーがログインして使用するタイプの業務アプリケーションを想定しているため、ログインしていないユーザーからサービスへのリクエストは許可しません。今回作成するサービスへのリクエストも、ログインしているユーザーからのものだけを受け付けます。まずはじめにhttp://{サービス名}.vte.cx/login.html
からログインしてください。login.htmlがサーバに存在しない場合は、/deploy.shを実行してください。)
以下のように表示されたら成功です。
ちなみに、サーバサイドJSのデプロイコマンドをdeploy.sh
に追加する際は、以下のように記述してください。
npx webpack --env entry=/server/multiply.tsx --mode=production --env externals=true
Reactを必要とするもの(SSRやPDF出力など)では、env externals=env externals=false
としてください。
クライアントからサーバサイドのJavaScriptコードを呼び出す
今度は、クライアントのaxiosからリクエストして、エンドポイント/s/multiply
にクエリパラメーターとして二つの数字を渡すと、その二つをかけ算して返す、というシンプルなアプリケーションを実装してみます。
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { useState } from 'react'
import axios from 'axios'
const App = () => {
const [result, setResult] = useState(0)
const multiply = async () => {
try {
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
const res = await axios.get('/s/multiply',{params: { a: 2, b: 3 }})
setResult(res.data.feed.title)
} catch (e) {
alert('error:'+e)
}
}
return (
<div>
<button onClick={() => { multiply() }}>
{result}
</button>
</div>
)
}
ReactDOM.render(<App/>, document.getElementById('container'))
npm run serve:login
でログインした後、npm run serve:index
でデプロイしてください。
vtecxapiを使ってデータを取得する
今度はvtecxapiを使ってデータベースからデータを取得してみましょう。
以下のように、vtecxapi.getFeed()
を使うことで、これまで/d/hotel
に対して行ってきたGETリクエストをサーバサイドJSから行うことができます。簡単ですね。
import * as vtecxapi from 'vtecxapi'
const feed = vtecxapi.getFeed('/hotel')
vtecxapi.doResponse(feed)
これをデプロイしましょう。
npm run watch:server -- --env entry=/server/getfeed.tsx
ブラウザで、http://{サービス名}.vte.cx/s/getfeed?x
を開いてください。
以下のようにfeedが表示されたら成功です。
ReactによるSSR(サーバサイドレンダリング)
Reactの機能を使うことでSSR(サーバサイドレンダリング)を実行できます。
デプロイして/s/ssr.htmlにアクセスすると、「Hello, vte.cx!」が表示されます。
import * as vtecxapi from 'vtecxapi'
import * as React from 'react'
import * as ReactDOMServer from 'react-dom/server'
const element = (
<h3> Hello, vte.cx! </h3>
)
const html = ReactDOMServer.renderToStaticMarkup(element)
vtecxapi.doResponseHtml(html)
デプロイ
npm run watch:server -- --env.entry=/server/ssr.html.tsx
PDF出力
ReactのSSR機能を利用してPDFを出力することができます。
vte.cxのPDF出力機能のテンプレートにSSRで生成したHTMLを指定すると動的にPDFを生成します。以下のサンプルでは、/s/ssr.pdfにアクセスするとPDFを動的に生成しダウンロードします。
import * as vtecxapi from 'vtecxapi'
import * as React from 'react'
import * as ReactDOMServer from 'react-dom/server'
import * as pdfstyles from '../pdf/pdfstyles'
interface User {
firstName: string
lastName: string
}
function formatName(user: User) {
return user.firstName + ' ' + user.lastName
}
const user: User = {
firstName: 'Hello',
lastName: 'vte.cx'
}
const element = (
<html>
<body>
<div className="_page" style={pdfstyles._page}>
<table style={pdfstyles._table}>
<tr>
<td>
<p> Hello, {formatName(user)}! </p>
</td>
</tr>
<tr>
<td>
<div className="_barcodeEAN" style={pdfstyles._barcode} />
</td>
</tr>
</table>
</div>
</body>
</html>
)
const html = ReactDOMServer.renderToStaticMarkup(element)
// PDF出力
vtecxapi.toPdf(1, html, 'hello.pdf')
また、PDF用のスタイルシート/pdf/pdfstyles.ts
を置いてください。
PDFスタイルシートについては、ドキュメントを参照してください。
export const _page: any = {
pagesize: 'A4',
orientation: 'portrait'
}
export const _table: any = {
bgcolor: '#FFEC8B',
frame: 'box',
cellspacing: '3',
cellpadding: '3',
width: '90%',
align: 'left'
}
export const _barcode: any = {
value: '4900000000000;'
}
デプロイ
npm run watch:server -- --env entry=/server/ssr.pdf.tsx
ブラウザからhttp://{サービス名}/s/ssr.pdf
を開くとhello.pdf
がダウンロードされます。
本日はここまでです。お疲れさまでした。