Serverless FrameworkでReact + WP APIなwebページを作ってみたので、ひとまず覚書
使用ライブラリ
serverless
コマンドはグローバルインストールされている前提。
バージョン対応とかを考えると、npm側でやったほうがいいのだろうけど。
package.json
{
"name": "sls-wordpress-frontend",
"version": "0.0.0",
"description": "",
"main": "src/index.js",
"devDependencies": {
"babel-core": "^6.4.5",
"babel-loader": "^6.2.1",
"json-loader": "^0.5.4",
"babel-plugin-add-module-exports": "^0.1.2",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"serverless-webpack": "^1.0.0-rc.3",
"webpack": "^1.13.1",
"webpack-node-externals": "^1.3.3"
},
"dependencies": {
"react": "^0.14.6",
"react-dom": "^0.14.6",
"wpapi": "^1.0.0"
}
}
Webpackの設定
json-loaderはwpapiをrequireする際に必要となります。
dependencies
内のライブラリをLambdaに同梱したいので、webpack-node-externals
を採用。
webpack.config.js
var path = require('path');
var nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
'/src/index': './src/index.js'
},
target: 'node',
resolve: {
extensions: ['', '.js', '.jsx'],
modulesDirectories: [
'node_modules'
]
},
externals: [nodeExternals()],
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js'
},
module: {
loaders: [
{
test: /\.js$|\.jsx$/,
loader: 'babel-loader',
include: path.join(__dirname, 'src')
},{
test: /\.json$/,
loader: 'json-loader'
}
]
}
};
Lambda function
とりあえず動くの優先ということで、1ファイル内にReactのコンポーネントも詰め込んでます。
やっていることは以下の3つです。
- wpapiライブラリでのWordPress記事情報取得
- React SSRでのwebページレンダリング
- Lambdaのcallbackで作成したHTMLを返す
src/index.js
'use strict';
const WPAPI = require( 'wpapi' );
import React, { Component } from 'react';
import { renderToString } from 'react-dom/server';
class WPPost extends Component {
constructor(props, context) {
super(props)
}
render() {
const post = this.props.post
return (
<archive key={post.id}>
<h2>{post.title.rendered}</h2>
<div dangerouslySetInnerHTML={{__html: post.excerpt.rendered}} />
</archive>
)
}
}
class App extends Component {
constructor(props, context) {
super(props)
}
render() {
const postList = this.props.posts.map( post => {
return <WPPost post={post} />
})
return (
<main>
<h1>WP Postlist</h1>
{postList}
</main>
)
}
}
function renderFullPage(renderedContent) {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
${renderedContent}
</body>
</html>`;
}
module.exports.index = (event, context, callback) => {
const wp = new WPAPI({ endpoint: 'https://api.wp-app.org/wp-json' });
wp.posts().then(function( data ) {
const renderedContent = renderToString(<App posts={data} context={context}/>);
const renderedPage = renderFullPage(renderedContent);
callback(null, renderedPage);
}).catch(function( err ) {
callback(err);
});
};
serverless.yml
API GatewayでのContent-Type指定やpluginsの指定などをお忘れなく。
独自ドメインについては、SSL証明書の設定等が必要となりますのでまたおいおい。
serverless.yml
service: sls-wordpress-frontend
plugins:
- serverless-webpack
provider:
name: aws
runtime: nodejs4.3
stage: dev
package:
include:
- node_modules/
- src/
custom:
webpackIncludeModules: true
functions:
index:
handler: src/index.index
events:
- http:
path: v1/index
method: get
integration: lambda
response:
headers:
Content-Type: "'text/html'"
template: $input.path('$')
デプロイ
$ sls deploy
serverless-webpack
がよしなにしてくれるので、デプロイはいつも通りです。
デプロイ後、API Gatewayのエンドポイントにアクセスして表示確認しましょう。
今後について
検索とか記事ページ遷移とかもできるようにしたいので、そのへんまでまとまったら汎用化しようかなと。
README.mdもまだ無いですが、リポジトリは以下です。
https://github.com/hideokamoto/sls-wordpress-frontend