概要
SSRの勉強をしたくて、Qiitaを漁ったら、
思いの外、他の方の記事がわかりづらかった(私の能力が低いだけです
Express + ReactでSSR
参考:React での ServerSideRendering 入門
準備
npm install express-generator -g
express myapp
cd myapp
npm install
npm install react react-dom node-jsx
npm start
サンプルコンポーネント
ただのReactコンポーネント。
const React = require('react');
module.exports = class Sample extends React.Component {
render(){
return (
<div>
hoge
</div>
);
};
};
Viewをブラウザに返す
node-jsxを入れておくと、requireでJSXを解釈してくれるので
入れておいたほうがいい。
Reactコンポーネントを読み込んで、
ReactDomServer.renderToStringでHTML文字にする。
あとはそれをブラウザに渡す。
・・・
require('node-jsx').install({harmony: true});
const React = require('react');
const ReactDomServer = require('react-dom/server');
var Sample = require('./components/sample');
const createHtml = component => (`
<html>
${component}
</html>
`);
・・・
//app.use('/', index);
app.use('/', (req, res, next) => {
const sampleComp = ReactDomServer.renderToString(React.createElement(Sample));
const view = createHtml(sampleComp);
res.status(200).send(view);
});
・・・
今表示されているものは静的なHTML
のはず。
hogeを表示させるだけだとよくわからないので、
Componentのstateに、変化と、その表示をさせてみよう。
const React = require('react');
module.exports = class Sample extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.click = this.click.bind(this);
}
render(){
return (
<div>
<input type="button" onClick={this.click} value="CountUP"></input>
<div>{this.state.count}</div>
</div>
);
};
click() {
this.setState({
count: this.state.count + 1
});
}
};
ブラウザでReactを動かす
あれじゃあどうやって仮想DOM使うんだ・・?
と調べると・・。
参考:hydrateでSSR後にブラウザでReactを動かす
マジカヨ。
結局、ブラウザ用にファイル用意するのね・・。
わしゃてっきり、webpackから解放されるものかと・・。
というわけでwebpack準備
npm install -D \
webpack webpack-cli \
babel-cli babel-preset-env babel-preset-react babel-loader
※"webpack": "^4.10.1"
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'index.js'
},
module: {
rules: [
{
test: /\.(js)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'babel-preset-react',
'babel-preset-env'
]
}
}
}
]
}
};
肝は、express-generatorで作成したアプリなので、
デフォルトでpublicディレクトリが静的なファイルを置く場所と決まっていることだ。
なので、bundleファイルもそこに出力されるようにする。
表示の置換
参考を見る限り、
静的HTMLを、ReactのViewに後から置き換わるようにすれば良いみたい。
これは、ブラウザでReactを書いている人には馴染み深い
ReactDOM.render
とほぼ一緒だ。
renderではなく置換(という言葉であっているのか・・?)させる、
ReactDOM.hydrate
に変えてあげればいいみたい。
const React = require('react');
const ReactDOM = require('react-dom');
var Sample = require('./../components/sample');
ReactDOM.hydrate(
<Sample />,
document.getElementById('root')
);
bundleファイルを読み込みと、
DOMにレンダリング(置換)しないといけないので、最親のHTMLにコンテナを用意。
・・・
const createHtml = component => (`
<html>
<div id="root">${component}</div>
<script src="index.js"></script>
</html>
`);
・・・
./node_modules/.bin/webpack
npm run start