mirror of
https://github.com/withastro/astro.git
synced 2025-01-27 22:19:04 -05:00
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 type { PathLike } from 'node:fs';
|
||||||
import * as fs from 'node:fs/promises';
|
import * as fs from 'node:fs/promises';
|
||||||
|
import { existsSync } from 'node:fs';
|
||||||
import nodePath from 'node:path';
|
import nodePath from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
@ -74,11 +75,13 @@ export async function copyFilesToFunction(
|
||||||
|
|
||||||
if (isSymlink) {
|
if (isSymlink) {
|
||||||
const realdest = fileURLToPath(new URL(nodePath.relative(commonAncestor, realpath), outDir));
|
const realdest = fileURLToPath(new URL(nodePath.relative(commonAncestor, realpath), outDir));
|
||||||
await fs.symlink(
|
const target = nodePath.relative(fileURLToPath(new URL('.', dest)), realdest);
|
||||||
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.
|
||||||
dest,
|
// So we check if the destination already exists. If it does, move on.
|
||||||
isDir ? 'dir' : 'file'
|
// 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) {
|
} else if (!isDir) {
|
||||||
await fs.copyFile(origin, dest);
|
await fs.copyFile(origin, dest);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,28 @@
|
||||||
import { relative as relativePath } from 'node:path';
|
import { relative as relativePath } from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { relative } from 'node:path';
|
||||||
import { copyFilesToFunction } from './fs.js';
|
import { copyFilesToFunction } from './fs.js';
|
||||||
|
import type { AstroIntegrationLogger } from 'astro';
|
||||||
|
|
||||||
export async function copyDependenciesToFunction({
|
export async function copyDependenciesToFunction(
|
||||||
entry,
|
{
|
||||||
outDir,
|
entry,
|
||||||
includeFiles,
|
outDir,
|
||||||
excludeFiles,
|
includeFiles,
|
||||||
}: {
|
excludeFiles,
|
||||||
entry: URL;
|
logger,
|
||||||
outDir: URL;
|
}: {
|
||||||
includeFiles: URL[];
|
entry: URL;
|
||||||
excludeFiles: URL[];
|
outDir: URL;
|
||||||
}): Promise<{ handler: string }> {
|
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);
|
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)
|
// Get root of folder of the system (like C:\ on Windows or / on Linux)
|
||||||
let base = entry;
|
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
|
// If you have a route of /dev this appears in source and NFT will try to
|
||||||
// scan your local /dev :8
|
// scan your local /dev :8
|
||||||
ignore: ['/dev/**'],
|
ignore: ['/dev/**'],
|
||||||
|
cache,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const error of result.warnings) {
|
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 { AstroError } from 'astro/errors';
|
||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import { basename } from 'node:path';
|
import { basename } from 'node:path';
|
||||||
|
@ -78,16 +84,27 @@ export default function vercelServerless({
|
||||||
// Extra files to be merged with `includeFiles` during build
|
// Extra files to be merged with `includeFiles` during build
|
||||||
const extraFilesToInclude: URL[] = [];
|
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);
|
const functionFolder = new URL(`./functions/${funcName}.func/`, _config.outDir);
|
||||||
|
|
||||||
// Copy necessary files (e.g. node_modules/)
|
// Copy necessary files (e.g. node_modules/)
|
||||||
const { handler } = await copyDependenciesToFunction({
|
const { handler } = await copyDependenciesToFunction(
|
||||||
entry,
|
{
|
||||||
outDir: functionFolder,
|
entry,
|
||||||
includeFiles: inc,
|
outDir: functionFolder,
|
||||||
excludeFiles: excludeFiles?.map((file) => new URL(file, _config.root)) || [],
|
includeFiles: inc,
|
||||||
});
|
excludeFiles: excludeFiles?.map((file) => new URL(file, _config.root)) || [],
|
||||||
|
logger,
|
||||||
|
},
|
||||||
|
NTF_CACHE
|
||||||
|
);
|
||||||
|
|
||||||
// Enable ESM
|
// Enable ESM
|
||||||
// https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/
|
// 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
|
// Merge any includes from `vite.assetsInclude
|
||||||
if (_config.vite.assetsInclude) {
|
if (_config.vite.assetsInclude) {
|
||||||
const mergeGlobbedIncludes = (globPattern: unknown) => {
|
const mergeGlobbedIncludes = (globPattern: unknown) => {
|
||||||
|
@ -192,7 +209,7 @@ You can set functionPerRoute: false to prevent surpassing the limit.`
|
||||||
if (_entryPoints.size) {
|
if (_entryPoints.size) {
|
||||||
for (const [route, entryFile] of _entryPoints) {
|
for (const [route, entryFile] of _entryPoints) {
|
||||||
const func = basename(entryFile.toString()).replace(/\.mjs$/, '');
|
const func = basename(entryFile.toString()).replace(/\.mjs$/, '');
|
||||||
await createFunctionFolder(func, entryFile, filesToInclude);
|
await createFunctionFolder(func, entryFile, filesToInclude, logger);
|
||||||
routeDefinitions.push({
|
routeDefinitions.push({
|
||||||
src: route.pattern.source,
|
src: route.pattern.source,
|
||||||
dest: func,
|
dest: func,
|
||||||
|
@ -202,7 +219,8 @@ You can set functionPerRoute: false to prevent surpassing the limit.`
|
||||||
await createFunctionFolder(
|
await createFunctionFolder(
|
||||||
'render',
|
'render',
|
||||||
new URL(serverEntry, buildTempFolder),
|
new URL(serverEntry, buildTempFolder),
|
||||||
filesToInclude
|
filesToInclude,
|
||||||
|
logger
|
||||||
);
|
);
|
||||||
routeDefinitions.push({ src: '/.*', dest: 'render' });
|
routeDefinitions.push({ src: '/.*', dest: 'render' });
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue