You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置带Vite的Docker化Laravel开发环境以实现HMR与SPA特性

Docker化Laravel+Vite+React+Inertia环境中HMR与SPA特性失效问题排查与修复

我的目标是为开发环境配置Docker化的Laravel + Vite + React.js + Inertia.js。目前应用能正常运行,但缺少热模块替换(HMR)功能,页面加载方式类似SSR页面,没有SPA的快速加载体验。

假设:
Vite服务可能未正常工作

现象:

  • localhost:8000可以正常显示应用,但无HMR和SPA特性
  • localhost:5173显示Laravel+Vite默认页面

相关配置文件

Dockerfile

# Use the official PHP image as a base
FROM php:8.2-fpm

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip \
    nodejs \
    npm \
    && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

# Install Composer 2.2
RUN curl -sS https://getcomposer.org/installer | php -- --version=2.2.0 --install-dir=/usr/bin --filename=composer

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www-data:www-data . /var/www

# Install Laravel dependencies
RUN composer install

RUN npm install

# Expose port 9000 and start php-fpm server
EXPOSE 9000 5173
CMD ["sh", "-c", "php-fpm & npm run dev"]

docker-compose.yml

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: laravel_app
    container_name: laravel_app
    ports:
      - "5173:5173"
    restart: unless-stopped
    working_dir: /var/www
    volumes:
      - .:/var/www
      - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
    networks:
      - laravel
    environment:
      - APP_ENV=local
      - APP_DEBUG=true
      - APP_KEY=${APP_KEY}
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_PORT=3306
      - DB_DATABASE=laravel
      - DB_USERNAME=laravel
      - DB_PASSWORD=laravel

  web:
    image: nginx:alpine
    container_name: laravel_web
    #restart: unless-stopped
    ports:
      - "8000:80"
    volumes:
      - .:/var/www
      - ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    networks:
      - laravel
    depends_on:
      - app

  db:
    image: mysql
    container_name: laravel_db
    restart: unless-stopped
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: laravel
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - laravel

volumes:
  dbdata:
  
networks:
  laravel:
    driver: bridge

nginx.conf

server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    root /var/www/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    location /_vite/ {
        proxy_pass http://app:5173;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location ~ /\.ht {
        deny all;
    }
}

vite.config.js

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.jsx',
            ],
            refresh: true,
        }),
        react({}),
    ],
    server: {
        host: '0.0.0.0',
        port: 5173,
        hmr: {
            host: 'localhost',
        },
    },
});

问题修复方案

1. 修正Vite的HMR配置

Docker容器内无法直接识别宿主机的localhost,需调整HMR配置为Docker内置的宿主机别名,同时开启文件轮询解决容器内文件监听失效问题:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.jsx',
            ],
            refresh: true,
        }),
        react({}),
    ],
    server: {
        host: '0.0.0.0',
        port: 5173,
        hmr: {
            host: 'host.docker.internal',
            protocol: 'ws',
            clientPort: 5173,
        },
        watch: {
            usePolling: true,
        },
    },
});

2. 完善Nginx的Vite代理配置

当前代理路径不全,需覆盖Vite所有相关请求路径,确保WebSocket通信正常:

server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    root /var/www/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    # 代理Vite开发服务器及HMR全量路径
    location ~ ^/(.*)$ {
        if ($uri ~* ^/(_vite|@vite|__vite_ping|vite\.js)$) {
            proxy_pass http://app:5173;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    location ~ /\.ht {
        deny all;
    }
}

3. 优化Docker容器启动逻辑

调整Dockerfile,利用缓存减少构建时间,同时确保Vite服务前台稳定运行:

# Use the official PHP image as a base
FROM php:8.2-fpm

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip \
    nodejs \
    npm \
    && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

# Install Composer 2.2
RUN curl -sS https://getcomposer.org/installer | php -- --version=2.2.0 --install-dir=/usr/bin --filename=composer

# 先复制依赖文件缓存,避免代码变更重复安装
COPY composer.json composer.lock ./
RUN composer install --no-scripts --no-autoloader

COPY package.json package-lock.json ./
RUN npm install

# 复制应用代码
COPY . /var/www
COPY --chown=www-data:www-data . /var/www

# 生成自动加载文件
RUN composer dump-autoload --optimize

# Expose ports
EXPOSE 9000 5173

# 确保服务前台运行
CMD ["sh", "-c", "php-fpm & npm run dev && wait"]

4. 验证Inertia.js路由配置

确保Laravel路由使用Inertia渲染,前端跳转使用Inertia的Link组件而非原生a标签:

// routes/web.php
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Welcome');
});

Route::get('/dashboard', function () {
    return Inertia::render('Dashboard');
})->middleware(['auth', 'verified']);

5. 重启服务验证

执行以下命令重建并重启容器:

docker-compose down
docker-compose build --no-cache
docker-compose up -d

访问localhost:8000,修改React组件代码,验证HMR自动刷新是否生效,同时检查页面跳转是否为SPA无刷新模式。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:50:57