diff --git a/web/Dockerfile b/web/Dockerfile index 3485713b..3b3ea298 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -4,6 +4,7 @@ WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile COPY . . +ENV VITE_BASE_PATH=/skillhub-web/ RUN pnpm build FROM jsessh-registry.cn-shanghai.cr.aliyuncs.com/base-images/nginx-skillhub:alpine diff --git a/web/nginx.conf.template b/web/nginx.conf.template index 9899efb8..7589ba1f 100644 --- a/web/nginx.conf.template +++ b/web/nginx.conf.template @@ -10,11 +10,12 @@ server { gzip_types text/plain text/css application/json application/javascript text/xml; gzip_min_length 1000; - location / { - try_files $uri $uri/ /index.html; + location /skillhub-web/ { + alias /usr/share/nginx/html/; + try_files $uri $uri/ /skillhub-web/index.html; } - location /api/ { + location /skillhub-web/api/ { proxy_pass ${SKILLHUB_API_UPSTREAM}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -22,45 +23,51 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } - location /oauth2/ { + location /skillhub-web/oauth2/ { proxy_pass ${SKILLHUB_API_UPSTREAM}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } - location /login/oauth2/ { + location /skillhub-web/login/oauth2/ { proxy_pass ${SKILLHUB_API_UPSTREAM}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } - location /.well-known/ { + location /skillhub-web/.well-known/ { proxy_pass ${SKILLHUB_API_UPSTREAM}; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; } - location /assets/ { + location /skillhub-web/assets/ { + alias /usr/share/nginx/html/assets/; expires 1y; add_header Cache-Control "public, immutable"; } - location = /registry/skill.md { + location = /skillhub-web/registry/skill.md { + alias /usr/share/nginx/html/registry/skill.md; default_type text/plain; add_header Content-Disposition "inline"; add_header X-Content-Type-Options "nosniff"; - try_files $uri =404; } - location = /runtime-config.js { + location = /skillhub-web/runtime-config.js { + alias /usr/share/nginx/html/runtime-config.js; add_header Cache-Control "no-store"; - try_files $uri =404; } location /nginx-health { return 200 'ok'; add_header Content-Type text/plain; } + + # 根路径重定向到子路径 + location = / { + return 301 /skillhub-web/; + } } diff --git a/web/package.json b/web/package.json index 728f7a23..54660099 100644 --- a/web/package.json +++ b/web/package.json @@ -45,6 +45,7 @@ "devDependencies": { "@playwright/test": "^1.58.2", "@types/mdast": "^4.0.4", + "@types/node": "^25.5.2", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@typescript-eslint/eslint-plugin": "^7.0.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index a2c150da..f0bd2803 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -87,6 +87,9 @@ importers: '@types/mdast': specifier: ^4.0.4 version: 4.0.4 + '@types/node': + specifier: ^25.5.2 + version: 25.5.2 '@types/react': specifier: ^19.0.0 version: 19.2.14 @@ -101,7 +104,7 @@ importers: version: 7.18.0(eslint@8.57.1)(typescript@5.9.3) '@vitejs/plugin-react': specifier: ^4.3.0 - version: 4.7.0(vite@6.4.1(jiti@1.21.7)) + version: 4.7.0(vite@6.4.1(@types/node@25.5.2)(jiti@1.21.7)) autoprefixer: specifier: ^10.4.0 version: 10.4.27(postcss@8.5.8) @@ -128,10 +131,10 @@ importers: version: 5.9.3 vite: specifier: ^6.1.0 - version: 6.4.1(jiti@1.21.7) + version: 6.4.1(@types/node@25.5.2)(jiti@1.21.7) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(jiti@1.21.7) + version: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.2)(jiti@1.21.7) packages: @@ -984,6 +987,9 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@25.5.2': + resolution: {integrity: sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==} + '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: @@ -2375,6 +2381,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -3327,6 +3336,10 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@25.5.2': + dependencies: + undici-types: 7.18.2 + '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 @@ -3422,7 +3435,7 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-react@4.7.0(vite@6.4.1(jiti@1.21.7))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.5.2)(jiti@1.21.7))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -3430,7 +3443,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.1(jiti@1.21.7) + vite: 6.4.1(@types/node@25.5.2)(jiti@1.21.7) transitivePeerDependencies: - supports-color @@ -3442,13 +3455,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.4.1(jiti@1.21.7))': + '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@25.5.2)(jiti@1.21.7))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.4.1(jiti@1.21.7) + vite: 6.4.1(@types/node@25.5.2)(jiti@1.21.7) '@vitest/pretty-format@3.2.4': dependencies: @@ -4990,6 +5003,8 @@ snapshots: typescript@5.9.3: {} + undici-types@7.18.2: {} + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -5071,13 +5086,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-node@3.2.4(jiti@1.21.7): + vite-node@3.2.4(@types/node@25.5.2)(jiti@1.21.7): dependencies: cac: 6.7.14 debug: 4.4.3(supports-color@10.2.2) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.4.1(jiti@1.21.7) + vite: 6.4.1(@types/node@25.5.2)(jiti@1.21.7) transitivePeerDependencies: - '@types/node' - jiti @@ -5092,7 +5107,7 @@ snapshots: - tsx - yaml - vite@6.4.1(jiti@1.21.7): + vite@6.4.1(@types/node@25.5.2)(jiti@1.21.7): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -5101,14 +5116,15 @@ snapshots: rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: + '@types/node': 25.5.2 fsevents: 2.3.3 jiti: 1.21.7 - vitest@3.2.4(@types/debug@4.1.12)(jiti@1.21.7): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.2)(jiti@1.21.7): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.4.1(jiti@1.21.7)) + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@25.5.2)(jiti@1.21.7)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -5126,11 +5142,12 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.1(jiti@1.21.7) - vite-node: 3.2.4(jiti@1.21.7) + vite: 6.4.1(@types/node@25.5.2)(jiti@1.21.7) + vite-node: 3.2.4(@types/node@25.5.2)(jiti@1.21.7) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 + '@types/node': 25.5.2 transitivePeerDependencies: - jiti - less diff --git a/web/vite.config.ts b/web/vite.config.ts index aff7ad67..caac3178 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,17 +1,15 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' -import path from 'path' +import * as path from 'path' export default defineConfig({ + base: process.env.VITE_BASE_PATH || '/', plugins: [react()], resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, - test: { - exclude: ['**/node_modules/**', '**/e2e/**'], - }, server: { port: 3000, watch: {