JavaScriptだけでWebサイト開発

node.js + Express + mongodb系 + React でサービスを作るメモ

express-react-views+Material-UIをSSRで試す

わざわざServer Side Renderingでやるべきことではないですが、やってみました。

やったこと

  • express-generator で雛形を作る
  • app.jsで view engineに express-react-views を設定
  • view 内の layout.jsxとindex.jsx でmaterial-uiを利用
  • ブラウザで確認

環境構築

$ express material
$ cd material
$ npm install
$ npm install --save express-react-views react react-dom material-ui

app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// express-react-views engine setup
// ---------------------------------------------------------------
app.set('views', __dirname + '/views');
app.set('view engine', 'jsx');
app.engine('jsx', require('express-react-views').createEngine());


// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

views/layout.jsx

var React = require('react');
const {getMuiTheme, MuiThemeProvider} = require('material-ui/styles');

class Layout extends React.Component {
  render() {
      console.log(this.props);
    return (
      <html>
        <head><title>{this.props.title}</title></head>
        <body>
            <MuiThemeProvider muiTheme={getMuiTheme()}>
                {this.props.children}
            </MuiThemeProvider>
        </body>
      </html>
    );
  }
}

module.exports = Layout;

views/index.jsx

var React = require('react');
var Layout = require('./layout');
var {AppBar, RaisedButton, Drawer, MenuItem} = require('material-ui');

class Index extends React.Component {
    constructor(props) {
      super(props);
      this.state = {open: false};
    }

    handleToggle() {
        this.setState({open: !this.state.open});
    }
    
    render() {
        return (
            <Layout title={this.props.title}>
                <AppBar title={this.props.title} iconClassNameRight="muidocs-icon-navigation-expand-more"/>
                    This index page
                <RaisedButton label="Toggle Drawer" onClick={this.handleToggle} />
                <Drawer open={this.state.open}>
                    <MenuItem>Menu Item</MenuItem>
                    <MenuItem>Menu Item 2</MenuItem>
                </Drawer>
            </Layout>
        );
    }
}

module.exports = Index;

サーバー起動

$ npm start

ブラウザで確認

localhost:3000

f:id:ichi-bit:20171121123253p:plain

イベント処理が動作すべきところは反映していません。見た目だけ反映しています。 HTMLは非常に汚いです。

まとめ

  • 見た目だけ反映したい場合は有効
  • クライアントサイドでイベント処理が必要
  • express-react-viewsでは厳しい
  • 詳しくはこちら github.com

  • こんなのも github.com

©ichi-bit