Skip to content

Commit

Permalink
fix(container): breakdown files to avoid importing vite (#11327)
Browse files Browse the repository at this point in the history
* fix(container): breakdown files to avoid importing `vite`

* chore: update imports inside tests

* restore code

* format
  • Loading branch information
ematipico authored Jun 26, 2024
1 parent d9e6190 commit 0df8142
Show file tree
Hide file tree
Showing 18 changed files with 126 additions and 120 deletions.
5 changes: 5 additions & 0 deletions .changeset/happy-boxes-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes an issue with the container APIs where a runtime error was thrown during the build, when using `pnpm` as package manager.
8 changes: 4 additions & 4 deletions packages/astro/src/container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import type {
SSRManifest,
SSRResult,
} from '../@types/astro.js';
import { validateConfig } from '../core/config/config.js';
import { ASTRO_CONFIG_DEFAULTS } from '../core/config/schema.js';
import { validateConfig } from '../core/config/validate.js';
import { Logger } from '../core/logger/core.js';
import { nodeLogDestination } from '../core/logger/node.js';
import { removeLeadingForwardSlash } from '../core/path.js';
Expand Down Expand Up @@ -208,7 +208,7 @@ type AstroContainerConstructor = {
renderers?: SSRLoadedRenderer[];
manifest?: AstroContainerManifest;
resolve?: SSRResult['resolve'];
astroConfig: AstroConfig;
astroConfig?: AstroConfig;
};

export class experimental_AstroContainer {
Expand Down Expand Up @@ -253,10 +253,10 @@ export class experimental_AstroContainer {
});
}

async #containerResolve(specifier: string, astroConfig: AstroConfig): Promise<string> {
async #containerResolve(specifier: string, astroConfig?: AstroConfig): Promise<string> {
const found = this.#pipeline.manifest.entryModules[specifier];
if (found) {
return new URL(found, astroConfig.build.client).toString();
return new URL(found, astroConfig?.build.client).toString();
}
return found;
}
Expand Down
3 changes: 0 additions & 3 deletions packages/astro/src/container/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@ import type {
} from '../@types/astro.js';
import { type HeadElements, Pipeline } from '../core/base-pipeline.js';
import type { SinglePageBuiltModule } from '../core/build/types.js';
import { RouteNotFound } from '../core/errors/errors-data.js';
import { AstroError } from '../core/errors/index.js';
import {
createModuleScriptElement,
createStylesheetElementSet,
} from '../core/render/ssr-element.js';
import { DEFAULT_404_ROUTE } from '../core/routing/astro-designed-error-pages.js';
import { findRouteToRewrite } from '../core/routing/rewrite.js';

