0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Express × React の環境をゼロから構築

Posted at

Reactの環境構築(Frontend)

packageのインストール

■ webpack

npm i -D webpack-cli webpack webpack-dev-server html-webpack-plugin

■ babel

# ※変更 プリセットが古くなってたので、新しいプリセットに切り替え
npm uninstall babel-preset-react # 削除用
npm install --save-dev @babel/preset-react @babel/core @babel/preset-env babel-loader
.babelrc
"presets": ["@babel/preset-env", "@babel/preset-react"]

■ loader

🌾 正直よくわかってない。

npm i -D css-loader style-loader

■ React

npm i -S react react-dom

Reactをビルドして画面に表示させてみる

■ ベースとなるHTMLを作成

src/client/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>React and Webpack4</title>
</head>
<body>
<section id="index"></section>
</body>
</html> 

■ "Hello React!" を描画するシンプルなReactを実装

src/client/index.js
import React from "react";
import ReactDOM from "react-dom";

const Index = () => {
  return <div>Hello React!</div>;
};

ReactDOM.render(<Index />, document.getElementById("index")); 

■ webpackの設定ファイルを作成
ここで、html-webpack-pluginの設定をする。
htmlにreactのコードが埋め込まれたものをdestディレクトリ配下に生成するためのやつ。

config/webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require('path')

const htmlWebpackPlugin = new HtmlWebPackPlugin({
  template: "./src/client/index.html",
  filename: "./index.html"
});
 module.exports = {
  entry: "./src/client/index.js",
  output: {
    path: path.resolve('dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  plugins: [htmlWebpackPlugin]
}; 

■ package.jsonにコンパイル用のスクリプトを追記

package.json
  "scripts": {
    "client": "webpack-dev-server --config ./config/webpack.config.js --open --mode development",
    "build": "webpack --config ./config/webpack.config.js --mode development"
  },

実行してみる。

npm run client

Screenshot 2024-07-31 at 09.56.39.png
frontの開発サーバーが立ち上がって、Hello React!がブラウザに表示される。
ここでは、webpack-dev-serverを利用して開発用のサーバーを立ち上げている。

sh
npm run build

frontのコードがビルドされて、dist/ 配下にbuildされたコードがdistされる。

expressの環境構築(Backend)

packageのインストール

■ express

npm i -S express

■ babel

npm install --save-dev @babel/preset-env @babel/preset-react @babel/cli @babel/node

本来 ES5 環境であれば server 側にビルドは不要だが、今回は ES6 を利用したいので babel を利用。

.babelrc
# すでに設定ずみのはず
"presets": ["@babel/preset-env", "@babel/preset-react"]

■ その他 実行用
開発時に利用するパッケージたち。

npm i -D nodemon concurrently
# nodemon : 対象のファイルを監視しnodeプロセスを再起動する
# concurrently : 複数のコマンドを並列に実行する

expressサーバーの立ち上げ

clientへのルーティングと、バックエンドAPIを実装。

src/server/server.js
import express from 'express';
import path from 'path';

const app = express();

// 静的ファイルがリクエストされた場合、dist内からそれを返却する
// ex) http://localhost:3000/index.html, http://localhost:3000/styles.css
app.use(express.static(path.resolve('./', 'dist')));

// /api へのリクエストの場合、JSONレスポンスが返される
app.get('/api', (req, res) => {
  res.send({api: 'test'});
})

// 全ての残りのリクエストを index.html にリダイレクト
app.get('*', function (req, res) {
  res.sendFile(path.resolve('./', 'dist', 'index.html'))
})

// サーバーの起動
app.listen(3000, ()=> {
  console.log('server running');
})
package.json
# 追加
"scripts": {
 "server": "nodemon src/server/server.js  --exec babel-node",
  "dev": "concurrently \"npm run client\" \"npm run server\""

※ babel-cli で直接ES6を実行してるので server 側のコードはコンパイルされない。

babel-node is a CLI that works exactly the same as the Node.js CLI, with the added benefit of compiling with Babel presets and plugins before running it.
https://babeljs.io/docs/babel-node

もっと詳しく babel-node は、babel-cli の一部で、BabelがJavaScriptコードを実行しながらトランスパイルするので、src/server/server.js のコードが事前にトランスパイルされることはなく、そのままES6の形式で保存される。サーバーが実行されるたびに、babel-node がそのコードをリアルタイムでトランスパイルして実行するので、手元に変換後のコードが保存されない。

実行してみる。

npm run dev

下記サーバーが並列に立ち上がる。

サーバー host 用途
web-dev-server localhost:8080 webpack-dev-server
express server localhost:3000 expressサーバー

8080, 3000共に ルートにアクセスすると "Hello React!"のページが表示されるはず。

Frontend と Backend の連携

ひとまず、client と server をそれぞれ立ち上げて "Hello React!" のページを表示できるようにはなった。
......が、このままだとフロントからバックエンドのAPIを叩こうとするとポートが違うためCORSで弾かれてしまう。

それを回避するために開発サーバー側にProxyを建てる。
ただ、Proxyは開発時しか必要ないので、dev専用のwebpack.config.jsを用意。

packageのインストール

■ webpack-merge
webpack-mergeは2つのwebpack.configをマージすることができるプラグイン。
これを利用して、開発用の設定のみを切り出す。

npm i -D webpack-merge
config/webpack.config.dev.js
const { merge } = require('webpack-merge');
const path = require('path');
const webpackConfig = require('./webpack.config.js');

module.exports = merge(webpackConfig, {
  mode: 'development',
  devServer: {
    historyApiFallback: true,
    open: true,
    host: 'localhost',
    port: 8080,
    proxy: [
      {
        context: ['/api/**'],
        target: 'http://localhost:3000',
        secure: false,
        logLevel: 'debug',
      }
    ],
    static: {
      directory: path.resolve('./', 'dist')
    },
  }
})

webpack-dev-serverで/api/ でアクセスした場合のみ、3000に向けてリクエストするProxyが立ち上がる。

この設定をdevの時にのみ読み込むように書き換える。

package.json
  "scripts": {
    "server": "nodemon src/server/server.js  --exec babel-node",
    "client": "webpack-dev-server --config ./config/webpack.config.dev.js",
    "build": "webpack --config ./config/webpack.config.js --mode production",
    "dev": "NODE_ENV=development concurrently \"npm run client\" \"npm run server\"",
    "start": "NODE_ENV=production npm run build && npm run server"
  },
タスク 説明
server expressの立ち上げ
client webpack-dev-serverの立ち上げ
build frontのコードのコンパイル
dev 開発モードで、expressサーバーとwebpack-dev-serverが立ち上がる
start 本番モードで、frontコードをコンパイルし、expressを立ち上げる

バックエンドAPIを叩くように実装。

src/client/index.js
import React from "react";
import ReactDOM from "react-dom";

fetch('/api/').then(response => {
  console.log(response.json());
})

export const Index = () => {
  return <div>Hello React!</div>;
};

ReactDOM.render(<Index />, document.getElementById("index")); 

localhost:8080を叩くとバックエンドAPIの結果が返ってくるはず。

その他ツール

ほとんどそのままできたけど、差分だけメモ。

configuration

パッケージインストール時に、js-yamlも必要だった。

npm i config
npm install js-yaml --save

logging

下記のimportが必要だった。

src/server/server.js
import { logger } from './logger';
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?