Воркер теперь собирается через injectManifest: generateSW умеет только кэш, а уведомление показывает именно воркер — страница при этом может быть закрыта. Нажатие на уведомление переиспользует уже открытое окно, а не плодит второе. Включение — строкой на главном экране, по нажатию. Не всплывающим окном на входе: разрешение спрашивается один раз за установку, отказ браузер запоминает навсегда, и потраченная впустую попытка закрывает канал. Если сервер уведомления не настроил — разрешение не запрашиваем вовсе. Отдельные тексты вместо молчания: на iPhone без установки на домашний экран уведомления невозможны в принципе, и об этом сказано прямо. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
84 lines
4.3 KiB
TypeScript
84 lines
4.3 KiB
TypeScript
import { execSync } from "child_process";
|
||
import { defineConfig, loadEnv } from "vite";
|
||
import react from "@vitejs/plugin-react";
|
||
import { VitePWA } from "vite-plugin-pwa";
|
||
import path from "path";
|
||
|
||
/**
|
||
* Что именно сейчас открыто — видно на вкладке «Отладка».
|
||
*
|
||
* Без этого «правка не приехала» и «приехала, но кэш старый» выглядят
|
||
* одинаково, а проверяются по-разному. Коммит берём из git; вне репозитория
|
||
* (сборка из архива, CI без .git) — честный «unknown», а не падение сборки.
|
||
*/
|
||
function buildCommit(): string {
|
||
try {
|
||
return execSync("git rev-parse --short HEAD", { stdio: ["ignore", "pipe", "ignore"] })
|
||
.toString().trim() || "unknown";
|
||
} catch {
|
||
return "unknown";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Локальная разработка ходит в бэкенд ЧЕРЕЗ ПРОКСИ dev-сервера, а не напрямую.
|
||
*
|
||
* Почему не «разрешить localhost в CORS бэкенда»: через прокси запрос уходит с
|
||
* того же origin, что и страница (http://localhost:5174/api/...), поэтому CORS
|
||
* в разработке не участвует вообще — ни preflight, ни credentials. Боевой
|
||
* список origin'ов на бэкенде остаётся закрытым, и CORS_ALLOW_LOCALHOST ради
|
||
* этого фронта включать не нужно.
|
||
*
|
||
* Дефолтная цель прокси — ЛОКАЛЬНЫЙ бэкенд, а не crm.pptaxi.ru. Контур боевой:
|
||
* «по умолчанию проксировать в прод» означало бы, что первый же тычок в
|
||
* «Пополнить» на машине разработчика создаёт платёж на живом терминале и живой
|
||
* чек 54-ФЗ. Другой адрес задаётся VITE_API_TARGET — тем же именем, что в CRM
|
||
* (crm2/frontend/vite.config.ts), чтобы рецепт был один на оба фронта.
|
||
*/
|
||
export default defineConfig(({ command, mode }) => {
|
||
// База для ky (src/api/client.ts): в dev — свой же origin, дальше прокси.
|
||
// Ставим ТОЛЬКО если разработчик не задал базу сам (.env.local, .env,
|
||
// VITE_API_BASE=... перед командой): loadEnv отдаёт и файлы, и process.env,
|
||
// причём process.env приоритетнее файлов — без этой проверки собственная
|
||
// настройка молча перебивалась бы нашим дефолтом.
|
||
// В сборку (command === "build") не лезем никогда: там база остаётся боевой —
|
||
// из .env, либо из дефолта в client.ts.
|
||
if (command === "serve" && !loadEnv(mode, __dirname, "VITE_").VITE_API_BASE) {
|
||
process.env.VITE_API_BASE = "/api";
|
||
}
|
||
|
||
return {
|
||
define: {
|
||
__BUILD_COMMIT__: JSON.stringify(buildCommit()),
|
||
__BUILD_TIME__: JSON.stringify(new Date().toISOString().slice(0, 16).replace("T", " ")),
|
||
},
|
||
plugins: [
|
||
react(),
|
||
// injectManifest, а не generateSW: воркер свой, потому что уведомления
|
||
// показывает он (см. src/sw.ts), а сгенерированный умеет только кэш.
|
||
VitePWA({
|
||
strategies: "injectManifest",
|
||
srcDir: "src",
|
||
filename: "sw.ts",
|
||
registerType: "autoUpdate",
|
||
manifest: false,
|
||
includeAssets: ["icons/*.png"],
|
||
injectManifest: { globPatterns: ["**/*.{js,css,html,png,svg,webmanifest}"] },
|
||
}),
|
||
],
|
||
resolve: { alias: { "@": path.resolve(__dirname, "src") } },
|
||
server: {
|
||
port: 5174,
|
||
proxy: {
|
||
"/api": {
|
||
// secure: false нужен только для VITE_API_TARGET на https-цель с
|
||
// самоподписанным сертификатом; на дефолтную http-цель не влияет.
|
||
target: process.env.VITE_API_TARGET || "http://127.0.0.1:8000",
|
||
changeOrigin: true,
|
||
secure: false,
|
||
},
|
||
},
|
||
},
|
||
};
|
||
});
|