fix(deploy): prod-бандл без devDependencies — динамический импорт vite в setupVite
Шаги 0.5/0.2 плана production-готовности (досрочно ушли с a54ec77):
- Dockerfile: npm ci --omit=dev вместо копирования node_modules из builder,
пользователь app (USER app), HOME=/tmp, npm_config_cache=/tmp/.npm
- docker/Dockerfile.documents: USER app, HOME=/tmp
- server/vite.ts: vite и vite.config импортируются динамически внутри setupVite —
иначе prod-бандл падал с ERR_MODULE_NOT_FOUND (@vitejs/plugin-react)
- package.json: vitest/supertest/@types/* (16 пакетов) перенесены
в devDependencies — именно vitest в dependencies тянул vite/esbuild/tsx в прод-образ
Проверено локально: образ собирается, uid=1001(app), /app/data доступна на запись,
бандл стартует без devDeps (падает только на отсутствии JWT-секретов окружения)
This commit is contained in:
192
package-lock.json
generated
192
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@@ -76,20 +76,6 @@
|
|||||||
"@tiptap/starter-kit": "^3.27.0",
|
"@tiptap/starter-kit": "^3.27.0",
|
||||||
"@tiptap/suggestion": "^3.27.0",
|
"@tiptap/suggestion": "^3.27.0",
|
||||||
"@turbodocx/html-to-docx": "^1.22.0",
|
"@turbodocx/html-to-docx": "^1.22.0",
|
||||||
"@types/archiver": "^8.0.0",
|
|
||||||
"@types/bcrypt": "^6.0.0",
|
|
||||||
"@types/cors": "^2.8.19",
|
|
||||||
"@types/dompurify": "^3.0.5",
|
|
||||||
"@types/js-beautify": "^1.14.3",
|
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
|
||||||
"@types/jspreadsheet-ce": "^4.7.9",
|
|
||||||
"@types/multer": "^2.0.0",
|
|
||||||
"@types/pg": "^8.20.0",
|
|
||||||
"@types/qrcode": "^1.5.6",
|
|
||||||
"@types/supertest": "^7.2.0",
|
|
||||||
"@types/swagger-jsdoc": "^6.0.4",
|
|
||||||
"@types/swagger-ui-express": "^4.1.8",
|
|
||||||
"@types/web-push": "^3.6.4",
|
|
||||||
"archiver": "^8.0.0",
|
"archiver": "^8.0.0",
|
||||||
"bcrypt": "^6.0.0",
|
"bcrypt": "^6.0.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
@@ -141,7 +127,6 @@
|
|||||||
"react-resizable-panels": "^2.1.7",
|
"react-resizable-panels": "^2.1.7",
|
||||||
"recharts": "^2.15.2",
|
"recharts": "^2.15.2",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"supertest": "^7.2.2",
|
|
||||||
"swagger-jsdoc": "^6.2.8",
|
"swagger-jsdoc": "^6.2.8",
|
||||||
"swagger-ui-express": "^5.0.1",
|
"swagger-ui-express": "^5.0.1",
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
@@ -149,7 +134,6 @@
|
|||||||
"to-words": "^5.6.1",
|
"to-words": "^5.6.1",
|
||||||
"tw-animate-css": "^1.2.5",
|
"tw-animate-css": "^1.2.5",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2",
|
||||||
"vitest": "^4.1.5",
|
|
||||||
"web-push": "^3.6.7",
|
"web-push": "^3.6.7",
|
||||||
"wouter": "^3.3.5",
|
"wouter": "^3.3.5",
|
||||||
"ws": "^8.18.0",
|
"ws": "^8.18.0",
|
||||||
@@ -164,17 +148,31 @@
|
|||||||
"@replit/vite-plugin-runtime-error-modal": "^0.0.3",
|
"@replit/vite-plugin-runtime-error-modal": "^0.0.3",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.1.3",
|
"@tailwindcss/vite": "^4.1.3",
|
||||||
|
"@types/archiver": "^8.0.0",
|
||||||
|
"@types/bcrypt": "^6.0.0",
|
||||||
"@types/connect-pg-simple": "^7.0.3",
|
"@types/connect-pg-simple": "^7.0.3",
|
||||||
"@types/cookie-parser": "^1.4.10",
|
"@types/cookie-parser": "^1.4.10",
|
||||||
|
"@types/cors": "^2.8.19",
|
||||||
|
"@types/dompurify": "^3.0.5",
|
||||||
"@types/express": "4.17.21",
|
"@types/express": "4.17.21",
|
||||||
"@types/express-session": "^1.18.0",
|
"@types/express-session": "^1.18.0",
|
||||||
|
"@types/js-beautify": "^1.14.3",
|
||||||
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
|
"@types/jspreadsheet-ce": "^4.7.9",
|
||||||
"@types/leaflet": "^1.9.22",
|
"@types/leaflet": "^1.9.22",
|
||||||
"@types/leaflet.markercluster": "^1.5.6",
|
"@types/leaflet.markercluster": "^1.5.6",
|
||||||
|
"@types/multer": "^2.0.0",
|
||||||
"@types/node": "20.16.11",
|
"@types/node": "20.16.11",
|
||||||
"@types/passport": "^1.0.16",
|
"@types/passport": "^1.0.16",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
|
"@types/pg": "^8.20.0",
|
||||||
|
"@types/qrcode": "^1.5.6",
|
||||||
"@types/react": "^18.3.11",
|
"@types/react": "^18.3.11",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
|
"@types/supertest": "^7.2.0",
|
||||||
|
"@types/swagger-jsdoc": "^6.0.4",
|
||||||
|
"@types/swagger-ui-express": "^4.1.8",
|
||||||
|
"@types/web-push": "^3.6.4",
|
||||||
"@types/ws": "^8.5.13",
|
"@types/ws": "^8.5.13",
|
||||||
"@types/yandex-maps": "^2.1.36",
|
"@types/yandex-maps": "^2.1.36",
|
||||||
"@vitejs/plugin-react": "^4.3.2",
|
"@vitejs/plugin-react": "^4.3.2",
|
||||||
@@ -182,10 +180,12 @@
|
|||||||
"drizzle-kit": "^0.31.10",
|
"drizzle-kit": "^0.31.10",
|
||||||
"esbuild": "^0.28.1",
|
"esbuild": "^0.28.1",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.47",
|
||||||
|
"supertest": "^7.2.2",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"tsx": "^4.19.1",
|
"tsx": "^4.19.1",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^5.4.19"
|
"vite": "^5.4.19",
|
||||||
|
"vitest": "^4.1.5"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"bufferutil": "^4.0.8"
|
"bufferutil": "^4.0.8"
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import express, { type Express } from "express";
|
import express, { type Express } from "express";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { createServer as createViteServer, createLogger } from "vite";
|
|
||||||
import { type Server } from "http";
|
import { type Server } from "http";
|
||||||
import viteConfig from "../vite.config";
|
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
const viteLogger = createLogger();
|
|
||||||
|
|
||||||
export function log(message: string, source = "express") {
|
export function log(message: string, source = "express") {
|
||||||
const formattedTime = new Date().toLocaleTimeString("en-US", {
|
const formattedTime = new Date().toLocaleTimeString("en-US", {
|
||||||
hour: "numeric",
|
hour: "numeric",
|
||||||
@@ -20,6 +16,11 @@ export function log(message: string, source = "express") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function setupVite(app: Express, server: Server) {
|
export async function setupVite(app: Express, server: Server) {
|
||||||
|
// vite и vite.config — devDependencies: импортируем динамически, чтобы
|
||||||
|
// production-бандл (npm ci --omit=dev) не резолвил их при старте.
|
||||||
|
const { createServer: createViteServer, createLogger } = await import("vite");
|
||||||
|
const { default: viteConfig } = await import("../vite.config");
|
||||||
|
const viteLogger = createLogger();
|
||||||
const serverOptions = {
|
const serverOptions = {
|
||||||
middlewareMode: true,
|
middlewareMode: true,
|
||||||
hmr: { server },
|
hmr: { server },
|
||||||
|
|||||||
Reference in New Issue
Block a user