Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Vite 5 #9122

Merged
merged 2 commits into from
Nov 17, 2023
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
8 changes: 8 additions & 0 deletions .changeset/light-ties-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@astrojs/svelte': major
'@astrojs/react': patch
'@astrojs/vue': patch
'astro': major
---

Adds Vite 5 support. There are no breaking changes from Astro. Check the [Vite migration guide](https://vitejs.dev/guide/migration.html) for details of the breaking changes from Vite instead.
5 changes: 5 additions & 0 deletions .changeset/wild-apricots-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/svelte': major
---

Drops support for Svelte 3 as `@sveltejs/vite-plugin-svelte` is updated to `3.0.0` which does not support Svelte 3
4 changes: 2 additions & 2 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@
"tsconfck": "^3.0.0",
"unist-util-visit": "^4.1.2",
"vfile": "^5.3.7",
"vite": "^4.4.9",
"vite": "^5.0.0",
"vitefu": "^0.2.4",
"which-pm": "^2.1.1",
"yargs-parser": "^21.1.1",
Expand Down Expand Up @@ -222,7 +222,7 @@
"rehype-slug": "^5.0.1",
"rehype-toc": "^3.0.2",
"remark-code-titles": "^0.1.2",
"rollup": "^3.28.1",
"rollup": "^4.4.1",
"sass": "^1.66.1",
"srcset-parse": "^1.1.0",
"unified": "^10.1.2"
Expand Down
2 changes: 0 additions & 2 deletions packages/astro/src/core/preview/static-preview-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ export default async function createStaticPreviewServer(
host: getResolvedHostForHttpServer(settings.config.server.host),
port: settings.config.server.port,
closed,
// In Vite 5, `httpServer` may be a `Http2SecureServer`, but we know we are only starting a HTTP server
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
server: previewServer.httpServer as http.Server,
Copy link
Member

@Princesseuh Princesseuh Nov 17, 2023

Choose a reason for hiding this comment

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

Is there a world where we'd want to support https for the preview server? Unrelated to this, just wondering.

Copy link
Member Author

Choose a reason for hiding this comment

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

We could! At the moment we have control over the config passed to Vite's preview() so we know this will always be a http server. If we open up to the config from astro.config.mjs in the future, they can create https servers.

stop: async () => {
await new Promise((resolve, reject) => {
Expand Down
67 changes: 43 additions & 24 deletions packages/astro/src/core/preview/vite-plugin-astro-preview.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import fs from 'node:fs';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { fileURLToPath } from 'node:url';
import type { Connect, Plugin } from 'vite';
import { version } from 'vite';
import type { AstroSettings } from '../../@types/astro.js';
import { notFoundTemplate, subpathNotUsedTemplate } from '../../template/4xx.js';
import { cleanUrl } from '../../vite-plugin-utils/index.js';
import { stripBase } from './util.js';

const HAS_FILE_EXTENSION_REGEXP = /^.*\.[^\\]+$/;
const IS_VITE_5 = version.startsWith('5.');

export function vitePluginAstroPreview(settings: AstroSettings): Plugin {
const { base, outDir, trailingSlash } = settings.config;
Expand All @@ -24,8 +24,7 @@ export function vitePluginAstroPreview(settings: AstroSettings): Plugin {
return;
}

const strippedPathname = stripBase(req.url!, base);
const pathname = new URL(strippedPathname, 'https://a.b').pathname;
const pathname = cleanUrl(stripBase(req.url!, base));
const isRoot = pathname === '/';

// Validate trailingSlash
Expand Down Expand Up @@ -53,29 +52,49 @@ export function vitePluginAstroPreview(settings: AstroSettings): Plugin {
});

return () => {
const fourOhFourMiddleware: Connect.NextHandleFunction = (req, res) => {
const errorPagePath = fileURLToPath(outDir + '/404.html');
if (fs.existsSync(errorPagePath)) {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end(fs.readFileSync(errorPagePath));
} else {
const pathname = stripBase(req.url!, base);
res.statusCode = 404;
res.end(notFoundTemplate(pathname, 'Not Found'));
}
};
// NOTE: the `base` is stripped from `req.url` for post middlewares

// Vite 5 has its own 404 middleware, we replace it with ours instead.
if (IS_VITE_5) {
for (const middleware of server.middlewares.stack) {
// This hardcoded name will not break between Vite versions
if ((middleware.handle as Connect.HandleFunction).name === 'vite404Middleware') {
middleware.handle = fourOhFourMiddleware;
server.middlewares.use((req, res, next) => {
const pathname = cleanUrl(req.url!);

// Vite doesn't handle /foo/ if /foo.html exists, we handle it anyways
if (pathname.endsWith('/')) {
const pathnameWithoutSlash = pathname.slice(0, -1);
const htmlPath = fileURLToPath(outDir + pathnameWithoutSlash + '.html');
if (fs.existsSync(htmlPath)) {
req.url = pathnameWithoutSlash + '.html';
return next();
}
Comment on lines +60 to 67
Copy link
Member Author

Choose a reason for hiding this comment

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

The comment above should clarify what this does. But to further explain why we're assigning to req.url, this is for a later Vite middleware to load the files. We only need to update the req.url so that middleware can detect a HTML file.

}
} else {
server.middlewares.use(fourOhFourMiddleware);
// Vite doesn't handle /foo if /foo/index.html exists, we handle it anyways
else {
const htmlPath = fileURLToPath(outDir + pathname + '/index.html');
if (fs.existsSync(htmlPath)) {
req.url = pathname + '/index.html';
return next();
}
}

next();
});

// Vite has its own 404 middleware, we replace it with ours instead.
for (const middleware of server.middlewares.stack) {
// This hardcoded name will not break between Vite versions
if ((middleware.handle as Connect.HandleFunction).name === 'vite404Middleware') {
// Fallback to 404 page if it exists
middleware.handle = (req: IncomingMessage, res: ServerResponse) => {
const errorPagePath = fileURLToPath(outDir + '/404.html');
if (fs.existsSync(errorPagePath)) {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end(fs.readFileSync(errorPagePath));
} else {
res.statusCode = 404;
res.end(notFoundTemplate(req.url!, 'Not Found'));
}
};
}
}
};
},
Expand Down
6 changes: 1 addition & 5 deletions packages/astro/src/vite-plugin-load-fallback/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import nodeFs from 'node:fs';
import npath from 'node:path';
import type * as vite from 'vite';
import { slash } from '../core/path.js';
import { cleanUrl } from '../vite-plugin-utils/index.js';

type NodeFileSystemModule = typeof nodeFs;

Expand Down Expand Up @@ -77,8 +78,3 @@ export default function loadFallbackPlugin({
},
];
}

const queryRE = /\?.*$/s;
const hashRE = /#.*$/s;

const cleanUrl = (url: string): string => url.replace(hashRE, '').replace(queryRE, '');
3 changes: 1 addition & 2 deletions packages/astro/src/vite-plugin-scripts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ export default function astroScriptsPlugin({ settings }: { settings: AstroSettin
},
buildStart() {
const hasHydrationScripts = settings.scripts.some((s) => s.stage === 'before-hydration');
// @ts-expect-error Vite 5 renamed `ssrBuild` to `isSsrBuild`
const isSsrBuild = env?.ssrBuild || env?.isSsrBuild;
const isSsrBuild = env?.isSsrBuild;
if (hasHydrationScripts && env?.command === 'build' && !isSsrBuild) {
this.emitFile({
type: 'chunk',
Expand Down
5 changes: 5 additions & 0 deletions packages/astro/src/vite-plugin-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ export function normalizeFilename(filename: string, root: URL) {
}
return removeLeadingForwardSlashWindows(filename);
}

const postfixRE = /[?#].*$/s;
export function cleanUrl(url: string): string {
return url.replace(postfixRE, '');
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineConfig } from 'rollup'
import { defineConfig } from 'astro/config'
import test from './integration.js'

export default defineConfig({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineConfig } from 'rollup'
import { defineConfig } from 'astro/config'
import test from './integration.js'

export default defineConfig({
Expand Down
7 changes: 1 addition & 6 deletions packages/astro/test/preview-routing.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { expect } from 'chai';
import { version } from 'vite';
import { loadFixture } from './test-utils.js';

const IS_VITE_5 = version.startsWith('5.');

// Skip in Vite 5 as it changes how HTML files are served. We may want to review aligning
// trailingSlash and build.format to avoid potential footguns in Astro 4
(IS_VITE_5 ? describe.skip : describe)('Preview Routing', function () {
describe('Preview Routing', function () {
describe('build format: directory', () => {
describe('Subpath without trailing slash and trailingSlash: never', () => {
/** @type {import('./test-utils').Fixture} */
Expand Down
3 changes: 1 addition & 2 deletions packages/integrations/markdoc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@
"devalue": "^4.3.2",
"linkedom": "^0.15.1",
"mocha": "^10.2.0",
"rollup": "^3.28.1",
"vite": "^4.4.9"
"vite": "^5.0.0"
},
"engines": {
"node": ">=18.14.1"
Expand Down
5 changes: 2 additions & 3 deletions packages/integrations/markdoc/src/content-entry-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import matter from 'gray-matter';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import type * as rollup from 'rollup';
import type { ErrorPayload as ViteErrorPayload } from 'vite';
import type { ErrorPayload as ViteErrorPayload, Rollup } from 'vite';
import type { ComponentConfig } from './config.js';
import { htmlTokenTransform } from './html/transform/html-token-transform.js';
import type { MarkdocConfigResult } from './load-config.js';
Expand Down Expand Up @@ -174,7 +173,7 @@ function getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string })
async function emitOptimizedImages(
nodeChildren: Node[],
ctx: {
pluginContext: rollup.PluginContext;
pluginContext: Rollup.PluginContext;
filePath: string;
astroConfig: AstroConfig;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"remark-shiki-twoslash": "^3.1.3",
"remark-toc": "^8.0.1",
"unified": "^10.1.2",
"vite": "^4.4.9"
"vite": "^5.0.0"
},
"engines": {
"node": ">=18.14.1"
Expand Down
4 changes: 2 additions & 2 deletions packages/integrations/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"dev": "astro-scripts dev \"src/**/*.ts\""
},
"dependencies": {
"@vitejs/plugin-react": "^4.0.4",
"@vitejs/plugin-react": "^4.2.0",
"ultrahtml": "^1.3.0"
},
"devDependencies": {
Expand All @@ -57,7 +57,7 @@
"cheerio": "1.0.0-rc.12",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"vite": "^4.4.9"
"vite": "^5.0.0"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",
Expand Down
6 changes: 3 additions & 3 deletions packages/integrations/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@
"dev": "astro-scripts dev \"src/**/*.ts\""
},
"dependencies": {
"@sveltejs/vite-plugin-svelte": "^2.5.2",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"svelte2tsx": "^0.6.20"
},
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"svelte": "^4.2.0",
"vite": "^4.4.9"
"vite": "^5.0.0"
},
"peerDependencies": {
"astro": "^3.0.0",
"svelte": "^3.55.0 || ^4.0.0 || ^5.0.0-next.1"
"svelte": "^4.0.0 || ^5.0.0-next.1"
},
"engines": {
"node": ">=18.14.1"
Expand Down
1 change: 1 addition & 0 deletions packages/integrations/svelte/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ async function getViteConfiguration({
}

if (!resolvedOptions.preprocess && !(await svelteConfigHasPreprocess(root))) {
// @ts-expect-error there's a bug with the types where the first arg should be optional
resolvedOptions.preprocess = vitePreprocess();
Comment on lines +76 to 77
Copy link
Member Author

Choose a reason for hiding this comment

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

I've sent a PR upstream to fix it. If it's released, I'll update this part before merging.

}

Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/tailwind/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"tailwindcss": "^3.3.3",
"vite": "^4.4.9"
"vite": "^5.0.0"
},
"peerDependencies": {
"astro": "^3.0.0",
Expand Down
8 changes: 4 additions & 4 deletions packages/integrations/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
"test": "mocha --timeout 20000"
},
"dependencies": {
"@vitejs/plugin-vue": "^4.3.3",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"@vitejs/plugin-vue": "^4.5.0",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/babel-plugin-jsx": "^1.1.5",
"@vue/compiler-sfc": "^3.3.4"
},
Expand All @@ -50,10 +50,10 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"chai": "^4.3.7",
"linkedom": "^0.15.1",
"cheerio": "1.0.0-rc.12",
"linkedom": "^0.15.1",
"mocha": "^10.2.0",
"vite": "^4.4.9",
"vite": "^5.0.0",
"vue": "^3.3.4"
},
"peerDependencies": {
Expand Down
Loading
Loading