Skip to content

Commit 7aac56a

Browse files
authored
Vite embedded build of Element Call (#3077)
* Embedded package build of Element Call Part of #2994 This creates a new "embedded" build (vs "full" build) at the vite level. It will be used by a later PR that actually provides platform specific packages. Embedded build: - Uses relative URLs - Uses relative config.json path and other resource loading - Has a config.json built in - Doesn't include the public folder (e.g. favicon) Out of scope: - this doesn't attempt to exclude SPA functionality, so technically the build could be used in SPA - the above means that the crypto-wasm binary is included in the build * CI artifact name based on type of build * Update src/config/Config.ts
1 parent 520c0f4 commit 7aac56a

File tree

12 files changed

+390
-98
lines changed

12 files changed

+390
-98
lines changed

.github/workflows/build-and-publish-docker.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
with:
3131
github-token: ${{ secrets.GITHUB_TOKEN }}
3232
run-id: ${{ inputs.artifact_run_id }}
33-
name: build-output
33+
name: build-output-full
3434
path: dist
3535

3636
- name: Log in to container registry

.github/workflows/build-element-call.yaml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ on:
55
vite_app_version:
66
required: true
77
type: string
8+
package:
9+
type: string # This would ideally be a `choice` type, but that isn't supported yet
10+
description: The package type to be built. Must be one of 'full' or 'embedded'
11+
required: true
812
secrets:
913
SENTRY_ORG:
1014
required: true
@@ -31,8 +35,20 @@ jobs:
3135
node-version-file: ".node-version"
3236
- name: Install dependencies
3337
run: "yarn install --frozen-lockfile"
34-
- name: Build
35-
run: "yarn run build"
38+
- name: Build full version
39+
if: ${{ inputs.package == 'full' }}
40+
run: "yarn run build:full"
41+
env:
42+
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
43+
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
44+
SENTRY_URL: ${{ secrets.SENTRY_URL }}
45+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
46+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
47+
VITE_APP_VERSION: ${{ inputs.vite_app_version }}
48+
NODE_OPTIONS: "--max-old-space-size=4096"
49+
- name: Build embedded
50+
if: ${{ inputs.package == 'embedded' }}
51+
run: "yarn run build:embedded"
3652
env:
3753
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
3854
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
@@ -44,7 +60,7 @@ jobs:
4460
- name: Upload Artifact
4561
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
4662
with:
47-
name: build-output
63+
name: build-output-${{ inputs.package }}
4864
path: dist
4965
# We'll only use this in a triggered job, then we're done with it
5066
retention-days: 1

.github/workflows/build.yaml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ on:
1616
- ".github/CODEOWNERS"
1717
- "docs/**"
1818
jobs:
19-
build_element_call:
19+
build_full_element_call:
20+
# Use the full package vite build
2021
uses: ./.github/workflows/build-element-call.yaml
2122
with:
23+
package: full
2224
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
2325
secrets:
2426
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
@@ -29,7 +31,7 @@ jobs:
2931
deploy_develop:
3032
# Deploy livekit branch to call.element.dev after build completes
3133
if: github.ref == 'refs/heads/livekit'
32-
needs: build_element_call
34+
needs: build_full_element_call
3335
runs-on: ubuntu-latest
3436
steps:
3537
- name: Deploy to call.element.dev
@@ -50,7 +52,7 @@ jobs:
5052
docker_for_develop:
5153
# Build docker and publish docker for livekit branch after build completes
5254
if: github.ref == 'refs/heads/livekit'
53-
needs: build_element_call
55+
needs: build_full_element_call
5456
permissions:
5557
contents: write
5658
packages: write
@@ -61,3 +63,15 @@ jobs:
6163
type=sha,format=short,event=branch
6264
type=raw,value=latest-ci
6365
type=raw,value=latest-ci_{{date 'X' }}
66+
build_embedded_element_call:
67+
# Use the embedded package vite build
68+
uses: ./.github/workflows/build-element-call.yaml
69+
with:
70+
package: embedded
71+
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
72+
secrets:
73+
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
74+
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
75+
SENTRY_URL: ${{ secrets.SENTRY_URL }}
76+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
77+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/deploy-to-netlify.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
with:
5151
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
5252
run-id: ${{ inputs.artifact_run_id }}
53-
name: build-output
53+
name: build-output-full
5454
path: webapp
5555

5656
- name: Add redirects file

.github/workflows/publish.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
if: ${{ github.event_name == 'release' }}
1414
uses: ./.github/workflows/build-element-call.yaml
1515
with:
16+
package: full
1617
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
1718
secrets:
1819
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
@@ -38,7 +39,7 @@ jobs:
3839
with:
3940
github-token: ${{ secrets.GITHUB_TOKEN }}
4041
run-id: ${{ github.event.workflow_run.id || github.run_id }}
41-
name: build-output
42+
name: build-output-full
4243
path: dist
4344
- name: Create Tarball
4445
env:

public/index.html renamed to index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5+
6+
<% if (packageType === "full") { %>
57
<link rel="icon" type="image/svg+xml" href="favicon.png" />
68
<link rel="preload" href="/config.json" as="fetch" />
9+
<% } %>
10+
711
<meta
812
name="viewport"
913
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
@@ -13,6 +17,7 @@
1317
window.global = window;
1418
</script>
1519

20+
<% if (packageType === "full") { %>
1621
<!-- Open graph meta tags -->
1722

1823
<meta property="og:title" content="<%- brand %>" />
@@ -30,6 +35,7 @@
3035
content="You're invited to join a call on <%- brand %>"
3136
/>
3237
<meta name="twitter:image" content="favicon.png" />
38+
<% } %>
3339
</head>
3440

3541
<!-- The default class is: .no-theme {display: none}. It will be overwritten once the app is loaded. -->

knip.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { KnipConfig } from "knip";
22

33
export default {
4+
vite: {
5+
config: ["vite.config.js", "vite-embedded.config.js"],
6+
},
47
entry: ["src/main.tsx", "i18next-parser.config.ts"],
58
ignoreBinaries: [
69
// This is deprecated, so Knip doesn't actually recognize it as a globally

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
"version": "0.0.0",
44
"type": "module",
55
"scripts": {
6-
"dev": "vite",
7-
"build": "NODE_OPTIONS=--max-old-space-size=16384 vite build",
6+
"dev": "yarn dev:full",
7+
"dev:full": "vite",
8+
"dev:embedded": "vite --config vite-embedded.config.js",
9+
"build": "yarn build:full",
10+
"build:full": "NODE_OPTIONS=--max-old-space-size=16384 vite build",
11+
"build:embedded": "yarn build:full --config vite-embedded.config.js",
812
"serve": "vite preview",
913
"prettier:check": "prettier -c .",
1014
"prettier:format": "prettier -w .",
@@ -114,7 +118,8 @@
114118
"unique-names-generator": "^4.6.0",
115119
"vaul": "^1.0.0",
116120
"vite": "^6.0.0",
117-
"vite-plugin-html-template": "^1.1.0",
121+
"vite-plugin-generate-file": "^0.2.0",
122+
"vite-plugin-html": "^3.2.2",
118123
"vite-plugin-svgr": "^4.0.0",
119124
"vitest": "^3.0.0",
120125
"vitest-axe": "^1.0.0-pre.3"

src/config/Config.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,20 @@ export class Config {
2929
const internalInstance = new Config();
3030
Config.internalInstance = internalInstance;
3131

32-
Config.internalInstance.initPromise = downloadConfig("/config.json").then(
32+
let fetchTarget: string;
33+
34+
if (
35+
window.location.pathname.endsWith("/room/") ||
36+
window.location.pathname.endsWith("/room")
37+
) {
38+
// it looks like we are running in standalone mode so use the config at the root
39+
fetchTarget = new URL("/config.json", window.location.href).href;
40+
} else {
41+
// otherwise we are probably running as a widget so use the config in the same directory
42+
fetchTarget = "config.json";
43+
}
44+
45+
Config.internalInstance.initPromise = downloadConfig(fetchTarget).then(
3346
(config) => {
3447
internalInstance.config = merge({}, DEFAULT_CONFIG, config);
3548
},
@@ -71,11 +84,8 @@ export class Config {
7184
private initPromise?: Promise<void>;
7285
}
7386

74-
async function downloadConfig(
75-
configJsonFilename: string,
76-
): Promise<ConfigOptions> {
77-
const url = new URL(configJsonFilename, window.location.href);
78-
const response = await fetch(url);
87+
async function downloadConfig(fetchTarget: string): Promise<ConfigOptions> {
88+
const response = await fetch(fetchTarget);
7989

8090
if (isFailure(response)) {
8191
// Lack of a config isn't an error, we should just use the defaults.

vite-embedded.config.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { defineConfig, mergeConfig } from "vite";
2+
import fullConfig from "./vite.config";
3+
import generateFile from "vite-plugin-generate-file";
4+
5+
const base = "./";
6+
7+
// Config for embedded deployments (possibly hosted under a non-root path)
8+
export default defineConfig((env) =>
9+
mergeConfig(
10+
fullConfig({ ...env, packageType: "embedded" }),
11+
defineConfig({
12+
base, // Use relative URLs to allow the app to be hosted under any path
13+
publicDir: false, // Don't serve the public directory which only contains the favicon
14+
plugins: [
15+
generateFile([
16+
{
17+
type: "json",
18+
output: "./config.json",
19+
data: {
20+
matrix_rtc_session: {
21+
key_rotation_on_leave_delay: 15000,
22+
membership_keep_alive_period: 5000,
23+
membership_server_side_expiry_timeout: 15000,
24+
},
25+
},
26+
},
27+
]),
28+
],
29+
}),
30+
),
31+
);

0 commit comments

Comments
 (0)