1. Qiita
  2. 投稿
  3. nodejs

Serverless FrameworkでReactを使ったWordPress記事一覧ページを作る

  • 10
    いいね
  • 0
    コメント

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