如何配置带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
相关产品推荐
相关产品推荐

