Fix __ENV__ truncation; route API_BASE_URL through the same injection
Two gaps blocked http://flights-ui.devwebzavod.ru/ru/flights-map: 1. The inline <script>window.__ENV__=...</script> was written with the Leaflet tile template ('/map/api/tile/{z}/{x}/{y}.jpeg') embedded directly. Rspack's html-plugin pre-processes the children string and ate the '{z}' placeholder, truncating the injected JS literal to '/map/api/tile/{z' — MAP_TILE_URL on the client ended up broken and getEnv() fell back to the default. Escape every '{'/'}' inside the stringified value as '\u007B'/'\u007D'. JS decodes the Unicode escapes back to '{}' at parse time; the html plugin's template engine sees no placeholders to eat. Object-literal braces outside the string stay raw (Unicode escapes aren't valid in operator positions in JS source). 2. API_BASE_URL was still hard-defaulting to 'http://localhost:8080/api', so every dictionary fetch on the deployed cluster died with ERR_CONNECTION_REFUSED. Thread API_BASE_URL through the same PUBLIC_ENV_KEYS/html.tags path as MAP_TILE_URL, add matching Docker ARG/ENV, and forward it in deployment/build-docker.sh + k8s manifest. The devwebzavod default for both is https://flights.test.aeroflot.ru — where the real Aeroflot ingress terminates /map/api/** and /api/**. Prod keeps overriding with same-origin URLs.
This commit is contained in:
@@ -26,6 +26,8 @@ COPY config/ config/
|
||||
# into the image if the cluster can't set env at runtime.
|
||||
ARG MAP_TILE_URL
|
||||
ENV MAP_TILE_URL=${MAP_TILE_URL}
|
||||
ARG API_BASE_URL
|
||||
ENV API_BASE_URL=${API_BASE_URL}
|
||||
|
||||
RUN pnpm build:standalone
|
||||
|
||||
|
||||
@@ -10,17 +10,20 @@ function build {
|
||||
export CopyRetryCount=100
|
||||
docker rmi -f $(docker images aeroflot.$K8NAMESPACE/$1 -a -q|uniq) >/dev/null 2>/dev/null
|
||||
ls -l "$2/Dockerfile"
|
||||
# MAP_TILE_URL must be a build-arg (not just a runtime env) because
|
||||
# Modern.js bakes html.tags into the HTML template at `pnpm build:standalone`
|
||||
# time. Setting it only on the pod won't change the served HTML.
|
||||
# Defaults here keep the prod-cluster behavior (same-origin) intact;
|
||||
# devwebzavod builds override with the flights.test.aeroflot.ru URL.
|
||||
: "${MAP_TILE_URL:=/map/api/tile/{z}/{x}/{y}.jpeg}"
|
||||
export MAP_TILE_URL
|
||||
# MAP_TILE_URL / API_BASE_URL must flow as build-args (not just runtime
|
||||
# env) because Modern.js bakes html.tags into the HTML template at
|
||||
# `pnpm build:standalone` time. Values set only on the pod don't change
|
||||
# the served HTML. The defaults match the devwebzavod cluster (no
|
||||
# /map/api/** or /api/** ingress rule — hit the upstream that the real
|
||||
# Aeroflot ingress terminates). Prod overrides with same-origin.
|
||||
: "${MAP_TILE_URL:=https://flights.test.aeroflot.ru/map/api/tile/{z}/{x}/{y}.jpeg}"
|
||||
: "${API_BASE_URL:=https://flights.test.aeroflot.ru/api}"
|
||||
export MAP_TILE_URL API_BASE_URL
|
||||
docker build -t aeroflot.$K8NAMESPACE/$1:v$VERSION.$BUILD_NUMBER \
|
||||
--build-arg ENVIRONMENT=${ENVIRONMENT} \
|
||||
--build-arg=NPM_PROXY \
|
||||
--build-arg MAP_TILE_URL=${MAP_TILE_URL} \
|
||||
--build-arg API_BASE_URL=${API_BASE_URL} \
|
||||
-f "$2/Dockerfile" $2
|
||||
}
|
||||
|
||||
|
||||
@@ -30,11 +30,14 @@ spec:
|
||||
value: production
|
||||
- name: ENVIRONMENT
|
||||
value: $ENVIRONMENT
|
||||
# flights-ui.devwebzavod.ru has no /map/api/** ingress rule, so
|
||||
# point Leaflet at the upstream tile service that the real
|
||||
# Aeroflot ingress serves (flights.test.aeroflot.ru terminates
|
||||
# /map/api/** correctly). Override per-cluster if a different
|
||||
# tile source is required.
|
||||
# flights-ui.devwebzavod.ru has no /map/api/** or /api/** ingress
|
||||
# rule, so point Leaflet and the API client at the upstream
|
||||
# services that the real Aeroflot ingress terminates.
|
||||
# Both MAP_TILE_URL and API_BASE_URL are also wired as docker
|
||||
# build-args because Modern.js bakes html.tags into the HTML at
|
||||
# build time; the k8s env still flows to the Node SSR process.
|
||||
- name: MAP_TILE_URL
|
||||
value: https://flights.test.aeroflot.ru/map/api/tile/{z}/{x}/{y}.jpeg
|
||||
- name: API_BASE_URL
|
||||
value: https://flights.test.aeroflot.ru/api
|
||||
$IMAGE_PULL_SECRETS
|
||||
|
||||
+17
-3
@@ -9,15 +9,29 @@ const isRemote = buildTarget === "remote";
|
||||
// any value we want per-deployment (e.g. MAP_TILE_URL pointing at a tile
|
||||
// service that the local ingress doesn't proxy) has to be injected into
|
||||
// the HTML as a window global. getEnv() picks up window.__ENV__ on the
|
||||
// client. Evaluated once at Modern.js server start → pod env → HTML.
|
||||
const PUBLIC_ENV_KEYS = ["MAP_TILE_URL"] as const;
|
||||
// client. Evaluated once at Modern.js build time → pod env → HTML.
|
||||
//
|
||||
// IMPORTANT: Rspack's HTML plugin passes `children` through a template
|
||||
// engine that eats `{token}` pairs (it was swallowing `{z}`, `{x}`, `{y}`
|
||||
// from the Leaflet tile URL, leaving "/map/api/tile/{z"). Escape every
|
||||
// brace INSIDE string values as `\u007B` / `\u007D`; JS decodes those
|
||||
// back to `{` / `}` at parse time but the HTML preprocessor sees no
|
||||
// placeholders to substitute. Object-literal braces outside strings stay
|
||||
// raw because Unicode escapes aren't valid in operator positions in JS
|
||||
// source.
|
||||
const PUBLIC_ENV_KEYS = ["MAP_TILE_URL", "API_BASE_URL"] as const;
|
||||
const PUBLIC_ENV: Record<string, string> = {};
|
||||
for (const k of PUBLIC_ENV_KEYS) {
|
||||
const v = process.env[k];
|
||||
if (typeof v === "string" && v.length > 0) PUBLIC_ENV[k] = v;
|
||||
}
|
||||
const escapeInString = (s: string): string =>
|
||||
s.replace(/\{/g, "\\u007B").replace(/\}/g, "\\u007D");
|
||||
const pairs = Object.entries(PUBLIC_ENV)
|
||||
.map(([k, v]) => `${JSON.stringify(k)}:${escapeInString(JSON.stringify(v))}`)
|
||||
.join(",");
|
||||
const PUBLIC_ENV_SCRIPT =
|
||||
`window.__ENV__ = Object.assign(window.__ENV__ || {}, ${JSON.stringify(PUBLIC_ENV)});`;
|
||||
`window.__ENV__=Object.assign(window.__ENV__||{},{${pairs}});`;
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [appTools({ bundler: "rspack" }), moduleFederationPlugin()],
|
||||
|
||||
Reference in New Issue
Block a user