| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| import path from 'path'; | |
| import { fileURLToPath } from 'url'; | |
| import react from '@vitejs/plugin-react'; | |
| import yaml from '@modyfi/vite-plugin-yaml'; | |
| import { CORE_SCHEMA } from 'js-yaml'; | |
| import { defineConfig, loadEnv } from 'vite'; | |
| // This file is loaded as a real ES module, where __dirname does not exist. | |
| const rootDir = path.dirname(fileURLToPath(import.meta.url)); | |
| const i18nDir = path.resolve(rootDir, '../i18n'); | |
| export default defineConfig(({ mode }) => { | |
| const env = loadEnv(mode, rootDir, 'REACT_APP_'); | |
| // configs/config.yaml ui.public_url, as written by scripts/env.js, may or | |
| // may not already carry a trailing slash (the root value is exactly "/"). | |
| // Vite requires base to end with one, so add it only when missing rather | |
| // than concatenating blindly and risking "//". | |
| // | |
| // Vite keeps an absolute external base (e.g. a CDN URL) exactly as given | |
| // only for `vite build`. `vite dev` and `vite preview` reduce the same | |
| // base to its bare pathname, dropping the scheme and host. That split is | |
| // intentional here, not a bug to unify: those two commands only serve | |
| // this app locally, and the Go server only ever embeds `vite build`'s | |
| // output, so the reduction never reaches anything a real deployment | |
| // serves. | |
| const publicUrl = env.REACT_APP_PUBLIC_URL || '/'; | |
| const base = publicUrl.endsWith('/') ? publicUrl : `${publicUrl}/`; | |
| return { | |
| // The previous yaml-loader (yaml@2.6.1 core schema) kept bare dates as | |
| // strings and left merge keys unresolved. @modyfi/vite-plugin-yaml | |
| // defaults to js-yaml's DEFAULT_SCHEMA, which resolves bare YYYY-MM-DD | |
| // scalars to JS Date objects and enables merge keys. Pin CORE_SCHEMA so | |
| // yaml imports keep parsing the way they did before the migration. | |
| plugins: [react(), yaml({ schema: CORE_SCHEMA })], | |
| css: { | |
| preprocessorOptions: { | |
| // bootstrap 5.3.3's own scss internals emit dozens of deprecation | |
| // warnings (color functions, mixed-decls) on every build. They are | |
| // unactionable here and bury warnings that point at our own code. | |
| scss: { quietDeps: true }, | |
| }, | |
| }, | |
| // scripts/env.js generates .env.production from the server's own | |
| // configs/config.yaml using REACT_APP_ names. Reading that prefix keeps the | |
| // generator as the single source of truth for both sides. | |
| envPrefix: 'REACT_APP_', | |
| base, | |
| resolve: { | |
| alias: { | |
| '@': path.resolve(rootDir, 'src'), | |
| '@i18n': i18nDir, | |
| }, | |
| }, | |
| build: { | |
| // ui/static.go embeds this directory, and internal/router/ui.go serves | |
| // /static from it. Neither path is configurable from here. | |
| outDir: 'build', | |
| assetsDir: 'static', | |
| // Matches the previous build so before/after size comparisons measure the | |
| // bundler rather than a change of sourcemap setting. | |
| sourcemap: true, | |
| rollupOptions: { | |
| output: { | |
| // Keep emitted files grouped under static/js, static/css and | |
| // static/media. The analyze script globs that layout, and a flat | |
| // static/ directory silently matches nothing. | |
| entryFileNames: 'static/js/[name].[hash].js', | |
| chunkFileNames: 'static/js/[name].[hash].chunk.js', | |
| assetFileNames: (assetInfo) => { | |
| const name = assetInfo.names?.[0] ?? ''; | |
| if (name.endsWith('.css')) { | |
| return 'static/css/[name].[hash][extname]'; | |
| } | |
| return 'static/media/[name].[hash][extname]'; | |
| }, | |
| }, | |
| }, | |
| }, | |
| server: { | |
| port: 3000, | |
| proxy: { | |
| '/answer': { | |
| target: env.REACT_APP_API_URL, | |
| changeOrigin: true, | |
| secure: false, | |
| }, | |
| '/installation': { | |
| target: env.REACT_APP_API_URL, | |
| changeOrigin: true, | |
| secure: false, | |
| }, | |
| '/custom.css': { | |
| target: env.REACT_APP_API_URL, | |
| }, | |
| }, | |
| fs: { | |
| // Languages live outside this root and are loaded through @i18n. | |
| allow: [rootDir, i18nDir], | |
| }, | |
| }, | |
| }; | |
| }); |