Compare commits
2 commits
main
...
new-adapte
Author | SHA1 | Date | |
---|---|---|---|
|
54c5900a24 | ||
|
ee5b66e298 |
30 changed files with 242 additions and 15114 deletions
5
.changeset/lucky-apes-yell.md
Normal file
5
.changeset/lucky-apes-yell.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Update "astro add" output to remove confusing multi-select prompt.
|
5
.changeset/perfect-drinks-fold.md
Normal file
5
.changeset/perfect-drinks-fold.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Update the help output to improve formatting
|
|
@ -1,4 +1,8 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import netlify from "@astrojs/netlify";
|
||||
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({});
|
||||
export default defineConfig({
|
||||
mode: "static",
|
||||
});
|
|
@ -41,6 +41,7 @@
|
|||
"./package.json": "./package.json",
|
||||
"./runtime/*": "./dist/runtime/*",
|
||||
"./server/*": "./dist/runtime/server/*",
|
||||
"./adapter-node/server.js": "./dist/adapter-node/server.js",
|
||||
"./vite-plugin-astro": "./dist/vite-plugin-astro/index.js",
|
||||
"./vite-plugin-astro/*": "./dist/vite-plugin-astro/*",
|
||||
"./vite-plugin-astro-postprocess": "./dist/vite-plugin-astro-postprocess/index.js",
|
||||
|
|
|
@ -78,7 +78,6 @@ export interface BuildConfig {
|
|||
client: URL;
|
||||
server: URL;
|
||||
serverEntry: string;
|
||||
staticMode: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -589,10 +588,15 @@ export interface AstroUserConfig {
|
|||
* @type {AstroIntegration}
|
||||
* @default `undefined`
|
||||
* @description
|
||||
* @deprecated
|
||||
* Add an adapter to build for SSR (server-side rendering). An adapter makes it easy to connect a deployed Astro app to a hosting provider or runtime environment.
|
||||
*/
|
||||
adapter?: AstroIntegration;
|
||||
|
||||
// TODO: Document
|
||||
mode?: 'static' | 'server';
|
||||
|
||||
|
||||
/**
|
||||
* @docs
|
||||
* @kind heading
|
||||
|
@ -720,7 +724,7 @@ export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
|
|||
// This is a more detailed type than zod validation gives us.
|
||||
// TypeScript still confirms zod validation matches this type.
|
||||
integrations: AstroIntegration[];
|
||||
adapter?: AstroIntegration;
|
||||
|
||||
// Private:
|
||||
// We have a need to pass context based on configured state,
|
||||
// that is different from the user-exposed configuration.
|
||||
|
|
9
packages/astro/src/adapter-node/index.ts
Normal file
9
packages/astro/src/adapter-node/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { AstroAdapter } from "../@types/astro";
|
||||
|
||||
export function getGenericNodeAdapter(): AstroAdapter {
|
||||
return {
|
||||
name: 'node',
|
||||
serverEntrypoint: 'astro/adapter-node/server.js',
|
||||
exports: ['handler'],
|
||||
};
|
||||
}
|
44
packages/astro/src/adapter-node/server.ts
Normal file
44
packages/astro/src/adapter-node/server.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { polyfill } from '@astrojs/webapi';
|
||||
import type { IncomingMessage, ServerResponse } from 'http';
|
||||
import type { Readable } from 'stream';
|
||||
import { SSRManifest } from '../@types/astro';
|
||||
import { NodeApp } from '../core/app/node';
|
||||
|
||||
polyfill(globalThis, {
|
||||
exclude: 'window document',
|
||||
});
|
||||
|
||||
export function createExports(manifest: SSRManifest) {
|
||||
const app = new NodeApp(manifest);
|
||||
return {
|
||||
async handler(req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) {
|
||||
const route = app.match(req);
|
||||
|
||||
if (route) {
|
||||
try {
|
||||
const response = await app.render(req);
|
||||
await writeWebResponse(res, response);
|
||||
} catch (err: unknown) {
|
||||
if (next) {
|
||||
next(err);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
} else if (next) {
|
||||
return next();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function writeWebResponse(res: ServerResponse, webResponse: Response) {
|
||||
const { status, headers, body } = webResponse;
|
||||
res.writeHead(status, Object.fromEntries(headers.entries()));
|
||||
if (body) {
|
||||
for await (const chunk of body as unknown as Readable) {
|
||||
res.write(chunk);
|
||||
}
|
||||
}
|
||||
res.end();
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import type { AstroAdapter, AstroIntegration } from '../@types/astro';
|
||||
|
||||
export function getAdapter(): AstroAdapter {
|
||||
return {
|
||||
name: '@astrojs/ssg',
|
||||
// This one has no server entrypoint and is mostly just an integration
|
||||
//serverEntrypoint: '@astrojs/ssg/server.js',
|
||||
};
|
||||
}
|
||||
|
||||
export default function createIntegration(): AstroIntegration {
|
||||
return {
|
||||
name: '@astrojs/ssg',
|
||||
hooks: {
|
||||
'astro:config:done': ({ setAdapter }) => {
|
||||
setAdapter(getAdapter());
|
||||
},
|
||||
'astro:build:start': ({ buildConfig }) => {
|
||||
buildConfig.staticMode = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -37,26 +37,27 @@ type CLICommand =
|
|||
function printAstroHelp() {
|
||||
printHelp({
|
||||
commandName: 'astro',
|
||||
usage: '[command] [...flags]',
|
||||
headline: 'Futuristic web development tool.',
|
||||
commands: [
|
||||
['add', 'Add an integration to your configuration.'],
|
||||
['docs', "Launch Astro's Doc site directly from the terminal. "],
|
||||
['dev', 'Run Astro in development mode.'],
|
||||
['build', 'Build a pre-compiled production-ready site.'],
|
||||
['preview', 'Preview your build locally before deploying.'],
|
||||
tables: {
|
||||
Commands: [
|
||||
['add', 'Add an integration.'],
|
||||
['build', 'Build your project and write it to disk.'],
|
||||
['check', 'Check your project for errors.'],
|
||||
['telemetry', 'Enable/disable anonymous data collection.'],
|
||||
['dev', 'Start the development server.'],
|
||||
['docs', "Open documentation in your web browser."],
|
||||
['preview', 'Preview your build locally.'],
|
||||
['telemetry', 'Configure telemetry settings.'],
|
||||
],
|
||||
'Global Flags': [
|
||||
['--config <path>', 'Specify your config file.'],
|
||||
['--root <path>', 'Specify your project root folder.'],
|
||||
['--verbose', 'Enable verbose logging.'],
|
||||
['--silent', 'Disable all logging.'],
|
||||
['--version', 'Show the version number and exit.'],
|
||||
['--help', 'Show this help message.'],
|
||||
],
|
||||
flags: [
|
||||
['--host [optional IP]', 'Expose server on network'],
|
||||
['--config <path>', 'Specify the path to the Astro config file.'],
|
||||
['--root <path>', 'Specify the path to the project root folder.'],
|
||||
['--drafts', 'Include markdown draft pages in the build.'],
|
||||
['--verbose', 'Enable verbose logging'],
|
||||
['--silent', 'Disable logging'],
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,14 @@ export async function update(subcommand: string, { flags, telemetry }: Telemetry
|
|||
if (flags.help || !isValid) {
|
||||
msg.printHelp({
|
||||
commandName: 'astro telemetry',
|
||||
usage: '<enable|disable|reset>',
|
||||
commands: [
|
||||
usage: '[command]',
|
||||
tables: {
|
||||
Commands: [
|
||||
['enable', 'Enable anonymous data collection.'],
|
||||
['disable', 'Disable anonymous data collection.'],
|
||||
['reset', 'Reset anonymous data collection settings.'],
|
||||
],
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
export const FIRST_PARTY_FRAMEWORKS = [
|
||||
{ value: 'react', title: 'React' },
|
||||
{ value: 'preact', title: 'Preact' },
|
||||
{ value: 'vue', title: 'Vue' },
|
||||
{ value: 'svelte', title: 'Svelte' },
|
||||
{ value: 'solid-js', title: 'Solid' },
|
||||
{ value: 'lit', title: 'Lit' },
|
||||
];
|
||||
export const FIRST_PARTY_ADDONS = [
|
||||
{ value: 'tailwind', title: 'Tailwind' },
|
||||
{ value: 'turbolinks', title: 'Turbolinks' },
|
||||
{ value: 'partytown', title: 'Partytown' },
|
||||
{ value: 'sitemap', title: 'Sitemap' },
|
||||
];
|
||||
export const ALIASES = new Map([
|
||||
['solid', 'solid-js'],
|
||||
['tailwindcss', 'tailwind'],
|
||||
]);
|
||||
export const CONFIG_STUB = `import { defineConfig } from 'astro/config';\n\nexport default defineConfig({});`;
|
||||
export const TAILWIND_CONFIG_STUB = `/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}\n`;
|
|
@ -11,14 +11,13 @@ import prompts from 'prompts';
|
|||
import { fileURLToPath, pathToFileURL } from 'url';
|
||||
import type yargs from 'yargs-parser';
|
||||
import { resolveConfigURL } from '../config.js';
|
||||
import { debug, error, info, LogOptions } from '../logger/core.js';
|
||||
import { debug, info, LogOptions } from '../logger/core.js';
|
||||
import * as msg from '../messages.js';
|
||||
import { printHelp } from '../messages.js';
|
||||
import { appendForwardSlash } from '../path.js';
|
||||
import { apply as applyPolyfill } from '../polyfill.js';
|
||||
import { parseNpmName } from '../util.js';
|
||||
import { generate, parse, t, visit } from './babel.js';
|
||||
import * as CONSTS from './consts.js';
|
||||
import { ensureImport } from './imports.js';
|
||||
import { wrapDefaultExport } from './wrapper.js';
|
||||
|
||||
|
@ -34,71 +33,77 @@ export interface IntegrationInfo {
|
|||
packageName: string;
|
||||
dependencies: [name: string, version: string][];
|
||||
}
|
||||
const ALIASES = new Map([
|
||||
['solid', 'solid-js'],
|
||||
['tailwindcss', 'tailwind'],
|
||||
]);
|
||||
const ASTRO_CONFIG_STUB = `import { defineConfig } from 'astro/config';\n\ndefault defineConfig({});`;
|
||||
const TAILWIND_CONFIG_STUB = `/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}\n`;
|
||||
|
||||
export default async function add(names: string[], { cwd, flags, logging, telemetry }: AddOptions) {
|
||||
if (flags.help) {
|
||||
if (flags.help || names.length === 0) {
|
||||
printHelp({
|
||||
commandName: 'astro add',
|
||||
usage: '[FLAGS] [INTEGRATIONS...]',
|
||||
flags: [
|
||||
['--yes', 'Add the integration without user interaction.'],
|
||||
usage: '[integration]',
|
||||
tables: {
|
||||
Flags: [
|
||||
['--yes', 'Accept all prompts.'],
|
||||
['--help', 'Show this help message.'],
|
||||
],
|
||||
'Recommended: UI Frameworks': [
|
||||
['react', 'astro add react'],
|
||||
['preact', 'astro add preact'],
|
||||
['vue', 'astro add vue'],
|
||||
['svelte', 'astro add svelte'],
|
||||
['solid-js', 'astro add solid-js'],
|
||||
['lit', 'astro add lit'],
|
||||
],
|
||||
'Recommended: Hosting': [
|
||||
['netlify', 'astro add netlify'],
|
||||
['vercel', 'astro add vercel'],
|
||||
['cloudflare', 'astro add cloudflare'],
|
||||
['deno', 'astro add deno'],
|
||||
],
|
||||
'Recommended: Integrations': [
|
||||
['tailwind', 'astro add tailwind'],
|
||||
['partytown', 'astro add partytown'],
|
||||
['sitemap', 'astro add sitemap'],
|
||||
],
|
||||
},
|
||||
description: `For more integrations, check out: ${cyan('https://astro.build/integrations')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
let configURL: URL | undefined;
|
||||
const root = pathToFileURL(cwd ? path.resolve(cwd) : process.cwd());
|
||||
// TODO: improve error handling for invalid configs
|
||||
configURL = await resolveConfigURL({ cwd, flags });
|
||||
|
||||
if (configURL?.pathname.endsWith('package.json')) {
|
||||
throw new Error(
|
||||
`Unable to use astro add with package.json#astro configuration! Try migrating to \`astro.config.mjs\` and try again.`
|
||||
);
|
||||
}
|
||||
applyPolyfill();
|
||||
|
||||
// If no integrations were given, prompt the user for some popular ones.
|
||||
if (names.length === 0) {
|
||||
const response = await prompts([
|
||||
{
|
||||
type: 'multiselect',
|
||||
name: 'frameworks',
|
||||
message: 'What frameworks would you like to enable?',
|
||||
instructions: '\n Space to select. Return to submit',
|
||||
choices: CONSTS.FIRST_PARTY_FRAMEWORKS,
|
||||
},
|
||||
{
|
||||
type: 'multiselect',
|
||||
name: 'addons',
|
||||
message: 'What additional integrations would you like to enable?',
|
||||
instructions: '\n Space to select. Return to submit',
|
||||
choices: CONSTS.FIRST_PARTY_ADDONS,
|
||||
},
|
||||
]);
|
||||
|
||||
names = [...(response.frameworks ?? []), ...(response.addons ?? [])];
|
||||
}
|
||||
|
||||
// If still empty after prompting, exit gracefully.
|
||||
if (names.length === 0) {
|
||||
error(logging, null, `No integrations specified.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Some packages might have a common alias! We normalize those here.
|
||||
names = names.map((name) => (CONSTS.ALIASES.has(name) ? CONSTS.ALIASES.get(name)! : name));
|
||||
|
||||
if (configURL) {
|
||||
debug('add', `Found config at ${configURL}`);
|
||||
} else {
|
||||
info(logging, 'add', `Unable to locate a config file, generating one for you.`);
|
||||
configURL = new URL('./astro.config.mjs', appendForwardSlash(root.href));
|
||||
await fs.writeFile(fileURLToPath(configURL), CONSTS.CONFIG_STUB, { encoding: 'utf-8' });
|
||||
await fs.writeFile(fileURLToPath(configURL), ASTRO_CONFIG_STUB, { encoding: 'utf-8' });
|
||||
}
|
||||
|
||||
const integrations = await validateIntegrations(names);
|
||||
// TODO: improve error handling for invalid configs
|
||||
if (configURL?.pathname.endsWith('package.json')) {
|
||||
throw new Error(
|
||||
`Unable to use "astro add" with package.json configuration. Try migrating to \`astro.config.mjs\` and try again.`
|
||||
);
|
||||
}
|
||||
|
||||
// Some packages might have a common alias! We normalize those here.
|
||||
const integrationNames = names.map((name) => (ALIASES.has(name) ? ALIASES.get(name)! : name));
|
||||
const integrations = await validateIntegrations(integrationNames);
|
||||
|
||||
let ast: t.File | null = null;
|
||||
try {
|
||||
|
@ -194,7 +199,7 @@ export default async function add(names: string[], { cwd, flags, logging, teleme
|
|||
if (await askToContinue({ flags })) {
|
||||
await fs.writeFile(
|
||||
fileURLToPath(new URL('./tailwind.config.cjs', configURL)),
|
||||
CONSTS.TAILWIND_CONFIG_STUB,
|
||||
TAILWIND_CONFIG_STUB,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
debug('add', `Generated default ./tailwind.config.cjs file`);
|
||||
|
|
|
@ -18,7 +18,7 @@ import { debug, info } from '../logger/core.js';
|
|||
import { render } from '../render/core.js';
|
||||
import { createLinkStylesheetElementSet, createModuleScriptsSet } from '../render/ssr-element.js';
|
||||
import { createRequest } from '../request.js';
|
||||
import { getOutputFilename, isBuildingToSSR } from '../util.js';
|
||||
import { getOutputFilename } from '../util.js';
|
||||
import { getOutFile, getOutFolder } from './common.js';
|
||||
import { eachPageData, getPageDataByComponent } from './internal.js';
|
||||
import type { PageBuildData, SingleFileBuiltModule, StaticBuildOptions } from './types';
|
||||
|
@ -97,7 +97,7 @@ export async function generatePages(
|
|||
const timer = performance.now();
|
||||
info(opts.logging, null, `\n${bgGreen(black(' generating static routes '))}`);
|
||||
|
||||
const ssr = isBuildingToSSR(opts.astroConfig);
|
||||
const ssr = opts.astroConfig.mode === 'server';
|
||||
const serverEntry = opts.buildConfig.serverEntry;
|
||||
const outFolder = ssr ? opts.buildConfig.server : opts.astroConfig.outDir;
|
||||
const ssrEntryURL = new URL('./' + serverEntry + `?time=${Date.now()}`, outFolder);
|
||||
|
@ -207,7 +207,7 @@ async function generatePath(
|
|||
}
|
||||
}
|
||||
|
||||
const ssr = isBuildingToSSR(opts.astroConfig);
|
||||
const ssr = opts.astroConfig.mode === 'server';
|
||||
const url = new URL(opts.astroConfig.base + removeLeadingForwardSlash(pathname), origin);
|
||||
const options: RenderOptions = {
|
||||
links,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { AstroTelemetry } from '@astrojs/telemetry';
|
||||
import type { AstroConfig, BuildConfig, ManifestData } from '../../@types/astro';
|
||||
import type { AstroAdapter, AstroConfig, BuildConfig, ManifestData } from '../../@types/astro';
|
||||
import type { LogOptions } from '../logger/core';
|
||||
|
||||
import fs from 'fs';
|
||||
|
@ -14,11 +14,11 @@ import {
|
|||
} from '../../integrations/index.js';
|
||||
import { createVite, ViteConfigWithSSR } from '../create-vite.js';
|
||||
import { fixViteErrorMessage } from '../errors.js';
|
||||
import { debug, info, levels, timerMessage, warnIfUsingExperimentalSSR } from '../logger/core.js';
|
||||
import { debug, info, levels, timerMessage } from '../logger/core.js';
|
||||
import { apply as applyPolyfill } from '../polyfill.js';
|
||||
import { RouteCache } from '../render/route-cache.js';
|
||||
import { createRouteManifest } from '../routing/index.js';
|
||||
import { createSafeError, isBuildingToSSR } from '../util.js';
|
||||
import { createSafeError } from '../util.js';
|
||||
import { collectPagesData } from './page-data.js';
|
||||
import { staticBuild } from './static-build.js';
|
||||
import { getTimeStat } from './util.js';
|
||||
|
@ -79,7 +79,6 @@ class AstroBuilder {
|
|||
{ astroConfig: this.config, logging, mode: 'build' }
|
||||
);
|
||||
await runHookConfigDone({ config: this.config });
|
||||
warnIfUsingExperimentalSSR(logging, this.config);
|
||||
const viteServer = await vite.createServer(viteConfig);
|
||||
debug('build', timerMessage('Vite started', this.timer.viteStart));
|
||||
return { viteConfig, viteServer };
|
||||
|
@ -98,11 +97,21 @@ class AstroBuilder {
|
|||
client: new URL('./client/', this.config.outDir),
|
||||
server: new URL('./server/', this.config.outDir),
|
||||
serverEntry: 'entry.mjs',
|
||||
staticMode: undefined,
|
||||
};
|
||||
await runHookBuildStart({ config: this.config, buildConfig });
|
||||
|
||||
info(this.logging, 'build', 'Collecting build information...');
|
||||
const getPrettyDeployTarget = (adapter: AstroAdapter | undefined) => {
|
||||
if (adapter?.name === 'node') {
|
||||
return 'node.js (generic)';
|
||||
}
|
||||
if (adapter?.name) {
|
||||
return adapter?.name;
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
info(this.logging, 'build', `build target: ${colors.green(this.config.mode)}`);
|
||||
info(this.logging, 'build', `deploy target: ${colors.green(getPrettyDeployTarget(this.config._ctx.adapter))}`);
|
||||
info(this.logging, 'build', 'Collecting build info...');
|
||||
this.timer.loadStart = performance.now();
|
||||
const { assets, allPages } = await collectPagesData({
|
||||
astroConfig: this.config,
|
||||
|
@ -111,7 +120,7 @@ class AstroBuilder {
|
|||
origin,
|
||||
routeCache: this.routeCache,
|
||||
viteServer,
|
||||
ssr: isBuildingToSSR(this.config),
|
||||
ssr: this.config.mode === 'server',
|
||||
});
|
||||
|
||||
debug('build', timerMessage('All pages loaded', this.timer.loadStart));
|
||||
|
@ -161,12 +170,11 @@ class AstroBuilder {
|
|||
});
|
||||
|
||||
if (this.logging.level && levels[this.logging.level] <= levels['info']) {
|
||||
const buildMode = isBuildingToSSR(this.config) ? 'ssr' : 'static';
|
||||
await this.printStats({
|
||||
logging: this.logging,
|
||||
timeStart: this.timer.init,
|
||||
pageCount: pageNames.length,
|
||||
buildMode,
|
||||
buildMode: this.config.mode,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +199,7 @@ class AstroBuilder {
|
|||
logging: LogOptions;
|
||||
timeStart: number;
|
||||
pageCount: number;
|
||||
buildMode: 'static' | 'ssr';
|
||||
buildMode: 'static' | 'server';
|
||||
}) {
|
||||
const total = getTimeStat(timeStart, performance.now());
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import { debug } from '../logger/core.js';
|
|||
import { removeTrailingForwardSlash } from '../path.js';
|
||||
import { callGetStaticPaths, RouteCache, RouteCacheEntry } from '../render/route-cache.js';
|
||||
import { matchRoute } from '../routing/match.js';
|
||||
import { isBuildingToSSR } from '../util.js';
|
||||
|
||||
export interface CollectPagesDataOptions {
|
||||
astroConfig: AstroConfig;
|
||||
|
@ -36,9 +35,6 @@ export async function collectPagesData(
|
|||
const assets: Record<string, string> = {};
|
||||
const allPages: AllPagesData = {};
|
||||
const builtPaths = new Set<string>();
|
||||
|
||||
const buildMode = isBuildingToSSR(astroConfig) ? 'ssr' : 'static';
|
||||
|
||||
const dataCollectionLogTimeout = setInterval(() => {
|
||||
info(opts.logging, 'build', 'The data collection step may take longer for larger projects...');
|
||||
clearInterval(dataCollectionLogTimeout);
|
||||
|
@ -72,7 +68,7 @@ export async function collectPagesData(
|
|||
};
|
||||
|
||||
clearInterval(routeCollectionLogTimeout);
|
||||
if (buildMode === 'static') {
|
||||
if (astroConfig.mode === 'static') {
|
||||
const html = `${route.pathname}`.replace(/\/?$/, '/index.html');
|
||||
debug(
|
||||
'build',
|
||||
|
|
|
@ -11,7 +11,6 @@ import { runHookBuildSetup } from '../../integrations/index.js';
|
|||
import { rollupPluginAstroBuildCSS } from '../../vite-plugin-build-css/index.js';
|
||||
import type { ViteConfigWithSSR } from '../create-vite';
|
||||
import { info } from '../logger/core.js';
|
||||
import { isBuildingToSSR } from '../util.js';
|
||||
import { generatePages } from './generate.js';
|
||||
import { trackPageData } from './internal.js';
|
||||
import type { PageBuildData, StaticBuildOptions } from './types';
|
||||
|
@ -60,9 +59,7 @@ export async function staticBuild(opts: StaticBuildOptions) {
|
|||
info(
|
||||
opts.logging,
|
||||
'build',
|
||||
isBuildingToSSR(astroConfig)
|
||||
? 'Building SSR entrypoints...'
|
||||
: 'Building entrypoints for prerendering...'
|
||||
`Building ${astroConfig.mode} entrypoints...`
|
||||
);
|
||||
const ssrResult = (await ssrBuild(opts, internals, pageInput)) as RollupOutput;
|
||||
info(opts.logging, 'build', dim(`Completed in ${getTimeStat(timer.ssr, performance.now())}.`));
|
||||
|
@ -79,7 +76,7 @@ export async function staticBuild(opts: StaticBuildOptions) {
|
|||
await clientBuild(opts, internals, clientInput);
|
||||
|
||||
timer.generate = performance.now();
|
||||
if (opts.buildConfig.staticMode) {
|
||||
if (astroConfig.mode === 'static') {
|
||||
try {
|
||||
await generatePages(ssrResult, opts, internals, facadeIdToPageDataMap);
|
||||
} finally {
|
||||
|
@ -96,7 +93,7 @@ export async function staticBuild(opts: StaticBuildOptions) {
|
|||
|
||||
async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, input: Set<string>) {
|
||||
const { astroConfig, viteConfig } = opts;
|
||||
const ssr = isBuildingToSSR(astroConfig);
|
||||
const ssr = astroConfig.mode === 'server';
|
||||
const out = ssr ? opts.buildConfig.server : astroConfig.outDir;
|
||||
|
||||
const viteBuildConfig: ViteConfigWithSSR = {
|
||||
|
@ -140,7 +137,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
|
|||
}),
|
||||
...(viteConfig.plugins || []),
|
||||
// SSR needs to be last
|
||||
isBuildingToSSR(opts.astroConfig) &&
|
||||
opts.astroConfig.mode === 'server' &&
|
||||
vitePluginSSR(opts, internals, opts.astroConfig._ctx.adapter!),
|
||||
vitePluginAnalyzer(opts.astroConfig, internals),
|
||||
],
|
||||
|
@ -171,7 +168,7 @@ async function clientBuild(
|
|||
) {
|
||||
const { astroConfig, viteConfig } = opts;
|
||||
const timer = performance.now();
|
||||
const ssr = isBuildingToSSR(astroConfig);
|
||||
const ssr = astroConfig.mode === 'server';
|
||||
const out = ssr ? opts.buildConfig.client : astroConfig.outDir;
|
||||
|
||||
// Nothing to do if there is no client-side JS.
|
||||
|
@ -272,7 +269,7 @@ async function copyFiles(fromFolder: URL, toFolder: URL) {
|
|||
|
||||
async function ssrMoveAssets(opts: StaticBuildOptions) {
|
||||
info(opts.logging, 'build', 'Rearranging server assets...');
|
||||
const serverRoot = opts.buildConfig.staticMode
|
||||
const serverRoot = opts.astroConfig.mode === 'static'
|
||||
? opts.buildConfig.client
|
||||
: opts.buildConfig.server;
|
||||
const clientRoot = opts.buildConfig.client;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { Plugin as VitePlugin } from 'vite';
|
||||
import { pagesVirtualModuleId, resolvedPagesVirtualModuleId } from '../app/index.js';
|
||||
import { isBuildingToSSR } from '../util.js';
|
||||
import { addRollupInput } from './add-rollup-input.js';
|
||||
import type { BuildInternals } from './internal.js';
|
||||
import { eachPageData } from './internal.js';
|
||||
|
@ -11,7 +10,7 @@ export function vitePluginPages(opts: StaticBuildOptions, internals: BuildIntern
|
|||
name: '@astro/plugin-build-pages',
|
||||
|
||||
options(options) {
|
||||
if (!isBuildingToSSR(opts.astroConfig)) {
|
||||
if (opts.astroConfig.mode === 'static') {
|
||||
return addRollupInput(options, [pagesVirtualModuleId]);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -93,7 +93,6 @@ export const LEGACY_ASTRO_CONFIG_KEYS = new Set([
|
|||
]);
|
||||
|
||||
export const AstroConfigSchema = z.object({
|
||||
adapter: z.object({ name: z.string(), hooks: z.object({}).passthrough().default({}) }).optional(),
|
||||
root: z
|
||||
.string()
|
||||
.optional()
|
||||
|
@ -132,6 +131,10 @@ export const AstroConfigSchema = z.object({
|
|||
.union([z.literal('always'), z.literal('never'), z.literal('ignore')])
|
||||
.optional()
|
||||
.default(ASTRO_CONFIG_DEFAULTS.trailingSlash),
|
||||
mode: z
|
||||
.union([z.literal('static'), z.literal('server')])
|
||||
.optional()
|
||||
.default('static'),
|
||||
build: z
|
||||
.object({
|
||||
format: z
|
||||
|
@ -227,6 +230,9 @@ export const AstroConfigSchema = z.object({
|
|||
})
|
||||
.optional()
|
||||
.default({}),
|
||||
// Deprecated:
|
||||
adapter: z.object({ name: z.string(), hooks: z.object({}).passthrough().default({}) }).optional(),
|
||||
|
||||
});
|
||||
|
||||
/** Turn raw config values into normalized values */
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
runHookServerStart,
|
||||
} from '../../integrations/index.js';
|
||||
import { createVite } from '../create-vite.js';
|
||||
import { info, LogOptions, warn, warnIfUsingExperimentalSSR } from '../logger/core.js';
|
||||
import { info, LogOptions, warn } from '../logger/core.js';
|
||||
import * as msg from '../messages.js';
|
||||
import { apply as applyPolyfill } from '../polyfill.js';
|
||||
|
||||
|
@ -58,7 +58,6 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
|
|||
{ astroConfig: config, logging: options.logging, mode: 'dev' }
|
||||
);
|
||||
await runHookConfigDone({ config });
|
||||
warnIfUsingExperimentalSSR(options.logging, config);
|
||||
const viteServer = await vite.createServer(viteConfig);
|
||||
runHookServerSetup({ config, server: viteServer });
|
||||
await viteServer.listen(port);
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import type { EndpointHandler } from '../../../@types/astro';
|
||||
import type { SSROptions } from '../../render/dev';
|
||||
import { preload } from '../../render/dev/index.js';
|
||||
import { isBuildingToSSR } from '../../util.js';
|
||||
import { call as callEndpoint } from '../index.js';
|
||||
|
||||
export async function call(ssrOpts: SSROptions) {
|
||||
const [, mod] = await preload(ssrOpts);
|
||||
return await callEndpoint(mod as unknown as EndpointHandler, {
|
||||
...ssrOpts,
|
||||
ssr: isBuildingToSSR(ssrOpts.astroConfig),
|
||||
ssr: ssrOpts.astroConfig.mode === 'server',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -128,16 +128,3 @@ export function timerMessage(message: string, startTime: number = Date.now()) {
|
|||
return `${message} ${dim(timeDisplay)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* A warning that SSR is experimental. Remove when we can.
|
||||
*/
|
||||
export function warnIfUsingExperimentalSSR(opts: LogOptions, config: AstroConfig) {
|
||||
if (config._ctx.adapter?.serverEntrypoint) {
|
||||
warn(
|
||||
opts,
|
||||
'warning',
|
||||
bold(`Warning:`),
|
||||
`SSR support is still experimental and subject to API changes. If using in production, pin your dependencies to prevent accidental breakage.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@ export const logger = {
|
|||
|
||||
export function enableVerboseLogging() {
|
||||
//debugPackage.enable('*,-babel');
|
||||
console.log('ah!');
|
||||
debug('cli', '--verbose flag enabled! Enabling: DEBUG="*,-babel"');
|
||||
debug(
|
||||
'cli',
|
||||
|
|
|
@ -248,28 +248,27 @@ export function printHelp({
|
|||
commandName,
|
||||
headline,
|
||||
usage,
|
||||
commands,
|
||||
flags,
|
||||
tables,
|
||||
description,
|
||||
}: {
|
||||
commandName: string;
|
||||
headline?: string;
|
||||
usage?: string;
|
||||
commands?: [command: string, help: string][];
|
||||
flags?: [flag: string, help: string][];
|
||||
tables?: Record<string, [command: string, help: string][]>;
|
||||
description?: string,
|
||||
}) {
|
||||
const linebreak = () => '';
|
||||
const title = (label: string) => ` ${bgWhite(black(` ${label} `))}`;
|
||||
const table = (rows: [string, string][], opts: { padding: number; prefix: string }) => {
|
||||
const split = rows.some((row) => {
|
||||
const message = `${opts.prefix}${' '.repeat(opts.padding)}${row[1]}`;
|
||||
return message.length > process.stdout.columns;
|
||||
});
|
||||
|
||||
const table = (rows: [string, string][], { padding }: { padding: number }) => {
|
||||
const split = process.stdout.columns < 60;
|
||||
let raw = '';
|
||||
|
||||
for (const row of rows) {
|
||||
raw += `${opts.prefix}${bold(`${row[0]}`.padStart(opts.padding - opts.prefix.length))}`;
|
||||
if (split) raw += '\n ';
|
||||
if (split) {
|
||||
raw += ` ${row[0]}\n `;
|
||||
} else {
|
||||
raw += `${(`${row[0]}`.padStart(padding))}`;
|
||||
}
|
||||
raw += ' ' + dim(row[1]) + '\n';
|
||||
}
|
||||
|
||||
|
@ -291,18 +290,21 @@ export function printHelp({
|
|||
message.push(linebreak(), ` ${green(commandName)} ${bold(usage)}`);
|
||||
}
|
||||
|
||||
if (commands) {
|
||||
message.push(
|
||||
linebreak(),
|
||||
title('Commands'),
|
||||
table(commands, { padding: 28, prefix: ` ${commandName || 'astro'} ` })
|
||||
);
|
||||
if (tables) {
|
||||
function calculateTablePadding(rows: [string, string][]) {
|
||||
return rows.reduce((val, [first]) => Math.max(val, first.length), 0) + 2;
|
||||
};
|
||||
const tableEntries = Object.entries(tables);
|
||||
const padding = Math.max(...tableEntries.map(([, rows]) => calculateTablePadding(rows)));
|
||||
for (const [tableTitle, tableRows] of tableEntries) {
|
||||
message.push(linebreak(), title(tableTitle), table(tableRows, { padding }));
|
||||
}
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
message.push(linebreak(), title('Flags'), table(flags, { padding: 28, prefix: ' ' }));
|
||||
if (description) {
|
||||
message.push(linebreak(), `${description}`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(message.join('\n'));
|
||||
console.log(message.join('\n') + '\n');
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import type {
|
|||
} from '../../../@types/astro';
|
||||
import { prependForwardSlash } from '../../../core/path.js';
|
||||
import { LogOptions } from '../../logger/core.js';
|
||||
import { isBuildingToSSR } from '../../util.js';
|
||||
import { render as coreRender } from '../core.js';
|
||||
import { RouteCache } from '../route-cache.js';
|
||||
import { createModuleScriptElementWithSrcSet } from '../ssr-element.js';
|
||||
|
@ -183,7 +182,7 @@ export async function render(
|
|||
route,
|
||||
routeCache,
|
||||
site: astroConfig.site ? new URL(astroConfig.base, astroConfig.site).toString() : undefined,
|
||||
ssr: isBuildingToSSR(astroConfig),
|
||||
ssr: astroConfig.mode === 'server',
|
||||
});
|
||||
|
||||
return response;
|
||||
|
|
|
@ -62,7 +62,7 @@ export function createRequest({
|
|||
warn(
|
||||
logging,
|
||||
'ssg',
|
||||
`Headers are not exposed in static-site generation (SSG) mode. To enable reading headers you need to set an SSR adapter in your config.`
|
||||
`Headers are not exposed in static-site generation (SSG) mode. To enable reading headers: set \`mode: "server"\` in your config file.`
|
||||
);
|
||||
return _headers;
|
||||
},
|
||||
|
|
|
@ -7,12 +7,11 @@ import {
|
|||
BuildConfig,
|
||||
RouteData,
|
||||
} from '../@types/astro.js';
|
||||
import ssgAdapter from '../adapter-ssg/index.js';
|
||||
import { getGenericNodeAdapter } from '../adapter-node/index.js';
|
||||
import type { SerializedSSRManifest } from '../core/app/types';
|
||||
import type { PageBuildData } from '../core/build/types';
|
||||
import { mergeConfig } from '../core/config.js';
|
||||
import type { ViteConfigWithSSR } from '../core/create-vite.js';
|
||||
import { isBuildingToSSR } from '../core/util.js';
|
||||
|
||||
type Hooks<
|
||||
Hook extends keyof AstroIntegration['hooks'],
|
||||
|
@ -26,9 +25,10 @@ export async function runHookConfigSetup({
|
|||
config: AstroConfig;
|
||||
command: 'dev' | 'build';
|
||||
}): Promise<AstroConfig> {
|
||||
if (_config.adapter) {
|
||||
_config.integrations.push(_config.adapter);
|
||||
}
|
||||
// DEPRECATED
|
||||
// if (_config.adapter) {
|
||||
// _config.integrations.push(_config.adapter);
|
||||
// }
|
||||
|
||||
let updatedConfig: AstroConfig = { ..._config };
|
||||
for (const integration of _config.integrations) {
|
||||
|
@ -86,7 +86,7 @@ export async function runHookConfigDone({ config }: { config: AstroConfig }) {
|
|||
setAdapter(adapter) {
|
||||
if (config._ctx.adapter && config._ctx.adapter.name !== adapter.name) {
|
||||
throw new Error(
|
||||
`Adapter already set to ${config._ctx.adapter.name}. You can only have one adapter.`
|
||||
`Integration "${integration.name}" conflicts with "${config._ctx.adapter.name}". You can only configure one deployment integration.`
|
||||
);
|
||||
}
|
||||
config._ctx.adapter = adapter;
|
||||
|
@ -95,17 +95,8 @@ export async function runHookConfigDone({ config }: { config: AstroConfig }) {
|
|||
}
|
||||
}
|
||||
// Call the default adapter
|
||||
if (!config._ctx.adapter) {
|
||||
const integration = ssgAdapter();
|
||||
config.integrations.push(integration);
|
||||
if (integration?.hooks?.['astro:config:done']) {
|
||||
await integration.hooks['astro:config:done']({
|
||||
config,
|
||||
setAdapter(adapter) {
|
||||
config._ctx.adapter = adapter;
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!config._ctx.adapter && config.mode === 'server') {
|
||||
config._ctx.adapter = getGenericNodeAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +200,7 @@ export async function runHookBuildDone({
|
|||
pages: string[];
|
||||
routes: RouteData[];
|
||||
}) {
|
||||
const dir = isBuildingToSSR(config) ? buildConfig.client : config.outDir;
|
||||
const dir = config.mode === 'server' ? buildConfig.client : config.outDir;
|
||||
|
||||
for (const integration of config.integrations) {
|
||||
if (integration?.hooks?.['astro:build:done']) {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { preload, ssr } from '../core/render/dev/index.js';
|
|||
import { RouteCache } from '../core/render/route-cache.js';
|
||||
import { createRequest } from '../core/request.js';
|
||||
import { createRouteManifest, matchRoute } from '../core/routing/index.js';
|
||||
import { createSafeError, isBuildingToSSR, resolvePages } from '../core/util.js';
|
||||
import { createSafeError, resolvePages } from '../core/util.js';
|
||||
import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js';
|
||||
import serverErrorTemplate from '../template/5xx.js';
|
||||
|
||||
|
@ -188,7 +188,7 @@ async function handleRequest(
|
|||
const site = config.site ? new URL(config.base, config.site) : undefined;
|
||||
const devRoot = site ? site.pathname : '/';
|
||||
const origin = `${viteServer.config.server.https ? 'https' : 'http'}://${req.headers.host}`;
|
||||
const buildingToSSR = isBuildingToSSR(config);
|
||||
const buildingToSSR = config.mode === 'server';
|
||||
// Ignore `.html` extensions and `index.html` in request URLS to ensure that
|
||||
// routing behavior matches production builds. This supports both file and directory
|
||||
// build formats, and is necessary based on how the manifest tracks build targets.
|
||||
|
@ -257,7 +257,7 @@ async function handleRequest(
|
|||
routeCache,
|
||||
pathname: rootRelativeUrl,
|
||||
logging,
|
||||
ssr: isBuildingToSSR(config),
|
||||
ssr: config.mode === 'server',
|
||||
});
|
||||
if (paramsAndPropsRes === GetParamsAndPropsError.NoMatchingStaticPath) {
|
||||
warn(
|
||||
|
|
|
@ -30,8 +30,6 @@ export default function vercelStatic(): AstroIntegration {
|
|||
);
|
||||
}
|
||||
|
||||
buildConfig.staticMode = true;
|
||||
|
||||
// Ensure to have `.vercel/output` empty.
|
||||
// This is because, when building to static, outDir = .vercel/output/static/,
|
||||
// so .vercel/output itself won't get cleaned.
|
||||
|
|
2
packages/webapi/mod.d.ts
vendored
2
packages/webapi/mod.d.ts
vendored
|
@ -1,5 +1,5 @@
|
|||
export { pathToPosix } from './lib/utils';
|
||||
export { AbortController, AbortSignal, alert, atob, Blob, btoa, ByteLengthQueuingStrategy, cancelAnimationFrame, cancelIdleCallback, CanvasRenderingContext2D, CharacterData, clearTimeout, Comment, CountQueuingStrategy, CSSStyleSheet, CustomElementRegistry, CustomEvent, Document, DocumentFragment, DOMException, Element, Event, EventTarget, fetch, File, FormData, Headers, HTMLBodyElement, HTMLCanvasElement, HTMLDivElement, HTMLDocument, HTMLElement, HTMLHeadElement, HTMLHtmlElement, HTMLImageElement, HTMLSpanElement, HTMLStyleElement, HTMLTemplateElement, HTMLUnknownElement, Image, ImageData, IntersectionObserver, MediaQueryList, MutationObserver, Node, NodeFilter, NodeIterator, OffscreenCanvas, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, Request, requestAnimationFrame, requestIdleCallback, ResizeObserver, Response, setTimeout, ShadowRoot, structuredClone, StyleSheet, Text, TransformStream, TreeWalker, URLPattern, Window, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter } from './mod.js';
|
||||
export { AbortController, AbortSignal, alert, atob, Blob, btoa, ByteLengthQueuingStrategy, cancelAnimationFrame, cancelIdleCallback, CanvasRenderingContext2D, CharacterData, clearTimeout, Comment, CountQueuingStrategy, CSSStyleSheet, CustomElementRegistry, CustomEvent, Document, DocumentFragment, DOMException, Element, Event, EventTarget, fetch, File, FormData, Headers, HTMLBodyElement, HTMLCanvasElement, HTMLDivElement, HTMLDocument, HTMLElement, HTMLHeadElement, HTMLHtmlElement, HTMLImageElement, HTMLSpanElement, HTMLStyleElement, HTMLTemplateElement, HTMLUnknownElement, Image, ImageData, IntersectionObserver, MediaQueryList, MutationObserver, Node, NodeFilter, NodeIterator, OffscreenCanvas, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, Request, requestAnimationFrame, requestIdleCallback, ResizeObserver, Response, setTimeout, ShadowRoot, structuredClone, StyleSheet, Text, TransformStream, TreeWalker, URLPattern, Window, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter, } from './mod.js';
|
||||
export declare const polyfill: {
|
||||
(target: any, options?: PolyfillOptions): any;
|
||||
internals(target: any, name: string): any;
|
||||
|
|
14890
pnpm-lock.yaml
14890
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue