Skip to content

Commit 3bbcabf

Browse files
committed
chore(build): add Vercel preview builds for framework test apps
1 parent 308aef5 commit 3bbcabf

File tree

4 files changed

+306
-1
lines changed

4 files changed

+306
-1
lines changed

packages/react/test/base/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ setupIonicReact();
4444

4545
const App: React.FC = () => (
4646
<IonApp>
47-
<IonReactRouter>
47+
<IonReactRouter basename={import.meta.env?.BASE_URL?.replace(/\/$/, '')}>
4848
<IonRouterOutlet>
4949
<Route exact path="/" component={Main} />
5050
<Route path="/overlay-hooks" component={OverlayHooks} />
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
11
/// <reference types="react-scripts" />
2+
3+
interface ImportMetaEnv {
4+
readonly BASE_URL?: string;
5+
}
6+
7+
interface ImportMeta {
8+
readonly env?: ImportMetaEnv;
9+
}

scripts/vercel-build.sh

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
#!/bin/bash
2+
#
3+
# Vercel preview build script
4+
#
5+
# Builds core component tests (same as before) plus framework test apps
6+
# (Angular, React, Vue) so they're all accessible from a single preview URL.
7+
#
8+
# Core tests: /src/components/{name}/test/{scenario}
9+
# Angular test app: /angular/
10+
# React test app: /react/
11+
# Vue test app: /vue/
12+
# React Router app: /react-router/ (only Vite-based apps, i.e. RR6+)
13+
#
14+
set -e
15+
16+
REPO_ROOT=$(pwd)
17+
OUTPUT_DIR="${REPO_ROOT}/_vercel_output"
18+
19+
echo "=== Ionic Framework Preview Build ==="
20+
echo "Root: ${REPO_ROOT}"
21+
22+
rm -rf "${OUTPUT_DIR}"
23+
mkdir -p "${OUTPUT_DIR}"
24+
25+
# ---------------------------------------------------------------------------
26+
# Step 1 - Build Core (dependencies already installed by Vercel installCommand)
27+
# ---------------------------------------------------------------------------
28+
echo ""
29+
echo "--- Step 1: Building Core ---"
30+
cd "${REPO_ROOT}/core"
31+
npm run build
32+
33+
# Copy core files to output. The test HTML files use relative paths like
34+
# ../../../../../dist/ionic/ionic.esm.js so the directory structure must
35+
# be preserved exactly.
36+
echo "Copying core output..."
37+
cp -r "${REPO_ROOT}/core/src" "${OUTPUT_DIR}/src"
38+
cp -r "${REPO_ROOT}/core/dist" "${OUTPUT_DIR}/dist"
39+
cp -r "${REPO_ROOT}/core/css" "${OUTPUT_DIR}/css"
40+
mkdir -p "${OUTPUT_DIR}/scripts"
41+
cp -r "${REPO_ROOT}/core/scripts/testing" "${OUTPUT_DIR}/scripts/testing"
42+
43+
# ---------------------------------------------------------------------------
44+
# Step 2 - Build Framework Packages (parallel)
45+
# ---------------------------------------------------------------------------
46+
echo ""
47+
echo "--- Step 2: Building Framework Packages ---"
48+
49+
build_angular_pkgs() {
50+
cd "${REPO_ROOT}/packages/angular" && npm install && npm run build
51+
cd "${REPO_ROOT}/packages/angular-server" && npm install && npm run build
52+
}
53+
54+
build_react_pkgs() {
55+
cd "${REPO_ROOT}/packages/react" && npm install && npm run build
56+
cd "${REPO_ROOT}/packages/react-router" && npm install && npm run build
57+
}
58+
59+
build_vue_pkgs() {
60+
cd "${REPO_ROOT}/packages/vue" && npm install && npm run build
61+
cd "${REPO_ROOT}/packages/vue-router" && npm install && npm run build
62+
}
63+
64+
build_angular_pkgs > /tmp/vercel-angular-pkg.log 2>&1 &
65+
PID_ANG=$!
66+
build_react_pkgs > /tmp/vercel-react-pkg.log 2>&1 &
67+
PID_REACT=$!
68+
build_vue_pkgs > /tmp/vercel-vue-pkg.log 2>&1 &
69+
PID_VUE=$!
70+
71+
FAILED=""
72+
wait $PID_ANG || { echo "Angular packages failed:"; tail -30 /tmp/vercel-angular-pkg.log; FAILED="${FAILED} angular-pkg"; }
73+
wait $PID_REACT || { echo "React packages failed:"; tail -30 /tmp/vercel-react-pkg.log; FAILED="${FAILED} react-pkg"; }
74+
wait $PID_VUE || { echo "Vue packages failed:"; tail -30 /tmp/vercel-vue-pkg.log; FAILED="${FAILED} vue-pkg"; }
75+
76+
if [ -n "${FAILED}" ]; then
77+
echo "ERROR: Framework package builds failed:${FAILED}"
78+
echo "Core tests will still be deployed."
79+
# Generate landing page and exit early -- core tests are still useful
80+
generate_landing_page
81+
exit 0
82+
fi
83+
84+
echo "All framework packages built."
85+
86+
# ---------------------------------------------------------------------------
87+
# Step 3 - Build Framework Test Apps (parallel)
88+
# ---------------------------------------------------------------------------
89+
echo ""
90+
echo "--- Step 3: Building Framework Test Apps ---"
91+
92+
# Find the best available app version for a given package
93+
pick_app() {
94+
local test_dir="$1"
95+
shift
96+
for v in "$@"; do
97+
if [ -d "${test_dir}/apps/${v}" ]; then
98+
echo "${v}"
99+
return 0
100+
fi
101+
done
102+
return 1
103+
}
104+
105+
build_angular_test() {
106+
local APP
107+
APP=$(pick_app "${REPO_ROOT}/packages/angular/test" ng20 ng19 ng18) || {
108+
echo "[angular] No test app found, skipping."
109+
return 0
110+
}
111+
echo "[angular] Building ${APP}..."
112+
113+
cd "${REPO_ROOT}/packages/angular/test"
114+
./build.sh "${APP}"
115+
cd "build/${APP}"
116+
npm install
117+
npm run sync
118+
# --base-href sets <base href="/angular/"> so Angular Router works under the sub-path
119+
npm run build -- --base-href /angular/
120+
121+
mkdir -p "${OUTPUT_DIR}/angular"
122+
cp -r dist/test-app/browser/* "${OUTPUT_DIR}/angular/"
123+
echo "[angular] Done."
124+
}
125+
126+
build_react_test() {
127+
local APP
128+
APP=$(pick_app "${REPO_ROOT}/packages/react/test" react19 react18) || {
129+
echo "[react] No test app found, skipping."
130+
return 0
131+
}
132+
echo "[react] Building ${APP}..."
133+
134+
cd "${REPO_ROOT}/packages/react/test"
135+
./build.sh "${APP}"
136+
cd "build/${APP}"
137+
npm install
138+
npm run sync
139+
# --base sets Vite's base URL; import.meta.env.BASE_URL is read by IonReactRouter basename
140+
npx vite build --base /react/
141+
142+
mkdir -p "${OUTPUT_DIR}/react"
143+
cp -r dist/* "${OUTPUT_DIR}/react/"
144+
echo "[react] Done."
145+
}
146+
147+
build_vue_test() {
148+
echo "[vue] Building vue3..."
149+
150+
cd "${REPO_ROOT}/packages/vue/test"
151+
./build.sh vue3
152+
cd build/vue3
153+
npm install
154+
npm run sync
155+
# Vue Router already reads import.meta.env.BASE_URL which Vite sets from --base
156+
npx vite build --base /vue/
157+
158+
mkdir -p "${OUTPUT_DIR}/vue"
159+
cp -r dist/* "${OUTPUT_DIR}/vue/"
160+
echo "[vue] Done."
161+
}
162+
163+
build_react_router_test() {
164+
# Only build Vite-based (RR6+) apps. CRA-based reactrouter5 can't handle
165+
# sub-path routing without code changes, and it's being replaced by RR6.
166+
local APP
167+
APP=$(pick_app "${REPO_ROOT}/packages/react-router/test" reactrouter6-react19 reactrouter6-react18 reactrouter6) || {
168+
echo "[react-router] No Vite-based test app found, skipping."
169+
return 0
170+
}
171+
echo "[react-router] Building ${APP}..."
172+
173+
cd "${REPO_ROOT}/packages/react-router/test"
174+
./build.sh "${APP}"
175+
cd "build/${APP}"
176+
npm install --legacy-peer-deps
177+
npm run sync
178+
npx vite build --base /react-router/
179+
180+
mkdir -p "${OUTPUT_DIR}/react-router"
181+
cp -r dist/* "${OUTPUT_DIR}/react-router/"
182+
echo "[react-router] Done."
183+
}
184+
185+
build_angular_test > /tmp/vercel-angular-test.log 2>&1 &
186+
PID_ANG_TEST=$!
187+
build_react_test > /tmp/vercel-react-test.log 2>&1 &
188+
PID_REACT_TEST=$!
189+
build_vue_test > /tmp/vercel-vue-test.log 2>&1 &
190+
PID_VUE_TEST=$!
191+
build_react_router_test > /tmp/vercel-rr-test.log 2>&1 &
192+
PID_RR_TEST=$!
193+
194+
TEST_FAILED=""
195+
wait $PID_ANG_TEST || { echo "Angular test app failed:"; tail -30 /tmp/vercel-angular-test.log; TEST_FAILED="${TEST_FAILED} angular"; }
196+
wait $PID_REACT_TEST || { echo "React test app failed:"; tail -30 /tmp/vercel-react-test.log; TEST_FAILED="${TEST_FAILED} react"; }
197+
wait $PID_VUE_TEST || { echo "Vue test app failed:"; tail -30 /tmp/vercel-vue-test.log; TEST_FAILED="${TEST_FAILED} vue"; }
198+
wait $PID_RR_TEST || { echo "React Router test app failed:"; tail -30 /tmp/vercel-rr-test.log; TEST_FAILED="${TEST_FAILED} react-router"; }
199+
200+
if [ -n "${TEST_FAILED}" ]; then
201+
echo ""
202+
echo "WARNING: Some test app builds failed:${TEST_FAILED}"
203+
echo "Core tests and successful framework apps will still be deployed."
204+
fi
205+
206+
# ---------------------------------------------------------------------------
207+
# Step 4 - Landing Page
208+
# ---------------------------------------------------------------------------
209+
echo ""
210+
echo "--- Step 4: Generating landing page ---"
211+
212+
cat > "${OUTPUT_DIR}/index.html" << 'LANDING_EOF'
213+
<!DOCTYPE html>
214+
<html lang="en">
215+
<head>
216+
<meta charset="UTF-8">
217+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
218+
<title>Ionic Framework - Preview</title>
219+
<style>
220+
* { margin: 0; padding: 0; box-sizing: border-box; }
221+
body {
222+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
223+
background: #f5f5f5; padding: 2rem; color: #333;
224+
}
225+
.container { max-width: 680px; margin: 0 auto; }
226+
h1 { font-size: 1.4rem; margin-bottom: 0.25rem; }
227+
.subtitle { color: #666; margin-bottom: 1.5rem; font-size: 0.875rem; }
228+
.cards { display: grid; gap: 0.75rem; }
229+
a.card {
230+
background: #fff; border-radius: 8px; padding: 1rem 1.25rem;
231+
text-decoration: none; color: inherit;
232+
border: 1px solid #e0e0e0; transition: border-color 0.15s;
233+
}
234+
a.card:hover { border-color: #4f8ef7; }
235+
.card h2 { font-size: 1rem; margin-bottom: 0.2rem; display: flex; align-items: center; gap: 0.5rem; }
236+
.card p { color: #666; font-size: 0.8rem; }
237+
.badge {
238+
display: inline-block; font-size: 0.65rem; padding: 1px 6px;
239+
border-radius: 3px; font-weight: 600;
240+
}
241+
.badge-green { background: #e8f5e9; color: #2e7d32; }
242+
.badge-blue { background: #e3f2fd; color: #1565c0; }
243+
.badge-red { background: #fce4ec; color: #c62828; }
244+
.badge-purple{ background: #f3e5f5; color: #6a1b9a; }
245+
hr { border: none; border-top: 1px solid #e0e0e0; margin: 1rem 0; }
246+
.tip { font-size: 0.75rem; color: #999; margin-top: 1rem; }
247+
</style>
248+
</head>
249+
<body>
250+
<div class="container">
251+
<h1>Ionic Framework Preview</h1>
252+
<p class="subtitle">Component test apps for manual validation</p>
253+
<div class="cards">
254+
<a class="card" href="/src/components/">
255+
<h2>Core Components <span class="badge badge-blue">Stencil</span></h2>
256+
<p>Browse to /src/components/{name}/test/{scenario}/</p>
257+
</a>
258+
<hr>
259+
<a class="card" href="/angular/">
260+
<h2>Angular <span class="badge badge-red">ng20</span></h2>
261+
<p>@ionic/angular standalone + lazy-loaded component tests</p>
262+
</a>
263+
<a class="card" href="/react/">
264+
<h2>React <span class="badge badge-blue">react19</span></h2>
265+
<p>@ionic/react overlays, hooks, tabs, form controls</p>
266+
</a>
267+
<a class="card" href="/vue/">
268+
<h2>Vue <span class="badge badge-green">vue3</span></h2>
269+
<p>@ionic/vue overlays, router, tabs, lifecycle</p>
270+
</a>
271+
<a class="card" href="/react-router/">
272+
<h2>React Router <span class="badge badge-purple">rr6</span></h2>
273+
<p>@ionic/react-router navigation, tabs, transitions</p>
274+
</a>
275+
</div>
276+
<p class="tip">Links to framework apps that were not built will 404.</p>
277+
</div>
278+
</body>
279+
</html>
280+
LANDING_EOF
281+
282+
echo ""
283+
echo "=== Preview build complete ==="
284+
ls -la "${OUTPUT_DIR}"

vercel.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "https://openapi.vercel.sh/vercel.json",
3+
"framework": null,
4+
"installCommand": "cd core && npm install",
5+
"buildCommand": "bash scripts/vercel-build.sh",
6+
"outputDirectory": "_vercel_output",
7+
"rewrites": [
8+
{ "source": "/angular/:path*", "destination": "/angular/index.html" },
9+
{ "source": "/react/:path*", "destination": "/react/index.html" },
10+
{ "source": "/vue/:path*", "destination": "/vue/index.html" },
11+
{ "source": "/react-router/:path*", "destination": "/react-router/index.html" }
12+
]
13+
}

0 commit comments

Comments
 (0)