Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/warn-vite8-cloudflare-override.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Warns on dev server startup when Vite 8 is detected at the top level of the user's project, and automatically adds a `"overrides": { "vite": "^7" }` entry to `package.json` when running `astro add cloudflare`. This prevents a `require_dist is not a function` crash caused by a Vite version split between Astro (requires Vite 7) and packages like `@tailwindcss/vite` that hoist Vite 8.
68 changes: 68 additions & 0 deletions packages/astro/src/cli/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ export async function add(names: string[], { flags }: AddOptions) {
logger,
scripts: { 'generate-types': 'wrangler types' },
});

await updatePackageJsonOverrides({
configURL,
flags,
logger,
overrides: { vite: '^7' },
});
}
if (integrations.find((integration) => integration.id === 'tailwind')) {
const dir = new URL('./styles/', new URL(userConfig.srcDir ?? './src/', root));
Expand Down Expand Up @@ -715,6 +722,67 @@ async function updateAstroConfig({
}
}

async function updatePackageJsonOverrides({
configURL,
flags,
logger,
overrides,
}: {
configURL: URL;
flags: Flags;
logger: Logger;
overrides: Record<string, string>;
}): Promise<UpdateResult> {
const pkgURL = new URL('./package.json', configURL);
if (!existsSync(pkgURL)) {
logger.debug('add', 'No package.json found, skipping overrides update');
return UpdateResult.none;
}

const pkgPath = fileURLToPath(pkgURL);
const input = await fs.readFile(pkgPath, { encoding: 'utf-8' });
const pkgJson = JSON.parse(input);

pkgJson.overrides ??= {};
let hasChanges = false;
for (const [name, range] of Object.entries(overrides)) {
if (!(name in pkgJson.overrides)) {
pkgJson.overrides[name] = range;
hasChanges = true;
}
}

if (!hasChanges) {
return UpdateResult.none;
}

const output = JSON.stringify(pkgJson, null, 2);
const diff = getDiffContent(input, output);

if (!diff) {
return UpdateResult.none;
}

logger.info(
'SKIP_FORMAT',
`\n ${magenta('Astro will add the following overrides to your package.json:')}`,
);

clack.box(diff, 'package.json', {
rounded: true,
withGuide: false,
width: 'auto',
});

if (await askToContinue({ flags, logger })) {
await fs.writeFile(pkgPath, output, { encoding: 'utf-8' });
logger.debug('add', 'Updated package.json overrides');
return UpdateResult.updated;
} else {
return UpdateResult.cancelled;
}
}

async function updatePackageJsonScripts({
configURL,
flags,
Expand Down
16 changes: 16 additions & 0 deletions packages/astro/src/core/dev/dev.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'node:fs';
import type http from 'node:http';
import { createRequire } from 'node:module';
import type { AddressInfo } from 'node:net';
import { performance } from 'node:perf_hooks';
import colors from 'piccolore';
Expand All @@ -24,6 +25,19 @@ import {
} from './update-check.js';
import { BuildTimeAstroVersionProvider } from '../../cli/infra/build-time-astro-version-provider.js';
import { piccoloreTextStyler } from '../../cli/infra/piccolore-text-styler.js';
import type { Logger } from '../logger/core.js';

function warnIfVite8({ root, logger }: { root: URL | string; logger: Logger }) {
try {
const require = createRequire(root);
const { version } = require('vite/package.json') as { version: string };
if (major(version) >= 8) {
logger.warn('SKIP_FORMAT', msg.vite8Warning({ viteVersion: version }));
}
} catch {
// If vite can't be resolved from the project root, skip the warning
}
}
Comment on lines +30 to +40
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vite already exposes its version number via APIs. We can use that

import { version  } from "vite"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import { version } from "vite" would load our version of Vite, but the goal here is to check the top-level version (which is owned by the user) to see if it's an incompatible version.


export interface DevServer {
address: AddressInfo;
Expand Down Expand Up @@ -140,6 +154,8 @@ export default async function dev(inlineConfig: AstroInlineConfig): Promise<DevS
logger.warn('SKIP_FORMAT', msg.fsStrictWarning());
}

setImmediate(() => warnIfVite8({ root: restart.container.settings.config.root, logger }));

logger.info(null, colors.green('watching for file changes...'));

return {
Expand Down
6 changes: 6 additions & 0 deletions packages/astro/src/core/messages/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ export function fsStrictWarning() {
return `${title}\n${subtitle}\n`;
}

export function vite8Warning({ viteVersion }: { viteVersion: string }) {
const title = yellow('▶ ' + `Vite ${bold(viteVersion)} detected in your project.`);
const subtitle = ` Astro requires Vite 7. Add ${bold('"overrides": { "vite": "^7" }')} to your ${bold('package.json')} to avoid issues.`;
return `${title}\n${subtitle}\n`;
}

export function prerelease({ currentVersion }: { currentVersion: string }) {
const tag = currentVersion.split('-').slice(1).join('-').replace(/\..*$/, '') || 'unknown';
const badge = bgYellow(black(` ${tag} `));
Expand Down
Loading