mirror of
https://github.com/unslothai/unsloth
synced 2026-04-21 13:37:39 +00:00
perf(studio): upgrade to Vite 8 + auto-install bun for faster frontend builds (#4522)
* perf(studio): upgrade to Vite 8 + auto-install bun for 3x faster frontend builds
* fix(studio): make bun-to-npm fallback actually reachable
setup.sh used run_quiet() for the bun install attempt, but run_quiet
calls exit on failure. This killed the script before the npm fallback
could run, making the "falling back to npm" branch dead code.
Replace the run_quiet call with a direct bun invocation that captures
output to a temp file (same pattern, but returns instead of exiting).
Also clean up partial node_modules left by a failed bun install before
falling back to npm, in both setup.sh and build.sh. Without this, npm
inherits a corrupted node_modules tree from the failed bun run.
* fix(studio): restore commonjsOptions for dagre CJS interop
The previous commit removed build.commonjsOptions, assuming Vite 8's
Rolldown handles CJS natively. While optimizeDeps.include covers the
dev server (pre-bundling), it does NOT apply to production builds.
The resolve.alias still points @dagrejs/dagre to its .cjs.js entry,
so without commonjsOptions the production bundle fails to resolve
the CJS default export. This causes "TypeError: e is not a function"
on /chat after build (while dev mode works fine).
Restore the original commonjsOptions block to fix production builds.
* fix(studio): use motion/react instead of legacy framer-motion import
* fix(studio): address PR review findings for Vite 8 + bun upgrade
Fixes:
- Remove bun.lock from repo and add to .gitignore (npm is source of truth)
- Use & bun install *> $null pattern in setup.ps1 for reliable $LASTEXITCODE
- Add Remove-Item node_modules before npm fallback in setup.ps1
- Print bun install failure log in setup.sh before discarding
- Add Refresh-Environment after npm install -g bun in setup.ps1
- Tighten Node version check to ^20.19.0 || >=22.12.0 (Vite 8 requirement)
- Add engines field to package.json
- Use string comparison for _install_ok in build.sh
- Remove explicit framer-motion ^11.18.2 from package.json (motion pulls
framer-motion ^12.38.0 as its own dependency — the old pin caused a
version conflict)
* Fix Colab Node bypass and bun.lock stale-build trigger
Gate the Colab Node shortcut on NODE_OK=true so Colab
environments with a Node version too old for Vite 8 fall
through to the nvm install path instead of silently proceeding.
Exclude bun.lock from the stale-build probe in both setup.sh
and setup.ps1 so it does not force unnecessary frontend rebuilds
on every run.
---------
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
Co-authored-by: Shine1i <wasimysdev@gmail.com>
This commit is contained in:
parent
be2cd7087a
commit
d69d60ff19
7 changed files with 131 additions and 2510 deletions
17
build.sh
17
build.sh
|
|
@ -29,7 +29,22 @@ _restore_gitignores() {
|
|||
}
|
||||
trap _restore_gitignores EXIT
|
||||
|
||||
npm install
|
||||
# Use bun for install if available (faster), fall back to npm.
|
||||
_install_ok=false
|
||||
if command -v bun &>/dev/null; then
|
||||
if bun install; then
|
||||
_install_ok=true
|
||||
else
|
||||
echo "⚠ bun install failed, falling back to npm"
|
||||
rm -rf node_modules
|
||||
fi
|
||||
fi
|
||||
if [ "$_install_ok" != "true" ]; then
|
||||
if ! npm install; then
|
||||
echo "❌ ERROR: package install failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
npm run build # outputs to studio/frontend/dist/
|
||||
|
||||
_restore_gitignores
|
||||
|
|
|
|||
1
studio/frontend/.gitignore
vendored
1
studio/frontend/.gitignore
vendored
|
|
@ -11,6 +11,7 @@ pnpm-debug.log*
|
|||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
bun.lock
|
||||
dist
|
||||
dist-ssr
|
||||
test/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -3,6 +3,9 @@
|
|||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
|
|
@ -35,7 +38,7 @@
|
|||
"@streamdown/code": "1.0.2",
|
||||
"@streamdown/math": "1.0.2",
|
||||
"@streamdown/mermaid": "1.0.2",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"@tanstack/react-router": "^1.159.10",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@toolwind/corner-shape": "^0.0.8-3",
|
||||
|
|
@ -48,7 +51,6 @@
|
|||
"cmdk": "^1.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"dexie": "^4.3.0",
|
||||
"framer-motion": "^11.18.2",
|
||||
"js-yaml": "^4.1.1",
|
||||
"katex": "^0.16.28",
|
||||
"lucide-react": "^0.577.0",
|
||||
|
|
@ -80,13 +82,13 @@
|
|||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.5",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.26",
|
||||
"globals": "^16.5.0",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.55.0",
|
||||
"vite": "^7.3.1"
|
||||
"vite": "^8.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import {
|
|||
useAuiEvent,
|
||||
useAuiState,
|
||||
} from "@assistant-ui/react";
|
||||
import { motion } from "framer-motion";
|
||||
import { motion } from "motion/react";
|
||||
import {
|
||||
ArrowDownIcon,
|
||||
ArrowUpIcon,
|
||||
|
|
|
|||
|
|
@ -728,16 +728,22 @@ if ($IsPipInstall) {
|
|||
Write-Host "[OK] Running from pip install - frontend already bundled, skipping Node/npm check" -ForegroundColor Green
|
||||
} else {
|
||||
# setup.sh installs Node LTS (v22) via nvm. We enforce the same range here:
|
||||
# Node >= 20, npm >= 11.
|
||||
# Vite 8 requires Node ^20.19.0 || >=22.12.0, npm >= 11.
|
||||
$NeedNode = $true
|
||||
try {
|
||||
$NodeVersion = (node -v 2>$null)
|
||||
$NpmVersion = (npm -v 2>$null)
|
||||
if ($NodeVersion -and $NpmVersion) {
|
||||
$NodeMajor = [int]($NodeVersion -replace 'v','').Split('.')[0]
|
||||
$NodeParts = ($NodeVersion -replace 'v','').Split('.')
|
||||
$NodeMajor = [int]$NodeParts[0]
|
||||
$NodeMinor = [int]$NodeParts[1]
|
||||
$NpmMajor = [int]$NpmVersion.Split('.')[0]
|
||||
|
||||
if ($NodeMajor -ge 20 -and $NpmMajor -ge 11) {
|
||||
# Vite 8: ^20.19.0 || >=22.12.0
|
||||
$NodeOk = ($NodeMajor -eq 20 -and $NodeMinor -ge 19) -or
|
||||
($NodeMajor -eq 22 -and $NodeMinor -ge 12) -or
|
||||
($NodeMajor -ge 23)
|
||||
if ($NodeOk -and $NpmMajor -ge 11) {
|
||||
Write-Host "[OK] Node $NodeVersion and npm $NpmVersion already meet requirements." -ForegroundColor Green
|
||||
$NeedNode = $false
|
||||
} else {
|
||||
|
|
@ -761,6 +767,24 @@ if ($IsPipInstall) {
|
|||
}
|
||||
|
||||
Write-Host "[OK] Node $(node -v) | npm $(npm -v)" -ForegroundColor Green
|
||||
|
||||
# ── bun (optional, faster package installs) ──
|
||||
# Installed via npm — Node is already guaranteed above. Works on all platforms.
|
||||
if (-not (Get-Command bun -ErrorAction SilentlyContinue)) {
|
||||
Write-Host " Installing bun (faster frontend package installs)..." -ForegroundColor DarkGray
|
||||
$prevEAP_bun = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
npm install -g bun 2>&1 | Out-Null
|
||||
$ErrorActionPreference = $prevEAP_bun
|
||||
Refresh-Environment
|
||||
if (Get-Command bun -ErrorAction SilentlyContinue) {
|
||||
Write-Host "[OK] bun installed ($(bun --version))" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[OK] bun install skipped (npm will be used instead)" -ForegroundColor DarkGray
|
||||
}
|
||||
} else {
|
||||
Write-Host "[OK] bun already installed ($(bun --version))" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
|
@ -844,10 +868,10 @@ if ($IsPipInstall) {
|
|||
if ($NewerFile) { break }
|
||||
}
|
||||
}
|
||||
# Also check all top-level files (package.json, bun.lock, vite.config.ts, index.html, etc.)
|
||||
# Also check all top-level files (package.json, vite.config.ts, index.html, etc.)
|
||||
if (-not $NewerFile) {
|
||||
$NewerFile = Get-ChildItem -Path $FrontendDir -File -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.LastWriteTime -gt $DistTime } |
|
||||
Where-Object { $_.Name -ne "bun.lock" -and $_.LastWriteTime -gt $DistTime } |
|
||||
Select-Object -First 1
|
||||
}
|
||||
if (-not $NewerFile) {
|
||||
|
|
@ -882,26 +906,47 @@ if ($NeedFrontendBuild -and -not $IsPipInstall) {
|
|||
$WalkDir = Split-Path $WalkDir -Parent
|
||||
}
|
||||
|
||||
# npm writes warnings to stderr; lower ErrorActionPreference so PS doesn't
|
||||
# treat them as terminating errors (same pattern as the pip section below).
|
||||
# Use bun if available (faster install), fall back to npm.
|
||||
# Bun is used only as package manager; Node runs the actual build (Vite 8).
|
||||
$prevEAP_npm = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
Push-Location $FrontendDir
|
||||
npm install 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
|
||||
$UseBun = $null -ne (Get-Command bun -ErrorAction SilentlyContinue)
|
||||
|
||||
if ($UseBun) {
|
||||
Write-Host " Using bun for package install (faster)" -ForegroundColor DarkGray
|
||||
& bun install *> $null
|
||||
$bunExit = $LASTEXITCODE
|
||||
if ($bunExit -ne 0) {
|
||||
Write-Host " [WARN] bun install failed (exit $bunExit), falling back to npm" -ForegroundColor Yellow
|
||||
if (Test-Path "node_modules") {
|
||||
Remove-Item "node_modules" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
$UseBun = $false
|
||||
}
|
||||
}
|
||||
if (-not $UseBun) {
|
||||
& npm install *> $null
|
||||
$npmExit = $LASTEXITCODE
|
||||
if ($npmExit -ne 0) {
|
||||
Pop-Location
|
||||
$ErrorActionPreference = $prevEAP_npm
|
||||
foreach ($gi in $HiddenGitignores) { Rename-Item -Path "$gi._twbuild" -NewName (Split-Path $gi -Leaf) -Force -ErrorAction SilentlyContinue }
|
||||
Write-Host "[ERROR] npm install failed (exit code $LASTEXITCODE)" -ForegroundColor Red
|
||||
Write-Host "[ERROR] npm install failed (exit code $npmExit)" -ForegroundColor Red
|
||||
Write-Host " Try running 'npm install' manually in frontend/ to see errors" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
npm run build 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
}
|
||||
|
||||
# Always use npm to run the build (Node runtime — avoids bun Windows runtime issues)
|
||||
& npm run build *> $null
|
||||
$buildExit = $LASTEXITCODE
|
||||
if ($buildExit -ne 0) {
|
||||
Pop-Location
|
||||
$ErrorActionPreference = $prevEAP_npm
|
||||
foreach ($gi in $HiddenGitignores) { Rename-Item -Path "$gi._twbuild" -NewName (Split-Path $gi -Leaf) -Force -ErrorAction SilentlyContinue }
|
||||
Write-Host "[ERROR] npm run build failed (exit code $LASTEXITCODE)" -ForegroundColor Red
|
||||
Write-Host "[ERROR] npm run build failed (exit code $buildExit)" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ _NEED_FRONTEND_BUILD=true
|
|||
if [ -d "$SCRIPT_DIR/frontend/dist" ]; then
|
||||
# Check all top-level files (package.json, bun.lock, vite.config.ts, index.html, etc.)
|
||||
_changed=$(find "$SCRIPT_DIR/frontend" -maxdepth 1 -type f \
|
||||
! -name 'bun.lock' \
|
||||
-newer "$SCRIPT_DIR/frontend/dist" -print -quit 2>/dev/null)
|
||||
# Check src/ and public/ recursively (|| true guards against set -e when dirs are missing)
|
||||
if [ -z "$_changed" ]; then
|
||||
|
|
@ -85,12 +86,18 @@ else
|
|||
NEED_NODE=true
|
||||
if command -v node &>/dev/null && command -v npm &>/dev/null; then
|
||||
NODE_MAJOR=$(node -v | sed 's/v//' | cut -d. -f1)
|
||||
NODE_MINOR=$(node -v | sed 's/v//' | cut -d. -f2)
|
||||
NPM_MAJOR=$(npm -v | cut -d. -f1)
|
||||
if [ "$NODE_MAJOR" -ge 20 ] && [ "$NPM_MAJOR" -ge 11 ]; then
|
||||
# Vite 8 requires Node ^20.19.0 || >=22.12.0
|
||||
NODE_OK=false
|
||||
if [ "$NODE_MAJOR" -eq 20 ] && [ "$NODE_MINOR" -ge 19 ]; then NODE_OK=true; fi
|
||||
if [ "$NODE_MAJOR" -eq 22 ] && [ "$NODE_MINOR" -ge 12 ]; then NODE_OK=true; fi
|
||||
if [ "$NODE_MAJOR" -ge 23 ]; then NODE_OK=true; fi
|
||||
if [ "$NODE_OK" = true ] && [ "$NPM_MAJOR" -ge 11 ]; then
|
||||
echo "✅ Node $(node -v) and npm $(npm -v) already meet requirements. Skipping nvm install."
|
||||
NEED_NODE=false
|
||||
else
|
||||
if [ "$IS_COLAB" = true ]; then
|
||||
if [ "$IS_COLAB" = true ] && [ "$NODE_OK" = true ]; then
|
||||
echo "✅ Node $(node -v) and npm $(npm -v) detected in Colab."
|
||||
# In Colab, just upgrade npm directly - nvm doesn't work well
|
||||
if [ "$NPM_MAJOR" -lt 11 ]; then
|
||||
|
|
@ -150,6 +157,20 @@ fi
|
|||
|
||||
echo "✅ Node $(node -v) | npm $(npm -v)"
|
||||
|
||||
# ── Install bun (optional, faster package installs) ──
|
||||
# Uses npm to install bun globally — Node is already guaranteed above,
|
||||
# avoids platform-specific installers, PATH issues, and admin requirements.
|
||||
if ! command -v bun &>/dev/null; then
|
||||
echo " Installing bun (faster frontend package installs)..."
|
||||
if npm install -g bun > /dev/null 2>&1 && command -v bun &>/dev/null; then
|
||||
echo "✅ bun installed ($(bun --version))"
|
||||
else
|
||||
echo " bun install skipped (npm will be used instead)"
|
||||
fi
|
||||
else
|
||||
echo "✅ bun already installed ($(bun --version))"
|
||||
fi
|
||||
|
||||
# ── 5. Build frontend ──
|
||||
cd "$SCRIPT_DIR/frontend"
|
||||
|
||||
|
|
@ -174,7 +195,27 @@ _restore_gitignores() {
|
|||
}
|
||||
trap _restore_gitignores EXIT
|
||||
|
||||
run_quiet "npm install" npm install
|
||||
# Use bun for install if available (faster), fall back to npm.
|
||||
# Build always uses npm (Node runtime — avoids bun runtime issues on some platforms).
|
||||
# NOTE: We intentionally avoid run_quiet for the bun install attempt because
|
||||
# run_quiet calls exit on failure, which would kill the script before the npm
|
||||
# fallback can run. Instead we capture output manually and only show it on failure.
|
||||
if command -v bun &>/dev/null; then
|
||||
echo " Using bun for package install (faster)"
|
||||
_bun_log=$(mktemp)
|
||||
if bun install >"$_bun_log" 2>&1; then
|
||||
rm -f "$_bun_log"
|
||||
else
|
||||
echo " ⚠️ bun install failed, falling back to npm"
|
||||
echo " bun install output:"
|
||||
sed 's/^/ | /' "$_bun_log" >&2
|
||||
rm -f "$_bun_log"
|
||||
rm -rf node_modules
|
||||
run_quiet "npm install" npm install
|
||||
fi
|
||||
else
|
||||
run_quiet "npm install" npm install
|
||||
fi
|
||||
run_quiet "npm run build" npm run build
|
||||
|
||||
_restore_gitignores
|
||||
|
|
|
|||
Loading…
Reference in a new issue