Laravel8 + Vue + Dockerを使ってサーバーサイドレンダリングする環境を構築する方法を解説します。
Vueを使うならSPAが主流ですが、
今回はサーバーサイドレンダリング(SSR)するMPAでLaravelとVueの開発環境を整えます。
理由としては、
SPAの性質上SEO的に良くない(クローラーに正しく認識されない)と言われているためです。
※ 実際のところは私の方では分かっていませんが、少なくともSSRなら確実です。
開発環境
使用するツールの各バージョンは以下の通りです。
Name | Version |
Laravel | 8.42.1 |
PHP | 7.4.19 |
Vue | 2.6.12 |
Docker | 20.10.2 |
Docker-compose | 1.27.4 |
Apache | 2.4.38 |
MariaDB | 10.5.10 |
Adminer | 4.8.1 |
全体の開発手順
- Dockerの設定をしてビルド&コンテナ起動する
- Laravelプロジェクトの作成と設定
- Vueの設定
- Laravel-mixでトランスパイルして画面に出力
ディレクトリ構造
ディレクトリの構造は以下の通りです。
root_folder/
├── docker/
│ └── web/
│ ├── Dockerfile
│ ├── apache/
│ │ └── 000-default.conf
│ └── php/
│ └── php.ini
├── mysql/
├── docker-compose.yml
└── server/
Dockerの設定
コンテナ起動に必要な各ファイルのソースコードを以下の通りに記述して下さい。
[Dockerfile]
FROM php:7.4-apache
COPY ./php/php.ini /usr/local/etc/php/
COPY ./apache/*.conf /etc/apache2/sites-enabled/
RUN apt-get update \
&& apt-get install -y zlib1g-dev libpq-dev mariadb-client unzip libzip-dev\
&& docker-php-ext-install zip pdo_mysql mysqli \
&& docker-php-ext-enable mysqli
# mod_rewriteを 有効に
RUN a2enmod rewrite
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin
WORKDIR /var/www/html
RUN composer global require "laravel/installer"
[docker-compose.yml]
version : "3"
services:
web:
container_name: web
build: ./docker/web
ports:
- 80:80
privileged: true
volumes:
- ./server:/var/www/html
db:
image: mariadb
restart: always
ports:
- 3307:3306
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/initdb:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=pwd
- MYSQL_DATABASE=test
- MYSQL_USER=user
- MYSQL_PASSWORD=pwd
adminer:
image: adminer
restart: always
ports:
- 8080:8080
[000-default.conf]
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/public
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Options Indexes FollowSymLinks MultiViews
Require all granted
AllowOverride All
[php.ini]
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
ビルドとコンテナ起動
docker-compose.ymlファイルがあるディレクトリにて、
以下のコマンドを実行して下さい。
command
$ docker-compose build --no-cache
$ docker-compose up -d
$ docker-compose ps -a
立ち上がったコンテナが以下のような状態であればコンテナ起動成功。
Name Command State Ports
------------------------------------------------------------------------------------------------------
adminer_1 entrypoint.sh docker-php-e ... Up 0.0.0.0:8080->8080/tcp,:::8080->8080/tcp
db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3307->3306/tcp,:::3307->3306/tcp
web docker-php-entrypoint apac ... Up 0.0.0.0:80->80/tcp,:::80->80/tcp
Laravelプロジェクトの作成と設定
ルートディレクトリ配下で下記コマンドを実行して、Laravelプロジェクトを作成します。
command
$ composer create-project laravel/laravel server --prefer-dist
下のように各ファイルが生成されます。
server
├── README.md
├── app/
├── artisan*
├── bootstrap/
├── composer.json
├── composer.lock
├── config/
├── database/
├── node_modules/
├── package-lock.json
├── package.json
├── phpunit.xml
├── public/
├── resources/
├── routes/
├── server.php
├── storage/
├── tests/
├── vendor/
└── webpack.mix.js
Vueの準備
Vueを使えるようにします。
vue-router含めて設定します。
package.jsonの"devDependencies"に次のように記述します。
"devDependencies": {
"axios": "^0.21",
"cross-env": "^7.0",
"laravel-mix": "^6.0.19",
"lodash": "^4.17.21",
"postcss": "^8.2.15",
"postcss-loader": "^5.3.0",
"resolve-url-loader": "^4.0.0",
"sass": "^1.32.13",
"sass-loader": "^11.1.1",
"vue": "^2.6.12",
"vue-loader": "^15.9.5",
"vue-router": "^3.5.1",
"vue-template-compiler": "^2.6.12"
}
以下コマンドを実行してライブラリをインストールします。
command
$ npm install
vueファイルをトランスパイルするために、
webpack.mix.jsに以下を記述して下さい。
const mix = require("laravel-mix");
mix.js("resources/js/app.js", "public/js")
.js("resources/js/router.js", "public/js")
.vue()
.postCss("resources/css/app.css", "public/css", [
]);
Laravelプロジェクトの中のresourcesディレクトリにて、
以下のようにファイルとフォルダを作成して下さい。
resources/
├── js/
│ ├── app.js
│ ├── bootstrap.js
│ ├── components/
│ │ └── pages/
│ │ └── Home.vue
│ └── router.js
└── views/
└── app.blade.php
各ファイルのソースは以下の通りです。
※修正する必要のないものは下に記載していません。
[app.js]
import Vue from "vue";
import router from "./router";
const app = new Vue({
el: "#app",
router: router,
});
[Home.vue]
<template>
<div>Home画面</div>
</template>
[router.js]
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
import home from "./components/pages/Home.vue";
const router = new VueRouter({
mode: "history",
routes: [
{
path: "/",
name: "home",
component: home,
},
],
});
export default router;
[app.blade.php]
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<router-view />
</div>
<script src="{{ mix('/js/app.js') }}"></script>
</body>
</html>
Laravelのルーティングを下のようにapp.blade.phpが出力されるように記述します。
[web.php]
Route::get('/', function () {
return view('app');
});
vueファイルをトランスパイルする
最後にvueファイルをlaravel-mixでトランスパイルして画面に出力します。
下のコマンドをlaravelプロジェクトディレクトリ配下で実行して下さい。
これでファイルに変更があったら随時トランスパイルされるように監視してくれるようになります。
command
$ npm run watch-poll
localhostにアクセスして以下のように画面に表示されれば成功です。