Pre-compile frontend and add environment config script
This commit is contained in:
parent
543ccb4fb6
commit
5dabd0b2f8
@ -1,23 +1,35 @@
|
|||||||
FROM node:14.18.2-buster-slim@sha256:20bedf0c09de887379e59a41c04284974f5fb529cf0e13aab613473ce298da3d as builder
|
FROM node:14.18.2-buster-slim@sha256:20bedf0c09de887379e59a41c04284974f5fb529cf0e13aab613473ce298da3d as builder
|
||||||
WORKDIR /usr/src
|
|
||||||
|
WORKDIR /usr/src/messages
|
||||||
COPY messages .
|
COPY messages .
|
||||||
RUN yarn install && yarn ts-proto
|
RUN yarn install && yarn ts-proto
|
||||||
|
|
||||||
# we are rebuilding on each deploy to cope with the PUSHER_URL environment URL
|
WORKDIR /usr/src/front
|
||||||
FROM thecodingmachine/nodejs:14-apache
|
COPY front .
|
||||||
|
|
||||||
COPY --chown=docker:docker front .
|
# move messages to front
|
||||||
COPY --from=builder --chown=docker:docker /usr/src/ts-proto-generated/protos /var/www/html/src/Messages/ts-proto-generated
|
RUN cp -r ../messages/ts-proto-generated/protos/* src/Messages/ts-proto-generated
|
||||||
RUN sed -i 's/import { Observable } from "rxjs";/import type { Observable } from "rxjs";/g' /var/www/html/src/Messages/ts-proto-generated/messages.ts
|
RUN sed -i 's/import { Observable } from "rxjs";/import type { Observable } from "rxjs";/g' src/Messages/ts-proto-generated/messages.ts
|
||||||
COPY --from=builder --chown=docker:docker /usr/src/JsonMessages /var/www/html/src/Messages/JsonMessages
|
RUN cp -r ../messages/JsonMessages src/Messages/JsonMessages
|
||||||
|
|
||||||
|
RUN yarn install && yarn build
|
||||||
|
|
||||||
# Removing the iframe.html file from the final image as this adds a XSS attack.
|
# Removing the iframe.html file from the final image as this adds a XSS attack.
|
||||||
# iframe.html is only in dev mode to circumvent a limitation
|
# iframe.html is only in dev mode to circumvent a limitation
|
||||||
RUN rm dist/iframe.html
|
RUN rm dist/iframe.html
|
||||||
|
|
||||||
RUN yarn install
|
FROM thecodingmachine/nodejs:14-apache
|
||||||
|
|
||||||
|
COPY --from=builder --chown=docker:docker /usr/src/front/dist dist
|
||||||
|
COPY front/templater.sh .
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
|
||||||
|
&& apt-get install -y \
|
||||||
|
gettext-base \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
USER docker
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
ENV STARTUP_COMMAND_0="./templater.sh"
|
ENV STARTUP_COMMAND_0="./templater.sh"
|
||||||
ENV STARTUP_COMMAND_1="yarn run build"
|
ENV STARTUP_COMMAND_1="envsubst < dist/env-config.template.js > dist/env-config.js"
|
||||||
ENV APACHE_DOCUMENT_ROOT=dist/
|
ENV APACHE_DOCUMENT_ROOT=dist/
|
||||||
|
1
front/dist/.gitignore
vendored
1
front/dist/.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
index.html
|
index.html
|
||||||
index.tmpl.html.tmp
|
|
||||||
/js/
|
/js/
|
||||||
style.*.css
|
style.*.css
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<meta name="msapplication-TileImage" content="static/images/favicons/ms-icon-144x144.png">
|
<meta name="msapplication-TileImage" content="static/images/favicons/ms-icon-144x144.png">
|
||||||
<meta name="theme-color" content="#000000">
|
<meta name="theme-color" content="#000000">
|
||||||
|
|
||||||
|
<script src="/env-config.js"></script>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<link href="https://unpkg.com/nes.css@2.3.0/css/nes.min.css" rel="stylesheet" />
|
<link href="https://unpkg.com/nes.css@2.3.0/css/nes.min.css" rel="stylesheet" />
|
||||||
|
|
@ -1,30 +1,46 @@
|
|||||||
const DEBUG_MODE: boolean = process.env.DEBUG_MODE == "true";
|
declare global {
|
||||||
const START_ROOM_URL: string =
|
interface Window {
|
||||||
process.env.START_ROOM_URL || "/_/global/maps.workadventure.localhost/Floor1/floor1.json";
|
env?: Record<string, string>;
|
||||||
const PUSHER_URL = process.env.PUSHER_URL || "//pusher.workadventure.localhost";
|
}
|
||||||
export const ADMIN_URL = process.env.ADMIN_URL || "//workadventu.re";
|
}
|
||||||
const UPLOADER_URL = process.env.UPLOADER_URL || "//uploader.workadventure.localhost";
|
|
||||||
const ICON_URL = process.env.ICON_URL || "//icon.workadventure.localhost";
|
const getEnv = (key: string): string | undefined => {
|
||||||
const STUN_SERVER: string = process.env.STUN_SERVER || "stun:stun.l.google.com:19302";
|
if (!window.env) {
|
||||||
const TURN_SERVER: string = process.env.TURN_SERVER || "";
|
return;
|
||||||
const SKIP_RENDER_OPTIMIZATIONS: boolean = process.env.SKIP_RENDER_OPTIMIZATIONS == "true";
|
}
|
||||||
const DISABLE_NOTIFICATIONS: boolean = process.env.DISABLE_NOTIFICATIONS == "true";
|
const value = window.env[key];
|
||||||
const TURN_USER: string = process.env.TURN_USER || "";
|
if (value === "") {
|
||||||
const TURN_PASSWORD: string = process.env.TURN_PASSWORD || "";
|
return;
|
||||||
const JITSI_URL: string | undefined = process.env.JITSI_URL === "" ? undefined : process.env.JITSI_URL;
|
}
|
||||||
const JITSI_PRIVATE_MODE: boolean = process.env.JITSI_PRIVATE_MODE == "true";
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEBUG_MODE: boolean = getEnv("DEBUG_MODE") == "true";
|
||||||
|
const START_ROOM_URL: string = getEnv("START_ROOM_URL") || "/_/global/maps.workadventure.localhost/Floor1/floor1.json";
|
||||||
|
const PUSHER_URL = getEnv("PUSHER_URL") || "//pusher.workadventure.localhost";
|
||||||
|
export const ADMIN_URL = getEnv("ADMIN_URL") || "//workadventu.re";
|
||||||
|
const UPLOADER_URL = getEnv("UPLOADER_URL") || "//uploader.workadventure.localhost";
|
||||||
|
const ICON_URL = getEnv("ICON_URL") || "//icon.workadventure.localhost";
|
||||||
|
const STUN_SERVER: string = getEnv("STUN_SERVER") || "stun:stun.l.google.com:19302";
|
||||||
|
const TURN_SERVER: string = getEnv("TURN_SERVER") || "";
|
||||||
|
const SKIP_RENDER_OPTIMIZATIONS: boolean = getEnv("SKIP_RENDER_OPTIMIZATIONS") == "true";
|
||||||
|
const DISABLE_NOTIFICATIONS: boolean = getEnv("DISABLE_NOTIFICATIONS") == "true";
|
||||||
|
const TURN_USER: string = getEnv("TURN_USER") || "";
|
||||||
|
const TURN_PASSWORD: string = getEnv("TURN_PASSWORD") || "";
|
||||||
|
const JITSI_URL: string | undefined = getEnv("JITSI_URL") === "" ? undefined : getEnv("JITSI_URL");
|
||||||
|
const JITSI_PRIVATE_MODE: boolean = getEnv("JITSI_PRIVATE_MODE") == "true";
|
||||||
const POSITION_DELAY = 200; // Wait 200ms between sending position events
|
const POSITION_DELAY = 200; // Wait 200ms between sending position events
|
||||||
const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new movement is sent by the player
|
const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new movement is sent by the player
|
||||||
export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || "") || 8;
|
export const MAX_USERNAME_LENGTH = parseInt(getEnv("MAX_USERNAME_LENGTH") || "") || 8;
|
||||||
export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || "4");
|
export const MAX_PER_GROUP = parseInt(getEnv("MAX_PER_GROUP") || "4");
|
||||||
export const DISPLAY_TERMS_OF_USE = process.env.DISPLAY_TERMS_OF_USE == "true";
|
export const DISPLAY_TERMS_OF_USE = getEnv("DISPLAY_TERMS_OF_USE") == "true";
|
||||||
export const NODE_ENV = process.env.NODE_ENV || "development";
|
export const NODE_ENV = getEnv("NODE_ENV") || "development";
|
||||||
export const CONTACT_URL = process.env.CONTACT_URL || undefined;
|
export const CONTACT_URL = getEnv("CONTACT_URL") || undefined;
|
||||||
export const PROFILE_URL = process.env.PROFILE_URL || undefined;
|
export const PROFILE_URL = getEnv("PROFILE_URL") || undefined;
|
||||||
export const POSTHOG_API_KEY: string = (process.env.POSTHOG_API_KEY as string) || "";
|
export const POSTHOG_API_KEY: string = (getEnv("POSTHOG_API_KEY") as string) || "";
|
||||||
export const POSTHOG_URL = process.env.POSTHOG_URL || undefined;
|
export const POSTHOG_URL = getEnv("POSTHOG_URL") || undefined;
|
||||||
export const DISABLE_ANONYMOUS: boolean = process.env.DISABLE_ANONYMOUS === "true";
|
export const DISABLE_ANONYMOUS: boolean = getEnv("DISABLE_ANONYMOUS") === "true";
|
||||||
export const OPID_LOGIN_SCREEN_PROVIDER = process.env.OPID_LOGIN_SCREEN_PROVIDER;
|
export const OPID_LOGIN_SCREEN_PROVIDER = getEnv("OPID_LOGIN_SCREEN_PROVIDER");
|
||||||
|
|
||||||
export const isMobile = (): boolean => window.innerWidth <= 800 || window.innerHeight <= 600;
|
export const isMobile = (): boolean => window.innerWidth <= 800 || window.innerHeight <= 600;
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -x
|
set -x
|
||||||
set -o nounset errexit
|
set -o nounset errexit
|
||||||
template_file_index=dist/index.tmpl.html
|
index_file=dist/index.html
|
||||||
generated_file_index=dist/index.tmpl.html.tmp
|
|
||||||
tmp_trackcodefile=/tmp/trackcode
|
tmp_trackcodefile=/tmp/trackcode
|
||||||
|
|
||||||
# To inject tracking code, you have two choices:
|
# To inject tracking code, you have two choices:
|
||||||
@ -21,6 +20,6 @@ if [[ "${GA_TRACKING_ID:-}" != "" || "${INSERT_ANALYTICS:-NO}" != "NO" ]]; then
|
|||||||
sed "s#<!-- TRACKING NUMBER -->#${GA_TRACKING_ID:-}#g" "${ANALYTICS_CODE_PATH}" > "$tmp_trackcodefile"
|
sed "s#<!-- TRACKING NUMBER -->#${GA_TRACKING_ID:-}#g" "${ANALYTICS_CODE_PATH}" > "$tmp_trackcodefile"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Templating ${generated_file_index} from ${template_file_index}"
|
echo "Templating ${index_file}"
|
||||||
sed "/<!-- TRACK CODE -->/r ${tmp_trackcodefile}" "${template_file_index}" > "${generated_file_index}"
|
sed --in-place "/<!-- TRACK CODE -->/r ${tmp_trackcodefile}" "${index_file}"
|
||||||
rm "${tmp_trackcodefile}"
|
rm "${tmp_trackcodefile}"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { Configuration } from "webpack";
|
import type { Configuration } from "webpack";
|
||||||
import type WebpackDevServer from "webpack-dev-server";
|
import type WebpackDevServer from "webpack-dev-server";
|
||||||
|
import fs from 'fs/promises';
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import webpack from "webpack";
|
import webpack from "webpack";
|
||||||
import HtmlWebpackPlugin from "html-webpack-plugin";
|
import HtmlWebpackPlugin from "html-webpack-plugin";
|
||||||
@ -33,6 +34,35 @@ module.exports = {
|
|||||||
disableDotRule: true,
|
disableDotRule: true,
|
||||||
},
|
},
|
||||||
liveReload: process.env.LIVE_RELOAD != "0" && process.env.LIVE_RELOAD != "false",
|
liveReload: process.env.LIVE_RELOAD != "0" && process.env.LIVE_RELOAD != "false",
|
||||||
|
before: (app) => {
|
||||||
|
let appConfigContent = '';
|
||||||
|
const TEMPLATE_PATH = path.join(__dirname, 'dist', 'env-config.template.js');
|
||||||
|
|
||||||
|
function renderTemplateWithEnvVars(content: string): string {
|
||||||
|
let result = content;
|
||||||
|
const regex = /\$\{([a-zA-Z_]+[a-zA-Z0-9_]*?)\}/g;
|
||||||
|
|
||||||
|
let matched: RegExpExecArray | null;
|
||||||
|
while ((matched = regex.exec(content))) {
|
||||||
|
result = result.replace(`\${${matched[1]}}`, process.env[matched[1]] || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void (async () => {
|
||||||
|
const content = (await fs.readFile(TEMPLATE_PATH)).toString();
|
||||||
|
appConfigContent = renderTemplateWithEnvVars(content);
|
||||||
|
})();
|
||||||
|
|
||||||
|
app.get('/env-config.js', (_, response) => {
|
||||||
|
response.setHeader('Content-Type', 'application/javascript; charset=utf-8');
|
||||||
|
response.setHeader('Cache-Control', 'no-cache');
|
||||||
|
response.setHeader('Content-Length', Buffer.byteLength(appConfigContent, 'utf8'));
|
||||||
|
|
||||||
|
response.send(appConfigContent);
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
@ -168,7 +198,7 @@ module.exports = {
|
|||||||
}),
|
}),
|
||||||
new MiniCssExtractPlugin({ filename: "[name].[contenthash].css" }),
|
new MiniCssExtractPlugin({ filename: "[name].[contenthash].css" }),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: "./dist/index.tmpl.html.tmp",
|
template: "./dist/index.ejs",
|
||||||
minify: {
|
minify: {
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
keepClosingSlash: true,
|
keepClosingSlash: true,
|
||||||
@ -184,32 +214,5 @@ module.exports = {
|
|||||||
Phaser: "phaser",
|
Phaser: "phaser",
|
||||||
}),
|
}),
|
||||||
new NodePolyfillPlugin(),
|
new NodePolyfillPlugin(),
|
||||||
new webpack.EnvironmentPlugin({
|
|
||||||
API_URL: null,
|
|
||||||
SKIP_RENDER_OPTIMIZATIONS: false,
|
|
||||||
DISABLE_NOTIFICATIONS: false,
|
|
||||||
PUSHER_URL: undefined,
|
|
||||||
UPLOADER_URL: null,
|
|
||||||
ADMIN_URL: null,
|
|
||||||
CONTACT_URL: null,
|
|
||||||
PROFILE_URL: null,
|
|
||||||
ICON_URL: null,
|
|
||||||
DEBUG_MODE: null,
|
|
||||||
STUN_SERVER: null,
|
|
||||||
TURN_SERVER: null,
|
|
||||||
TURN_USER: null,
|
|
||||||
TURN_PASSWORD: null,
|
|
||||||
JITSI_URL: null,
|
|
||||||
JITSI_PRIVATE_MODE: null,
|
|
||||||
START_ROOM_URL: null,
|
|
||||||
MAX_USERNAME_LENGTH: 8,
|
|
||||||
MAX_PER_GROUP: 4,
|
|
||||||
DISPLAY_TERMS_OF_USE: false,
|
|
||||||
POSTHOG_API_KEY: null,
|
|
||||||
POSTHOG_URL: null,
|
|
||||||
NODE_ENV: mode,
|
|
||||||
DISABLE_ANONYMOUS: false,
|
|
||||||
OPID_LOGIN_SCREEN_PROVIDER: null,
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
} as Configuration & WebpackDevServer.Configuration;
|
} as Configuration & WebpackDevServer.Configuration;
|
||||||
|
Loading…
Reference in New Issue
Block a user