追記: webpack-serve は非推奨となり webpack-dev-server が開発再開しました。新しく始める際はスタックに webpack-serve を採用しないほうがよいでしょう。
実は react あんまり関係ない。webpack-serve でSPAホストする際にフォールバックコンテンツの設定方法でちょっとハマったのでメモ。
実行環境は React.js 開発環境を webpack4 + webpack-serve + babel 7 で作る の流れで作ったものをそのまま利用しています。したがって babel7, webpack4 です。
webpack-serve と react-router
react-router-dom をインストールします
npm install --save react-router-dom
src/index.js をルーティング対応にする
ここではルートとして /
と /welcome
を持つとても簡単なアプリケーションを作成しました。
import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route,Switch, Link } from "react-router-dom";
import "./index.css";
const Root = () => (
<div>
<p>Roooooooooot component</p>
</div>
);
const Welcome = () => (
<div>
<p>Welcome component</p>
</div>
);
render(
<Router>
<div>
<h1>React Router</h1>
<div>
<ul>
<li>
<Link to="/welcome">Welcome</Link>
</li>
<li>
<Link to="/">App Root</Link>
</li>
</ul>
</div>
<Switch>
<Route exact path="/welcome" component={Welcome} />
<Route path="/" component={Root} />
</Switch>
</div>
</Router>,
document.getElementById("content")
);
フォールバックコンテンツを返す設定をする
connect-history-api-fallback をインストールします。
npm install --save connect-history-api-fallback koa-connect
ミドルウェアを有効にするため、webpack-serve のアドオン設定関数を追加します。ここでは webpack.config.js
に書いてますが、設定コールバック書き始めるあたりから serve.config.js
に分離したほうが見通しいい気がします。
output として publicPath: '/',
を設定し忘れると、/no/file/text.html
のように、/
を含んだパスのときにフォールバックコンテンツを返してくれないために注意が必要です。
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const convert = require("koa-connect");
const historyApiFallback = require("connect-history-api-fallback");
// アドオンに historyApiFallback を追加
const addon = (app, middleware, option) => {
app.use(convert(historyApiFallback()));
};
module.exports = {
mode: process.env.WEBPACK_SERVE ? 'development' : 'production',
entry: {
main: path.resolve(__dirname, './src/', "index.js")
},
output: {
path: path.resolve(__dirname, './dist/'),
publicPath: '/',
filename: '[name]-[hash].js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude:[ /node_modules/ ],
loader: 'babel-loader'
},
{
test: /\.css$/,
exclude: [/node_modules/],
use: ["style-loader", { loader: "css-loader", options: { modules: true } }]
}]
},
devtool: 'source-map',
serve: {
open: true,
port: 8080,
content: path.resolve(__dirname, 'public'),
add: addon
},
plugins: [new HtmlWebpackPlugin({ template: "src/index.html" })]
}
以上、おわり。
これで開発サーバ起動すると、/welcome
に対しても index.html
のコンテンツが返却されるようになりました。
connect-history-api-fallback
「404ページに対してフォールバックコンテンツを設定する」ミドルウェアではなく「History APIを利用して作成されるSPAのためのindexページをプロキシする」ミドルウェアなのでこういう名前なのはわかりにくいのか、わかりやすいのか・・・?
Middleware to proxy requests through a specified index page, useful for Single Page Applications that utilise the HTML5 History API.
最初、こいつが history APIをクライアント側で処理するライブラリかとばかり思ってスルーしていたのが冒頭に書いた「ちょっとハマった」の実態です。
koa-connect
connect
のミドルウェアを koa 向けに変換するアダプタ。名前もうちょっとわかりやすくしてもいいんじゃないかとは思う。 https://github.com/vkurchatkin/koa-connect リポジトリ見ると最終更新2年前。まあミドルウェアのインターフェイスなんてそうそう変更されないし別にいいのか。