create-react-appで作成したアプリに別のエンドポイント(html)を生やす方法
はじめに
自分用の備忘録として書いているので説明が簡素なのと、細かなところまで確認していないので確認が漏れている箇所がある。
よって間違いが含まれている可能性がある。
また、この修正自体はちょっとした検証を行う際に必要だったという理由で行ったものであり、この設定を施したアプリをProduction環境にデプロイして確認したわけではないので、その点は注意する必要がある。
特に後半の rewrite の設定などはアプリの環境やデプロイするホスティングサービスによって設定を行う必要も出てくると思うので、参考程度にとどめてほしい。
目次
Create react appで作成したアプリに別のエンドポイントを生やす
Create react appで作成したアプリではエンドポイントが /
のみとなる。
今回 /about.html
というエンドポイントを生やし、about.html
にアクセスした場合はそちらはそちらで別のSPAとしてアプリを機能させたいと考えた。
このポストはそれを実現するまでのメモとなる。
基本的にgit の diff を貼り付けてメモを残す。
ejectする
まず eject
する。
ejectしないで済む方法はわからない。
yarn eject
一旦 eject
した状態で問題なくアプリが動くかを確認し、一旦コミットする。
以降の diff
はこのコミットした状態からの diff
となる。
別のエンドポイントを追加するまでの修正内容
まずは config/paths.js
を以下のように変更する。
--- a/config/paths.js +++ b/config/paths.js @@ -57,7 +57,9 @@ module.exports = { appBuild: resolveApp(buildPath), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), + appAboutHtml: resolveApp('public/about.html'), appIndexJs: resolveModule(resolveApp, 'src/index'), + appAboutJs: resolveModule(resolveApp, 'src/about'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), appTsConfig: resolveApp('tsconfig.json'),
次に config/webpack.config.js
を以下のように変更する。
--- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -200,7 +200,10 @@ module.exports = function (webpackEnv) { : isEnvDevelopment && 'cheap-module-source-map', // These are the "entry points" to our application. // This means they will be the "root" imports that are included in JS bundle. - entry: paths.appIndexJs, + entry: { + index:[paths.appIndexJs], + about:[paths.appAboutJs], + }, output: { // The build folder. path: paths.appBuild, @@ -210,7 +213,7 @@ module.exports = function (webpackEnv) { // In development, it does not produce real files. filename: isEnvProduction ? 'static/js/[name].[contenthash:8].js' - : isEnvDevelopment && 'static/js/bundle.js', + : isEnvDevelopment && 'static/js/[name].bundle.js', // There are also additional JS chunk files if you use code splitting. chunkFilename: isEnvProduction ? 'static/js/[name].[contenthash:8].chunk.js' @@ -569,7 +572,36 @@ module.exports = function (webpackEnv) { {}, { inject: true, + chunks: ["index"], template: paths.appHtml, + filename: "index.html" + }, + isEnvProduction + ? { + minify: { + removeComments: true, + collapseWhitespace: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + removeStyleLinkTypeAttributes: true, + keepClosingSlash: true, + minifyJS: true, + minifyCSS: true, + minifyURLs: true, + }, + } + : undefined + ) + ), + new HtmlWebpackPlugin( + Object.assign( + {}, + { + inject: true, + chunks: ["about"], + template: paths.appAboutHtml, + filename: "about.html" }, isEnvProduction ? { @@ -642,9 +674,12 @@ module.exports = function (webpackEnv) { manifest[file.name] = file.path; return manifest; }, seed); - const entrypointFiles = entrypoints.main.filter( - fileName => !fileName.endsWith('.map') - ); + + let entrypointFiles = []; + for(let [entryFile, fileName] of Object.entries(entrypoints)) { + let notMapFiles = fileName.filter(fieldName => !fieldName.endsWith(".map")) + entrypointFiles = entrypointFiles.concat(notMapFiles); + } return { files: manifestFiles,
この時点で /about.html
にアクセスして意図したページが表示されることを確認。
rewriteの設定
ただし、/about.html/foo
みたいなURLをReact Routerなどでアクセスできるようにしている場合、/about.html/foo
の状態でリロードすると意図した画面が表示されない。
ここでは config/webpackDevServer.config.js
を編集し、下記のようなリダイレクト処理を挟むことにする。
ちなみに verbose: true
にすると、 Rewriting
時のログをコンソール上で確認できる。
--- a/config/webpackDevServer.config.js +++ b/config/webpackDevServer.config.js @@ -98,6 +98,10 @@ module.exports = function (proxy, allowedHost) { // See https://github.com/facebook/create-react-app/issues/387. disableDotRule: true, index: paths.publicUrlOrPath, + verbose: true, + rewrites: [ + { from : /^\/about/, to: "/about.html" } + ] }, // `proxy` is run between `before` and `after` `webpack-dev-server` hooks proxy,
これで /about.html/foo
の状態でリロードしても、意図したページの状態で描画されることが確認できた。