[api] Update /api/examples/list to be static for vc init (#7596)

Previously, this API would download the entire git repository for each request. Instead, we can defer downloading to the `/download` API only and change the list API to be statically generated at build time.

This will improve the time to render the results from `vc init`.


## Before
- `https://vercel-lu6z5kf4s.vercel.sh/api/examples/list` responds in 6200 ms
- `https://vercel-lu6z5kf4s.vercel.sh/api/examples/list-all` responds in 800ms

## After
- `https://vercel-ctsxcwzgc.vercel.sh/api/examples/list` responds in 60 ms 
- `https://vercel-ctsxcwzgc.vercel.sh/api/examples/list-all` responds in 60 ms
This commit is contained in:
Steven
2022-03-22 11:26:19 -04:00
committed by GitHub
parent a1e337e0dd
commit 26abb0a85a
6 changed files with 61 additions and 39 deletions

46
api/_lib/script/build.ts Normal file
View File

@@ -0,0 +1,46 @@
import fs from 'fs/promises';
import { join } from 'path';
import { getExampleList } from '../examples/example-list';
import { mapOldToNew } from '../examples/map-old-to-new';
const repoRoot = join(__dirname, '..', '..', '..');
const pubDir = join(repoRoot, 'public');
async function main() {
console.log(`Building static frontend ${repoRoot}...`);
await fs.rm(pubDir, { recursive: true, force: true });
await fs.mkdir(pubDir);
const examples = await getExampleList();
const pathListAll = join(pubDir, 'list-all.json');
await fs.writeFile(pathListAll, JSON.stringify(examples));
const exampleDirs = await fs.readdir(join(repoRoot, 'examples'), {
withFileTypes: true,
});
const existingExamples = exampleDirs
.filter(dir => dir.isDirectory())
.map(dir => ({
name: dir.name,
visible: true,
suggestions: [],
}));
const oldExamples = Object.keys(mapOldToNew).map(key => ({
name: key,
visible: false,
suggestions: mapOldToNew[key],
}));
const pathList = join(pubDir, 'list.json');
await fs.writeFile(
pathList,
JSON.stringify([...existingExamples, ...oldExamples])
);
console.log('Completed building static frontend.');
}
main().catch(console.error);

View File

@@ -1,10 +0,0 @@
import { VercelRequest, VercelResponse } from '@vercel/node';
import { getExampleList } from '../_lib/examples/example-list';
import { withApiHandler } from '../_lib/util/with-api-handler';
export default withApiHandler(async function (
req: VercelRequest,
res: VercelResponse
) {
res.status(200).json(await getExampleList());
});

View File

@@ -1,27 +0,0 @@
import { extract } from '../_lib/examples/extract';
import { summary } from '../_lib/examples/summary';
import { VercelRequest, VercelResponse } from '@vercel/node';
import { mapOldToNew } from '../_lib/examples/map-old-to-new';
import { withApiHandler } from '../_lib/util/with-api-handler';
export default withApiHandler(async function (
req: VercelRequest,
res: VercelResponse
) {
await extract('https://github.com/vercel/vercel/archive/main.zip', '/tmp');
const exampleList = summary('/tmp/vercel-main/examples');
const existingExamples = Array.from(exampleList).map(key => ({
name: key,
visible: true,
suggestions: [],
}));
const oldExamples = Object.keys(mapOldToNew).map(key => ({
name: key,
visible: false,
suggestions: mapOldToNew[key],
}));
res.status(200).json([...existingExamples, ...oldExamples]);
});

View File

@@ -42,6 +42,7 @@
"node-fetch": "2.6.1",
"npm-package-arg": "6.1.0",
"prettier": "2.3.1",
"ts-eager": "2.0.2",
"ts-jest": "27.0.4",
"turbo": "1.1.9"
},
@@ -53,7 +54,7 @@
"publish-from-github": "./utils/publish.sh",
"changelog": "node utils/changelog.js",
"build": "turbo run build",
"vercel-build": "mkdir -p public && echo '<a href=\"https://vercel.com/import\">Import</a>' > public/output.html",
"vercel-build": "yarn build && cd api && node -r ts-eager/register ./_lib/script/build.ts",
"pre-commit": "lint-staged",
"test": "jest --rootDir=\"test\" --testPathPattern=\"\\.test.js\"",
"test-unit": "yarn test && node utils/run.js test-unit",

View File

@@ -161,7 +161,6 @@
"title": "3.4.1",
"tmp-promise": "1.0.3",
"tree-kill": "1.2.2",
"ts-eager": "2.0.2",
"ts-node": "8.3.0",
"typescript": "4.3.4",
"universal-analytics": "0.4.20",

View File

@@ -8,8 +8,21 @@
{
"source": "/api/v1/frameworks",
"destination": "/api/frameworks"
},
{
"source": "/api/examples/list",
"destination": "/list.json"
},
{
"source": "/api/examples/list-all",
"destination": "/list-all.json"
}
],
"build": {
"env": {
"ENABLE_FILE_SYSTEM_API": "1"
}
},
"github": {
"silent": true,
"autoJobCancelation": true