fix(@astrojs/vercel): slowness and symbolic link (#8348)
This commit is contained in:
parent
f21599671a
commit
5f2c55bb54
4 changed files with 64 additions and 27 deletions
6
.changeset/proud-forks-rescue.md
Normal file
6
.changeset/proud-forks-rescue.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'@astrojs/vercel': patch
|
||||
---
|
||||
|
||||
- Cache result during bundling, to speed up the process of multiple functions;
|
||||
- Avoid creating multiple symbolic links of the dependencies when building the project with `funcitonPerRoute` enabled;
|
|
@ -1,5 +1,6 @@
|
|||
import type { PathLike } from 'node:fs';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import { existsSync } from 'node:fs';
|
||||
import nodePath from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
@ -74,11 +75,13 @@ export async function copyFilesToFunction(
|
|||
|
||||
if (isSymlink) {
|
||||
const realdest = fileURLToPath(new URL(nodePath.relative(commonAncestor, realpath), outDir));
|
||||
await fs.symlink(
|
||||
nodePath.relative(fileURLToPath(new URL('.', dest)), realdest),
|
||||
dest,
|
||||
isDir ? 'dir' : 'file'
|
||||
);
|
||||
const target = nodePath.relative(fileURLToPath(new URL('.', dest)), realdest);
|
||||
// NOTE: when building function per route, dependencies are linked at the first run, then there's no need anymore to do that once more.
|
||||
// So we check if the destination already exists. If it does, move on.
|
||||
// Symbolic links here are usually dependencies and not user code. Symbolic links exist because of the pnpm strategy.
|
||||
if (!existsSync(dest)) {
|
||||
await fs.symlink(target, dest, isDir ? 'dir' : 'file');
|
||||
}
|
||||
} else if (!isDir) {
|
||||
await fs.copyFile(origin, dest);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
import { relative as relativePath } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { relative } from 'node:path';
|
||||
import { copyFilesToFunction } from './fs.js';
|
||||
import type { AstroIntegrationLogger } from 'astro';
|
||||
|
||||
export async function copyDependenciesToFunction({
|
||||
entry,
|
||||
outDir,
|
||||
includeFiles,
|
||||
excludeFiles,
|
||||
}: {
|
||||
entry: URL;
|
||||
outDir: URL;
|
||||
includeFiles: URL[];
|
||||
excludeFiles: URL[];
|
||||
}): Promise<{ handler: string }> {
|
||||
export async function copyDependenciesToFunction(
|
||||
{
|
||||
entry,
|
||||
outDir,
|
||||
includeFiles,
|
||||
excludeFiles,
|
||||
logger,
|
||||
}: {
|
||||
entry: URL;
|
||||
outDir: URL;
|
||||
includeFiles: URL[];
|
||||
excludeFiles: URL[];
|
||||
logger: AstroIntegrationLogger;
|
||||
},
|
||||
// we want to pass the caching by reference, and not by value
|
||||
cache: object
|
||||
): Promise<{ handler: string }> {
|
||||
const entryPath = fileURLToPath(entry);
|
||||
logger.info(`Bundling function ${relative(fileURLToPath(outDir), entryPath)}`);
|
||||
|
||||
// Get root of folder of the system (like C:\ on Windows or / on Linux)
|
||||
let base = entry;
|
||||
|
@ -31,6 +40,7 @@ export async function copyDependenciesToFunction({
|
|||
// If you have a route of /dev this appears in source and NFT will try to
|
||||
// scan your local /dev :8
|
||||
ignore: ['/dev/**'],
|
||||
cache,
|
||||
});
|
||||
|
||||
for (const error of result.warnings) {
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro';
|
||||
import type {
|
||||
AstroAdapter,
|
||||
AstroConfig,
|
||||
AstroIntegration,
|
||||
RouteData,
|
||||
AstroIntegrationLogger,
|
||||
} from 'astro';
|
||||
import { AstroError } from 'astro/errors';
|
||||
import glob from 'fast-glob';
|
||||
import { basename } from 'node:path';
|
||||
|
@ -78,16 +84,27 @@ export default function vercelServerless({
|
|||
// Extra files to be merged with `includeFiles` during build
|
||||
const extraFilesToInclude: URL[] = [];
|
||||
|
||||
async function createFunctionFolder(funcName: string, entry: URL, inc: URL[]) {
|
||||
const NTF_CACHE = Object.create(null);
|
||||
|
||||
async function createFunctionFolder(
|
||||
funcName: string,
|
||||
entry: URL,
|
||||
inc: URL[],
|
||||
logger: AstroIntegrationLogger
|
||||
) {
|
||||
const functionFolder = new URL(`./functions/${funcName}.func/`, _config.outDir);
|
||||
|
||||
// Copy necessary files (e.g. node_modules/)
|
||||
const { handler } = await copyDependenciesToFunction({
|
||||
entry,
|
||||
outDir: functionFolder,
|
||||
includeFiles: inc,
|
||||
excludeFiles: excludeFiles?.map((file) => new URL(file, _config.root)) || [],
|
||||
});
|
||||
const { handler } = await copyDependenciesToFunction(
|
||||
{
|
||||
entry,
|
||||
outDir: functionFolder,
|
||||
includeFiles: inc,
|
||||
excludeFiles: excludeFiles?.map((file) => new URL(file, _config.root)) || [],
|
||||
logger,
|
||||
},
|
||||
NTF_CACHE
|
||||
);
|
||||
|
||||
// Enable ESM
|
||||
// https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/
|
||||
|
@ -167,7 +184,7 @@ You can set functionPerRoute: false to prevent surpassing the limit.`
|
|||
}
|
||||
},
|
||||
|
||||
'astro:build:done': async ({ routes }) => {
|
||||
'astro:build:done': async ({ routes, logger }) => {
|
||||
// Merge any includes from `vite.assetsInclude
|
||||
if (_config.vite.assetsInclude) {
|
||||
const mergeGlobbedIncludes = (globPattern: unknown) => {
|
||||
|
@ -192,7 +209,7 @@ You can set functionPerRoute: false to prevent surpassing the limit.`
|
|||
if (_entryPoints.size) {
|
||||
for (const [route, entryFile] of _entryPoints) {
|
||||
const func = basename(entryFile.toString()).replace(/\.mjs$/, '');
|
||||
await createFunctionFolder(func, entryFile, filesToInclude);
|
||||
await createFunctionFolder(func, entryFile, filesToInclude, logger);
|
||||
routeDefinitions.push({
|
||||
src: route.pattern.source,
|
||||
dest: func,
|
||||
|
@ -202,7 +219,8 @@ You can set functionPerRoute: false to prevent surpassing the limit.`
|
|||
await createFunctionFolder(
|
||||
'render',
|
||||
new URL(serverEntry, buildTempFolder),
|
||||
filesToInclude
|
||||
filesToInclude,
|
||||
logger
|
||||
);
|
||||
routeDefinitions.push({ src: '/.*', dest: 'render' });
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue