我想在 docker 环境内的本地 WordPress 主题开发中在 Nginx 和 Vite 之间进行反向代理。我这里的设置在生产中有效,否则在开发中不起作用。它返回 404
https://localhost.test/main.js
,我无法看到任何文件更改。
项目结构
project-dir/
- certs/
- localhost.test.pem
- localhost.test-key.pem
- config/
- nginx.conf
- default.conf
- logs/
- mytheme/
- index.php
- functions.php
- style.css
- vite.config.js
- package.json
- Dockerfile
- docker-compose.yml
/etc/hosts
127.0.0.1 localhost
127.0.0.1 localhost.test
Dockerfile
FROM mariadb:latest AS db
FROM wordpress:6.5.2-php8.3-fpm-alpine as wp
RUN set -ex; \
apk --no-cache add sudo \
&& rm -rf /var/cache/apk/*
VOLUME /var/www/html
WORKDIR /var/www/html
RUN chown -R www-data:www-data /var/www/html
USER www-data
FROM nginx:alpine3.19 as server
RUN set -x; \
addgroup -g 1000 -S www-data ; \
adduser -u 1000 -D -S -G www-data www-data && exit 0 ; exit 1
RUN set -eux; \
apk update && apk --no-cache add \
curl \
&& addgroup www-data nginx \
&& rm -rf /var/cache/apk/*
COPY ./certs:/etc/nginx/certs
COPY ./config/nginx.conf /etc/nginx/nginx.conf
COPY ./config/default.conf /etc/nginx/conf.d/default.conf
VOLUME /var/www/html
WORKDIR /var/www/html
RUN chown -R www-data:www-data /var/www/html
CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml
version: '3.9'
services:
db:
build:
target: db
image: localhost/db
container_name: db
restart: unless-stopped
volumes:
- ./logs/sql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
networks:
- wp_net
wp:
build:
target: wp
image: localhost/wp
container_name: wp
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DEBUG: 1
WORDPRESS_CONFIG_EXTRA: |
define( 'WP_HOME','https://localhost.test' );
define( 'WP_SITEURL','https://localhost.test' );
define( 'FS_METHOD', 'direct' );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
define( 'FORCE_SSL_ADMIN', true );
define( 'IS_VITE_DEVELOPMENT', true );
volumes:
- wp_data:/var/www/html
- ./mytheme:/var/www/html/wp-content/themes/mytheme
depends_on:
- db
networks:
- wp_net
nginx:
build:
target: server
image: localhost/nginx
container_name: nginx
restart: unless-stopped
volumes:
- wp_data:/var/www/html:ro
- ./logs/nginx:/var/log/nginx
- ./mytheme:/var/www/html/wp-content/themes/mytheme:ro
ports:
- 80:80
- 443:443
depends_on:
- wp
networks:
wp_net:
aliases:
- localhost.test
volumes:
wp_data:
networks:
wp_net:
nginx.conf
user www-data;
worker_processes 1;
pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time $pipe $upstream_cache_status';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
gzip on;
gzip_disable "msie6";
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
默认.conf
upstream wp {
server wp:9000;
}
server {
listen [::]:80;
listen 80;
listen [::]:443 ssl;
listen 443 ssl;
http2 on;
server_name localhost.test;
root /var/www/html;
index index.php;
sendfile off;
access_log /var/log/nginx/wp.access.log;
error_log /var/log/nginx/wp.error.log;
add_header Strict-Transport-Security "max-age=31536000" always;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDH+AESGCM:ECDH+AES256:ECDH+AES128:!ADH:!AECDH:!MD5;";
# generated with mkcert
ssl_certificate /etc/nginx/certs/localhost.test.pem;
ssl_certificate_key /etc/nginx/certs/localhost.test-key.pem;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass wp;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
functions.php
<?php
define('DIST_URI', get_template_directory_uri() . '/dist');
define('DIST_PATH', get_template_directory() . '/dist');
define('IS_VITE_DEVELOPMENT', true);
define('VITE_SERVER', 'https://localhost.test');
define('VITE_ENTRY_POINT', '/main.js');
// enqueue hook
add_action( 'wp_enqueue_scripts', function() {
if (defined('IS_VITE_DEVELOPMENT') && IS_VITE_DEVELOPMENT === true) {
// This is the problem.
function vite_head_module_hook() {
echo '<script type="module" crossorigin src="'. VITE_SERVER . VITE_ENTRY_POINT . '"></script>';
}
add_action( 'wp_head', 'vite_head_module_hook' );
} else {
// For production.
}
});
package.json
{
"name": "mytheme",
"version": "1.0.0",
"main": "main.js",
"license": "MIT",
"private": true,
"type": "module",
"scripts": {
"dev": "cross-env NODE_ENV=development vite",
"build": "rimraf dist && vite build",
"preview": "vite preview"
},
"devDependencies": {
"cross-env": "^7.0.3",
"rimraf": "^5.0.5",
"vite": "^5.2.11"
},
"packageManager": "[email protected]"
}
vite.config.js
import { defineConfig } from "vite";
import { resolve } from 'path';
export default defineConfig({
plugins: [
{
handleHotUpdate({ file, server }) {
if (file.endsWith('.php')) {
server.ws.send({ type: 'full-reload', path: '*' });
}
}
}
],
root: '',
base: process.env.NODE_ENV === 'development'
? '/'
: '/dist/',
build: {
outDir: resolve(__dirname, './dist'),
emptyOutDir: true,
manifest: true,
rollupOptions: {
input: {
main: resolve(__dirname + '/main.js')
},
}
},
server: {
host: true,
cors: true,
strictPort: true,
hmr: {
host: "localhost.test",
},
}
})
Vite使用
https://localhost:5137
来服务HMR。但是,我想使用 https://localhost.test
来观看文件更改。如何以良好的方式实现这一目标?
任何帮助将不胜感激。
我现在能弄清楚了。只需要触摸两个文件:
functions.php
和vite.config.js
。
在 functions.php 中,将值更改为:
define('VITE_SERVER', 'https://localhost.test');
至:
define('VITE_SERVER', 'http://localhost:5137'); // Adjust to your vite port.
在vite.config.js中,将服务器块更改为:
server: {
host: '0.0.0.0',
strictPort: true,
proxy: {
'/wp-content/**': {
target: 'https://localhost.test', // Adjust to your domain.
changeOrigin: true,
rewrite: (path) => path.replace(/^\/wp-content/, '.') // Dot means current directory or adjust to your need.
}
}
}
希望它可以帮助任何人。谢谢。