diff --git a/deployment/frontend/Dockerfile b/deployment/frontend/Dockerfile index 6f37ca0..bfe8d0f 100644 --- a/deployment/frontend/Dockerfile +++ b/deployment/frontend/Dockerfile @@ -11,6 +11,7 @@ RUN --mount=type=cache,target=/root/.npm \ COPY frontend frontend RUN npm run frontend:build + # 2. Build the static file server FROM node:24 AS server @@ -20,9 +21,13 @@ COPY deployment/frontend/package.json . RUN --mount=type=cache,target=/root/.npm \ npm install +# 2.2. Build +RUN npm run build + # 2.2. Copy the code COPY deployment/frontend/ . + # 3. Put it all together FROM node:24-slim @@ -44,4 +49,4 @@ COPY --from=server --chown=app /server . # 4. Final command ENV STATIC_FILE_PATH=/app -ENTRYPOINT ["npm", "run", "start"] \ No newline at end of file +ENTRYPOINT ["npm", "run", "start:prod"] \ No newline at end of file diff --git a/deployment/frontend/package.json b/deployment/frontend/package.json index de98491..233c6f0 100644 --- a/deployment/frontend/package.json +++ b/deployment/frontend/package.json @@ -3,10 +3,18 @@ "version": "1.0.0", "main": "server.js", "scripts": { - "start": "node server.js" + "start": "ts-node server.ts", + "build": "tsc", + "start:prod": "node dist/server.js" }, "dependencies": { "express": "^5.1.0", "http-proxy-middleware": "^3.0.5" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/node": "^20.10.0", + "typescript": "^5.3.0", + "ts-node": "^10.9.0" } } diff --git a/deployment/frontend/server.js b/deployment/frontend/server.js deleted file mode 100644 index af4c43c..0000000 --- a/deployment/frontend/server.js +++ /dev/null @@ -1,22 +0,0 @@ -// server.js -const express = require('express'); -const { createProxyMiddleware } = require('http-proxy-middleware'); -const path = require('path'); - -const app = express(); -const port = process.env.PORT || 3000; -const backendHost = process.env.BACKEND_HOST || "http://localhost:8300"; -const file_path = process.env.STATIC_FILE_PATH || "."; - -app.use('/api', createProxyMiddleware({ - target: backendHost, - changeOrigin: true, - pathRewrite: { '^/api': '' }, - ws: true -})); - -app.use(express.static(path.resolve(file_path))); - -app.listen(port, () => { - console.log(`Server launched на http://localhost:${port}`); -}); \ No newline at end of file diff --git a/deployment/frontend/server.ts b/deployment/frontend/server.ts new file mode 100644 index 0000000..9785831 --- /dev/null +++ b/deployment/frontend/server.ts @@ -0,0 +1,28 @@ +import express from 'express'; +import { createProxyMiddleware } from 'http-proxy-middleware'; +import { resolve } from 'path'; + +const app = express(); +const port = process.env.PORT || 3000; +const backendHost = process.env.BACKEND_HOST || "http://localhost:8300"; +const filePath = process.env.STATIC_FILE_PATH || "."; + +// API proxy middleware +app.use('/api', createProxyMiddleware({ + target: backendHost, + changeOrigin: true, + pathRewrite: { '^/api': '' }, + ws: true +})); + +// Serve static files +app.use(express.static(resolve(filePath))); + +// SPA routing - catch all handler for client-side routing +app.get('*', (_req, res) => { + res.sendFile(resolve(filePath, 'index.html')); +}); + +app.listen(port, () => { + console.log(`Server launched on http://localhost:${port}`); +}); diff --git a/deployment/frontend/tsconfig.json b/deployment/frontend/tsconfig.json new file mode 100644 index 0000000..c2fa00e --- /dev/null +++ b/deployment/frontend/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist", + "rootDir": "./", + "declaration": true, + "sourceMap": true + }, + "include": [ + "server.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 66e9e17..bb5d989 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -3,7 +3,6 @@ import { createHtmlPlugin } from "vite-plugin-html"; import autoprefixer from "autoprefixer"; import electron from "vite-plugin-electron/simple"; import react from "@vitejs/plugin-react"; -import { resolve } from "path"; const plugins: PluginOption[] = [ react(), @@ -61,7 +60,7 @@ export default defineConfig({ }, allowedHosts: ["beta.fromchat.ru"] }, - appType: "mpa", + appType: "spa", css: { postcss: { plugins: [autoprefixer()]