43
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

いなたつAdvent Calendar 2019

Day 24

ReactとNginxでリロードしても404しないSPAを作る

Last updated at Posted at 2019-12-24

はじめに

いなたつアドカレの二十四日目の記事です。
Dockerを使ってReactで作ったアプリケーションをnginx上にポイ投げするためのあれですね。

DockerってなにとかnginxってなにReactってなにってのはスルーで行きます。
今回の記事はcreate-react-app(以下CRA)を使用する前提となっています。

つかうもの

  • react
  • react-router
  • nginx
  • docker

完成系

react-router使ってnginx上でリンクに#がつかないかつリロードしても404にならない構成の作成

ディレクトリ構成

  • app
    • docker
      • react
        • Dockerfile
      • nginx
        • default.conf
    • web
    • docker-compose.yml

こんなかんじです

dockerディレクトリにdockerで使用するファイルを格納しています。
webディレクトリにCRAで作成したアプリが入りますね。

DockerでReact

docker-compose.yml
version: '3'

services:
  react_app:
    container_name: react_app
    build: ./docker/react
    command: npm start
    volumes:
      - ./web:/app
    ports:
      - 3000:3000

つづいて
docker/react/Dockerfile

FROM node

WORKDIR /app

ここは基本的になんでも構いません(めんどくさかった)
作成するアプリケーションに合わせてpackage.jsonなどを用意してあげてください。
今回は めんどくさいので これでいきます。

Dockerで んぎっくす

はい、Nginxいきます

docker-compose.yml
nginx:
    image: nginx
    container_name: nginx
    ports:
      - 8080:80
    volumes:
      - ./web/build:/var/www
      - ./docker/nginx/:/etc/nginx/conf.d/
    depends_on:
      - react_app

web(CRAのディレクトリ)の中のbuildをnginxコンテナにマウントしています。
docker/nginxには設定ファイルですね。

default.conf
server {
    listen       80;

    location / {
        root   /var/www;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

buildをマウントしてそのマウントしたファイルのindex.htmlを表示するぜ〜って感じですね。

Reactのコンポーネント構成

App.js
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Hello from './Pages/Hello'
import Changed from './Pages/Changed'




function App() {
  return (
    <Router>
        <Route exact path='/' component={Hello} />
        <Route exact path='/changed' component={Changed} />
    </Router>

  );
}


export default App;

react-routerで2つのページを遷移できるようにします。

/Pages/Hello,js
import React  from 'react';
import {Link} from 'react-router-dom'

const Hello = () => {

    return (
        <div>
            <div>Hello</div>
            <Link to='/changed'>ぺーじせんい</Link>
        </div>
    )
}

export default Hello;
/Pages/Changed,js

import React from 'react';

const Changed = () => {

    return (
        <div>
            <div>Changed</div>
        </div>
    )
}
export default Changed;

ページ遷移するだけですね。

うごかしてみる

とりあえずreactのプロジェクトをbuildしましょう。

localhost:8080にアクセスします。

スクリーンショット 2019-12-24 14.05.23.png

こんな感じですね。

ページ遷移してみます。

スクリーンショット 2019-12-24 14.05.29.png

遷移できましたね。おっけーです。

ちょっとリロードしたくなってきたわ

スクリーンショット 2019-12-24 14.05.34.png

あっあっあっ

だめですね。んぎっくすさんに怒られちゃいました。

ハッシュルーターとかダサいじゃん?

URLに「#」とかつくHashルーターをつかうことでこれを解決することはできます。

localhost:8080/#/changedだっっっっっっっっっさあああああい

やだよ。

解決しよう

nginxの設定を少し変えましょう

default.conf
server {
    listen       80;

    location / {
        root   /var/www;
        index  index.html index.htm;
        try_files $uri /index.html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

try_files $uri /index.html;この一行を書くだけですね。

ほら、リロードしてみてくださいよ、怒られますか?怒られませんよね。

これで解決ですね。

なぜ解決できたのか

とりま解決でけたらえーねんって人はみなくてよきですえ

nginxにはtry_files ディレクティブというものが存在し、これは、引数を前から順番にファイルが存在するかをtryしまくって行ってくれます。そして見つからなかった場合はindex.htmlを返却しましょうねっていう感じです。

何も見つからなかったら404を返すよ〜って実装をする場合もありますね。

43
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?