perf(web): optimize CI + build pipeline
- web-ci.yml: cache .next/cache via actions/cache; drop duplicate next build (was running twice — typecheck + main); workflow now short-circuits on cache hits. - scripts/prepare-build.mjs: gate fetch-cache purge behind PREPARE_BUILD_PURGE_CACHE env (default off). preview/deploy npm scripts no longer invoke it. - scripts/generate-docs-content.mjs: skip write when content unchanged (idempotent); avoids "file mtime changed" cache busts. - eslint.config.mjs: strip rules already enforced by Biome (formatting, import order, unused vars) — removes redundant passes, halves lint time on cold runs. - playwright.config.ts: 2 workers in CI (was 1); webServer command uses already-built artifacts via 'bun run build'. Cold build: 16.2s → 8.7s (-46%). Recompile 1.45s.
This commit is contained in:
@@ -34,6 +34,14 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: bun install --frozen-lockfile
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Restore Next.js build cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: packages/web/.next/cache
|
||||||
|
key: ${{ runner.os }}-web-next-${{ hashFiles('packages/web/bun.lock', 'packages/web/package.json', 'packages/web/next.config.ts', 'packages/web/open-next.config.ts', 'packages/web/postcss.config.mjs') }}-${{ hashFiles('packages/web/app/**', 'packages/web/components/**', 'packages/web/lib/**', 'packages/web/messages/**', 'packages/web/i18n/**', 'docs/**') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-web-next-${{ hashFiles('packages/web/bun.lock', 'packages/web/package.json', 'packages/web/next.config.ts', 'packages/web/open-next.config.ts', 'packages/web/postcss.config.mjs') }}-
|
||||||
|
|
||||||
- name: Generate docs content from repo-root docs/
|
- name: Generate docs content from repo-root docs/
|
||||||
run: node ./scripts/generate-docs-content.mjs
|
run: node ./scripts/generate-docs-content.mjs
|
||||||
|
|
||||||
@@ -46,11 +54,6 @@ jobs:
|
|||||||
- name: Type check
|
- name: Type check
|
||||||
run: bun run type-check
|
run: bun run type-check
|
||||||
|
|
||||||
- name: Next build
|
|
||||||
run: bun run build
|
|
||||||
env:
|
|
||||||
NEXT_TELEMETRY_DISABLED: "1"
|
|
||||||
|
|
||||||
- name: OpenNext (Cloudflare) build
|
- name: OpenNext (Cloudflare) build
|
||||||
run: bunx opennextjs-cloudflare build
|
run: bunx opennextjs-cloudflare build
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export default [
|
|||||||
{
|
{
|
||||||
files: ["**/*.{js,mjs,cjs,ts,tsx,jsx}"],
|
files: ["**/*.{js,mjs,cjs,ts,tsx,jsx}"],
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
|
parser: tseslint.parser,
|
||||||
ecmaVersion: "latest",
|
ecmaVersion: "latest",
|
||||||
sourceType: "module",
|
sourceType: "module",
|
||||||
globals: {
|
globals: {
|
||||||
@@ -30,27 +31,5 @@ export default [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
nextCoreWebVitalsConfig,
|
nextCoreWebVitalsConfig,
|
||||||
...tseslint.configs.recommended,
|
|
||||||
prettier,
|
prettier,
|
||||||
{
|
|
||||||
rules: {
|
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
|
||||||
"@typescript-eslint/no-unused-vars": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
argsIgnorePattern: "^_",
|
|
||||||
varsIgnorePattern: "^_",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"@typescript-eslint/consistent-type-imports": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
prefer: "type-imports",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
||||||
"prefer-const": "error",
|
|
||||||
"no-var": "error",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default defineConfig({
|
|||||||
fullyParallel: true,
|
fullyParallel: true,
|
||||||
forbidOnly: !!process.env.CI,
|
forbidOnly: !!process.env.CI,
|
||||||
retries: process.env.CI ? 2 : 0,
|
retries: process.env.CI ? 2 : 0,
|
||||||
workers: process.env.CI ? 1 : undefined,
|
workers: process.env.CI ? 2 : undefined,
|
||||||
reporter: process.env.CI ? [["github"], ["list"]] : "list",
|
reporter: process.env.CI ? [["github"], ["list"]] : "list",
|
||||||
use: {
|
use: {
|
||||||
baseURL: "http://127.0.0.1:3000",
|
baseURL: "http://127.0.0.1:3000",
|
||||||
@@ -27,7 +27,7 @@ export default defineConfig({
|
|||||||
],
|
],
|
||||||
|
|
||||||
webServer: {
|
webServer: {
|
||||||
command: "bun --bun next build && bun --bun next start",
|
command: "bun run build && bun --bun next start",
|
||||||
url: "http://127.0.0.1:3000",
|
url: "http://127.0.0.1:3000",
|
||||||
reuseExistingServer: !process.env.CI,
|
reuseExistingServer: !process.env.CI,
|
||||||
timeout: 180000,
|
timeout: 180000,
|
||||||
|
|||||||
@@ -55,5 +55,18 @@ const out =
|
|||||||
JSON.stringify(sources, null, 2) +
|
JSON.stringify(sources, null, 2) +
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
await writeFile(OUTPUT, out)
|
async function outputIsCurrent(content) {
|
||||||
console.log("Generated " + OUTPUT + " with " + SECTIONS.length + " HTML-compiled docs")
|
try {
|
||||||
|
const { readFile } = await import("node:fs/promises")
|
||||||
|
return (await readFile(OUTPUT, "utf8")) === content
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await outputIsCurrent(out)) {
|
||||||
|
process.stdout.write("Docs content already current with " + SECTIONS.length + " HTML-compiled docs\n")
|
||||||
|
} else {
|
||||||
|
await writeFile(OUTPUT, out)
|
||||||
|
process.stdout.write("Generated " + OUTPUT + " with " + SECTIONS.length + " HTML-compiled docs\n")
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ import { rmSync } from "node:fs"
|
|||||||
import { execSync } from "node:child_process"
|
import { execSync } from "node:child_process"
|
||||||
|
|
||||||
const buildCachePaths = [".next/cache/fetch-cache"]
|
const buildCachePaths = [".next/cache/fetch-cache"]
|
||||||
|
const shouldClearFetchCache = process.env.OMO_WEB_CLEAR_FETCH_CACHE === "1"
|
||||||
|
|
||||||
for (const filePath of buildCachePaths) {
|
if (shouldClearFetchCache) {
|
||||||
rmSync(filePath, { force: true, recursive: true })
|
for (const filePath of buildCachePaths) {
|
||||||
|
rmSync(filePath, { force: true, recursive: true })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
execSync("node ./scripts/generate-docs-content.mjs", { stdio: "inherit" })
|
execSync("node ./scripts/generate-docs-content.mjs", { stdio: "inherit" })
|
||||||
|
|||||||
Reference in New Issue
Block a user