export class ContainerPipeline extends Pipeline {
Expand Down
5 changes: 3 additions & 2 deletions packages/astro/src/content/vite-plugin-content-virtual-mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { extname } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import glob from 'fast-glob';
import pLimit from 'p-limit';
import { type Plugin } from 'vite';
import type { Plugin } from 'vite';
import type { AstroSettings } from '../@types/astro.js';
import { encodeName } from '../core/build/util.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { appendForwardSlash, removeFileExtension } from '../core/path.js';
import { isServerLikeOutput, rootRelativePath } from '../core/util.js';
import { isServerLikeOutput } from '../core/util.js';
import { rootRelativePath } from '../core/viteUtils.js';
import type { AstroPluginMetadata } from '../vite-plugin-astro/index.js';
import {
CONTENT_FLAG,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/plugins/plugin-manifest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fileURLToPath } from 'node:url';
import glob from 'fast-glob';
import type { OutputChunk } from 'rollup';
import { type Plugin as VitePlugin } from 'vite';
import type { Plugin as VitePlugin } from 'vite';
import { getAssetsPrefix } from '../../../assets/utils/getAssetsPrefix.js';
import { normalizeTheLocale } from '../../../i18n/index.js';
import { toRoutingStrategy } from '../../../i18n/utils.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/compile/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { AstroPreferences } from '../../preferences/index.js';
import type { AstroError } from '../errors/errors.js';
import { AggregateError, CompilerError } from '../errors/errors.js';
import { AstroErrorData } from '../errors/index.js';
import { resolvePath } from '../util.js';
import { resolvePath } from '../viteUtils.js';
import { type PartialCompileCssResult, createStylePreprocessor } from './style.js';
import type { CompileCssResult } from './types.js';

Expand Down
59 changes: 22 additions & 37 deletions packages/astro/src/core/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,24 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as colors from 'kleur/colors';
import type { Arguments as Flags } from 'yargs-parser';
import { ZodError } from 'zod';
import type {
AstroConfig,
AstroInlineConfig,
AstroInlineOnlyConfig,
AstroUserConfig,
CLIFlags,
} from '../../@types/astro.js';

import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as colors from 'kleur/colors';
import { ZodError } from 'zod';
import { eventConfigError, telemetry } from '../../events/index.js';
import { trackAstroConfigZodError } from '../errors/errors.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
import { formatConfigErrorMessage } from '../messages.js';
import { mergeConfig } from './merge.js';
import { createRelativeSchema } from './schema.js';
import { validateConfig } from './validate.js';
import { loadConfigWithVite } from './vite-load.js';

/** Turn raw config values into normalized values */
export async function validateConfig(
userConfig: any,
root: string,
cmd: string
): Promise<AstroConfig> {
const AstroConfigRelativeSchema = createRelativeSchema(cmd, root);

// First-Pass Validation
let result: AstroConfig;
try {
result = await AstroConfigRelativeSchema.parseAsync(userConfig);
} catch (e) {
// Improve config zod error messages
if (e instanceof ZodError) {
// Mark this error so the callee can decide to suppress Zod's error if needed.
// We still want to throw the error to signal an error in validation.
trackAstroConfigZodError(e);
// eslint-disable-next-line no-console
console.error(formatConfigErrorMessage(e) + '\n');
telemetry.record(eventConfigError({ cmd, err: e, isFatal: true }));
}
throw e;
}

// If successful, return the result as a verified AstroConfig object.
return result;
}

/** Convert the generic "yargs" flag object into our own, custom TypeScript object. */
// NOTE: This function will be removed in a later PR. Use `flagsToAstroInlineConfig` instead.
// All CLI related flow should be located in the `packages/astro/src/cli` directory.
Expand Down Expand Up @@ -197,7 +167,22 @@ export async function resolveConfig(

const userConfig = await loadConfig(root, inlineOnlyConfig.configFile, fsMod);
const mergedConfig = mergeConfig(userConfig, inlineUserConfig);
const astroConfig = await validateConfig(mergedConfig, root, command);
// First-Pass Validation
let astroConfig: AstroConfig;
try {
astroConfig = await validateConfig(mergedConfig, root, command);
} catch (e) {
// Improve config zod error messages
if (e instanceof ZodError) {
// Mark this error so the callee can decide to suppress Zod's error if needed.
// We still want to throw the error to signal an error in validation.
trackAstroConfigZodError(e);
// eslint-disable-next-line no-console
console.error(formatConfigErrorMessage(e) + '\n');
telemetry.record(eventConfigError({ cmd: command, err: e, isFatal: true }));
}
throw e;
}

return { userConfig: mergedConfig, astroConfig };
}
14 changes: 14 additions & 0 deletions packages/astro/src/core/config/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { AstroConfig } from '../../@types/astro.js';
import { createRelativeSchema } from './schema.js';

/** Turn raw config values into normalized values */
export async function validateConfig(
userConfig: any,
root: string,
cmd: string
): Promise<AstroConfig> {
const AstroConfigRelativeSchema = createRelativeSchema(cmd, root);

// First-Pass Validation
return await AstroConfigRelativeSchema.parseAsync(userConfig);
}
60 changes: 1 addition & 59 deletions packages/astro/src/core/util.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { normalizePath } from 'vite';
import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro.js';
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js';
import type { ModuleLoader } from './module-loader/index.js';
import { prependForwardSlash, removeTrailingForwardSlash, slash } from './path.js';
import { removeTrailingForwardSlash, slash } from './path.js';

/** Returns true if argument is an object of any prototype/class (but not null). */
export function isObject(value: unknown): value is Record<string, any> {
Expand Down Expand Up @@ -184,54 +182,10 @@ export function relativeToSrcDir(config: AstroConfig, idOrUrl: URL | string) {
return id.slice(slash(fileURLToPath(config.srcDir)).length);
}

export function rootRelativePath(
root: URL,
idOrUrl: URL | string,
shouldPrependForwardSlash = true
) {
let id: string;
if (typeof idOrUrl !== 'string') {
id = unwrapId(viteID(idOrUrl));
} else {
id = idOrUrl;
}
const normalizedRoot = normalizePath(fileURLToPath(root));
if (id.startsWith(normalizedRoot)) {
id = id.slice(normalizedRoot.length);
}
return shouldPrependForwardSlash ? prependForwardSlash(id) : id;
}

export function emoji(char: string, fallback: string) {
return process.platform !== 'win32' ? char : fallback;
}

/**
* Simulate Vite's resolve and import analysis so we can import the id as an URL
* through a script tag or a dynamic import as-is.
*/
// NOTE: `/@id/` should only be used when the id is fully resolved
export async function resolveIdToUrl(loader: ModuleLoader, id: string, root?: URL) {
let resultId = await loader.resolveId(id, undefined);
// Try resolve jsx to tsx
if (!resultId && id.endsWith('.jsx')) {
resultId = await loader.resolveId(id.slice(0, -4), undefined);
}
if (!resultId) {
return VALID_ID_PREFIX + id;
}
if (path.isAbsolute(resultId)) {
const normalizedRoot = root && normalizePath(fileURLToPath(root));
// Convert to root-relative path if path is inside root
if (normalizedRoot && resultId.startsWith(normalizedRoot)) {
return resultId.slice(normalizedRoot.length - 1);
} else {
return '/@fs' + prependForwardSlash(resultId);
}
}
return VALID_ID_PREFIX + resultId;
}

export function resolveJsToTs(filePath: string) {
if (filePath.endsWith('.jsx') && !fs.existsSync(filePath)) {
const tryPath = filePath.slice(0, -4) + '.tsx';
Expand All @@ -242,18 +196,6 @@ export function resolveJsToTs(filePath: string) {
return filePath;
}

/**
* Resolve the hydration paths so that it can be imported in the client
*/
export function resolvePath(specifier: string, importer: string) {
if (specifier.startsWith('.')) {
const absoluteSpecifier = path.resolve(path.dirname(importer), specifier);
return resolveJsToTs(normalizePath(absoluteSpecifier));
} else {
return specifier;
}
}

/**
* Set a default NODE_ENV so Vite doesn't set an incorrect default when loading the Astro config
*/
Expand Down
62 changes: 62 additions & 0 deletions packages/astro/src/core/viteUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { normalizePath } from 'vite';
import { prependForwardSlash } from '../core/path.js';
import type { ModuleLoader } from './module-loader/index.js';
import { VALID_ID_PREFIX, resolveJsToTs, unwrapId, viteID } from './util.js';

/**
* Resolve the hydration paths so that it can be imported in the client
*/
export function resolvePath(specifier: string, importer: string) {
if (specifier.startsWith('.')) {
const absoluteSpecifier = path.resolve(path.dirname(importer), specifier);
return resolveJsToTs(normalizePath(absoluteSpecifier));
} else {
return specifier;
}
}

export function rootRelativePath(
root: URL,
idOrUrl: URL | string,
shouldPrependForwardSlash = true
) {
let id: string;
if (typeof idOrUrl !== 'string') {
id = unwrapId(viteID(idOrUrl));
} else {
id = idOrUrl;
}
const normalizedRoot = normalizePath(fileURLToPath(root));
if (id.startsWith(normalizedRoot)) {
id = id.slice(normalizedRoot.length);
}
return shouldPrependForwardSlash ? prependForwardSlash(id) : id;
}

/**
* Simulate Vite's resolve and import analysis so we can import the id as an URL
* through a script tag or a dynamic import as-is.
*/
// NOTE: `/@id/` should only be used when the id is fully resolved
export async function resolveIdToUrl(loader: ModuleLoader, id: string, root?: URL) {
let resultId = await loader.resolveId(id, undefined);
// Try resolve jsx to tsx
if (!resultId && id.endsWith('.jsx')) {
resultId = await loader.resolveId(id.slice(0, -4), undefined);
}
if (!resultId) {
return VALID_ID_PREFIX + id;
}
if (path.isAbsolute(resultId)) {
const normalizedRoot = root && normalizePath(fileURLToPath(root));
// Convert to root-relative path if path is inside root
if (normalizedRoot && resultId.startsWith(normalizedRoot)) {
return resultId.slice(normalizedRoot.length - 1);
} else {
return '/@fs' + prependForwardSlash(resultId);
}
}
return VALID_ID_PREFIX + resultId;
}
2 changes: 1 addition & 1 deletion packages/astro/src/jsx/babel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { PluginObj } from '@babel/core';
import * as t from '@babel/types';
import { AstroError } from '../core/errors/errors.js';
import { AstroErrorData } from '../core/errors/index.js';
import { resolvePath } from '../core/util.js';
import { resolvePath } from '../core/viteUtils.js';
import type { PluginMetadata } from '../vite-plugin-astro/types.js';

const ClientOnlyPlaceholder = 'astro-client-only';
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/jsx/rehype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { visit } from 'unist-util-visit';
import type { VFile } from 'vfile';
import { AstroError } from '../core/errors/errors.js';
import { AstroErrorData } from '../core/errors/index.js';
import { resolvePath } from '../core/util.js';
import { resolvePath } from '../core/viteUtils.js';
import type { PluginMetadata } from '../vite-plugin-astro/types.js';

// This import includes ambient types for hast to include mdx nodes
Expand Down
10 changes: 4 additions & 6 deletions packages/astro/src/vite-plugin-astro-server/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ import type {
} from '../@types/astro.js';
import { getInfoOutput } from '../cli/info/index.js';
import { type HeadElements } from '../core/base-pipeline.js';
import { shouldAppendForwardSlash } from '../core/build/util.js';
import { ASTRO_VERSION, DEFAULT_404_COMPONENT } from '../core/constants.js';
import { enhanceViteSSRError } from '../core/errors/dev/index.js';
import { RewriteEncounteredAnError } from '../core/errors/errors-data.js';
import { AggregateError, AstroError, CSSError, MarkdownError } from '../core/errors/index.js';
import { AggregateError, CSSError, MarkdownError } from '../core/errors/index.js';
import type { Logger } from '../core/logger/core.js';
import type { ModuleLoader } from '../core/module-loader/index.js';
import { prependForwardSlash, removeTrailingForwardSlash } from '../core/path.js';
import { Pipeline, loadRenderer } from '../core/render/index.js';
import { DEFAULT_404_ROUTE, default404Page } from '../core/routing/astro-designed-error-pages.js';
import { default404Page } from '../core/routing/astro-designed-error-pages.js';
import { findRouteToRewrite } from '../core/routing/rewrite.js';
import { isPage, isServerLikeOutput, resolveIdToUrl, viteID } from '../core/util.js';
import { isPage, isServerLikeOutput, viteID } from '../core/util.js';
import { resolveIdToUrl } from '../core/viteUtils.js';
import { PAGE_SCRIPT_ID } from '../vite-plugin-scripts/index.js';
import { getStylesForURL } from './css.js';
import { getComponentMetadata } from './metadata.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/vite-plugin-astro-server/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ModuleLoader } from '../core/module-loader/index.js';
import { resolveIdToUrl } from '../core/util.js';
import { resolveIdToUrl } from '../core/viteUtils.js';

export function createResolve(loader: ModuleLoader, root: URL) {
// Resolves specifiers in the inline hydrated scripts, such as:
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/vite-plugin-astro-server/scripts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { SSRElement } from '../@types/astro.js';
import type { ModuleInfo, ModuleLoader } from '../core/module-loader/index.js';
import { createModuleScriptElementWithSrc } from '../core/render/ssr-element.js';
import { rootRelativePath, viteID } from '../core/util.js';
import { viteID } from '../core/util.js';
import { rootRelativePath } from '../core/viteUtils.js';
import type { PluginMetadata as AstroPluginMetadata } from '../vite-plugin-astro/types.js';
import { crawlGraph } from './vite.js';

Expand Down
Loading

0 comments on commit 0df8142

Please sign in to comment.