Migration Guide
This guide will help you migrate from older versions of Astro to the latest version.
You can update your project’s version of Astro to the latest version using your package manager. If you’re using Astro integrations, you’ll also want to update those to the latest version.
# updates the astro dependency:
npm upgrade astro
# or, to update all dependencies:
npm upgrade
# updates the astro dependency:
pnpm upgrade astro
# or, to update all dependencies:
pnpm upgrade
# updates the astro dependency:
yarn upgrade astro
# or, to update all dependencies:
yarn upgrade
Read the guide below for major highlights and instructions on how to handle breaking changes.
Astro 1.0
Section titled Astro 1.0Astro v1.0 introduces some changes that you should be aware of when migrating from v0.x and v1.0-beta releases. See below for more details.
Updated: Vite 3
Section titled Updated: Vite 3Astro v1.0 has upgraded from Vite 2 to Vite 3. We’ve handled most of the upgrade for you inside of Astro; however, some subtle Vite behaviors may still change between versions. Refer to the official Vite Migration Guide if you run into trouble.
Deprecated: Astro.canonicalURL
Section titled Deprecated: Astro.canonicalURLYou can now use the new Astro.url
helper to construct your own canonical URL from the current page/request URL.
// Before:
const canonicalURL = Astro.canonicalURL;
// After:
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
Changed: Scoped CSS specificity
Section titled Changed: Scoped CSS specificitySpecificity will now be preserved in scoped CSS styles. This change will cause most scoped styles to happen to take precedence over global styles. But, this behavior is no longer explicitly guaranteed.
Technically, this is accomplished using the :where()
pseudo-class instead of using classes directly in Astro’s CSS output.
Let’s use the following style block in an Astro component as an example:
<style>
div { color: red; } /* 0-0-1 specificity */
</style>
Previously, Astro would transform this into the following CSS, which has a specificity of 0-1-1
— a higher specificity than the source CSS:
div.astro-XXXXXX { color: red; } /* 0-1-1 specificity */
Now, Astro wraps the class selector with :where()
, maintaining the authored specificity:
div:where(.astro-XXXXXX) { color: red; } /* 0-0-1 specificity */
The previous specificity increase made it hard to combine scoped styles in Astro with other CSS files or styling libraries (e.g. Tailwind, CSS Modules, Styled Components, Stitches). This change will allow Astro’s scoped styles to work consistently alongside them while still preserving the exclusive boundaries that prevent styles from applying outside the component.
Deprecated: Components and JSX in Markdown
Section titled Deprecated: Components and JSX in MarkdownAstro no longer supports components or JSX expressions in Markdown pages by default. For long-term support you should migrate to the @astrojs/mdx
integration.
To make migrating easier, a new legacy.astroFlavoredMarkdown
flag (removed in v2.0) can be used to re-enable previous Markdown features.
Converting existing .md
files to .mdx
Section titled Converting existing .md files to .mdxIf you’re not familiar with MDX, here are some steps you can follow to quickly convert an existing “Astro Flavored Markdown” file to MDX. As you learn more about MDX, feel free to explore other ways of writing your pages!
-
Install the
@astrojs/mdx
integration. -
Change your existing
.md
file extensions to.mdx
-
Remove any
setup:
properties from your frontmatter, and write any import statements below the frontmatter instead.src/ pages/ posts/ my-post.mdx --- layout: '../../layouts/BaseLayout.astro' setup: | import ReactCounter from '../../components/ReactCounter.jsx' title: 'Migrating to MDX' date: 2022-07-26 tags: ["markdown", "mdx", "astro"] --- import ReactCounter from '../../components/ReactCounter.jsx' # {frontmatter.title} Here is my counter component, working in MDX: <ReactCounter client:load />
-
Update any
Astro.glob()
statements that currently return.md
files so that they will now return your.mdx
files. -
Update any use of the
<Content />
component to use the default export when importing MDX:src/ pages/ index.astro --- // Multiple imports with Astro.glob const mdxPosts = await Astro.glob('./posts/*.mdx'); --- {mdxPosts.map(Post => <Post.default />)}
src/ pages/ index.astro --- // Import a single page import { default as About } from './about.mdx'; --- <About />
<Markdown />
Component Removed
Section titled <Markdown /> Component RemovedAstro’s built-in <Markdown />
component has been moved to a separate package. To continue using this component, you will now need to install @astrojs/markdown-component
and update your imports accordingly. For more details, see the @astrojs/markdown
README.
Migrate to v1.0.0-beta
Section titled Migrate to v1.0.0-betaOn April 4, 2022 we released the Astro 1.0 Beta! 🎉
If you are coming from v0.25 or earlier, make sure you have read and followed the v0.26 Migration Guide below, which contained several major breaking changes.
The v1.0.0-beta.0
release of Astro contained no breaking changes. Below are small changes that were introduced during the beta period.
Changed: RSS Feeds
Section titled Changed: RSS FeedsRSS feeds should now be generated using the @astrojs/rss
package, as described in our RSS guide.
Migrate to v0.26
Section titled Migrate to v0.26New Configuration API
Section titled New Configuration APIOur Configuration API has been redesigned to solve a few glaring points of confusion that had built up over the last year. Most of the configuration options have just been moved or renamed, which will hopefully be a quick update for most users. A few options have been refactored more heavily, and may require a few additional changes:
.buildOptions.site
has been replaced with.site
(your deployed domain) and a new.base
(your deployed subpath) option..markdownOptions
has been replaced with.markdown
, a mostly similar config object with some small changes to simplify Markdown configuration..sitemap
has been moved into the @astrojs/sitemap integration.
If you run Astro with legacy configuration, you will see a warning with instructions on how to update. See our updated Configuration Reference for more information on upgrading.
Read RFC0019 for more background on these changes.
New Markdown API
Section titled New Markdown APIAstro v0.26 releases a brand new Markdown API for your content. This included three major user-facing changes:
- You can now
import
/import()
markdown content directly using an ESM import. - A new
Astro.glob()
API, for easier glob imports (especially for Markdown). - BREAKING CHANGE:
Astro.fetchContent()
has been removed and replaced byAstro.glob()
- BREAKING CHANGE: Markdown objects have an updated interface.
// v0.25
let allPosts = Astro.fetchContent('./posts/*.md');
// v0.26+
let allPosts = await Astro.glob('./posts/*.md');
When migrating, be careful about the new Markdown object interface. Frontmatter, for example, has been moved to the .frontmatter
property, so references like post.title
should change to post.frontmatter.title
.
This should solve many issues for Markdown users, including some nice performance boosts for larger sites.
Read RFC0017 for more background on these changes.
New Default Script Behavior
Section titled New Default Script Behavior<script>
tags in Astro components are now built, bundled and optimized by default. This completes a long-term move to make our Astro component syntax more consistent, matching the default-optimized behavior our <style>
tags have today.
This includes a few changes to be aware of:
- BREAKING:
<script hoist>
is the new default<script>
behavior. Thehoist
attribute has been removed. To use the new default behaviour, make sure there are no other attributes on the<script>
tag. For example, removetype="module"
if you were using it before. - New
<script is:inline>
directive, to revert a<script>
tag to previous default behavior (unbuilt, unbundled, untouched by Astro). - New
<style is:inline>
directive, to leave a style tag inline in the page template (similar to previous<script>
behavior). - New
<style is:global>
directive to replace<style global>
in a future release.
// v0.25
<script hoist type="module">
// v0.26+
<script>
See how to use client-side scripts in Astro for full details.
Read RFC0016 for more background on these changes.
Updated Astro.request
API
Section titled Updated Astro.request APIAstro.request
has been changed from our custom object to a standard Request
object. This is part of a project to use more web standard APIs, especially where SSR is concerned.
This includes a few changes to be aware of:
- Change
Astro.request
to become a Request object. - Move
Astro.request.params
toAstro.params
. - Move
Astro.request.canonicalURL
toAstro.canonicalURL
.
Read RFC0018 for more background on these changes.
Other Changes
Section titled Other Changes- Improve
Astro.slots
API to support passing arguments to function-based slots. This allows for more ergonomic utility components that accept a callback function as a child. - Update CLI output formatting, especially around error reporting.
- Update
@astrojs/compiler
, fixing some bugs related to RegExp usage in frontmatter
Migrate to v0.25
Section titled Migrate to v0.25Astro Integrations
Section titled Astro IntegrationsThe renderers
config has been replaced by a new, official integration system! This unlocks some really exciting new features for Astro. You can read our Using Integrations guide for more details on how to use this new system.
Integrations replace our original renderers
concept, and come with a few breaking changes and new defaults for existing users. These changes are covered below.
Removed: Built-in Framework Support
Section titled Removed: Built-in Framework SupportPreviously, React, Preact, Svelte, and Vue were all included with Astro by default. Starting in v0.25.0, Astro no longer comes with any built-in renderers. If you did not have a renderers
configuration entry already defined for your project, you will now need to install those frameworks yourself.
Read our step-by-step walkthrough to learn how to add a new Astro integration for the framework(s) that you currently use.
Deprecated: Renderers
Section titled Deprecated: RenderersThe new integration system replaces the previous renderers
system, including the published @astrojs/renderer-*
packages on npm. Going forward, @astrojs/renderer-react
becomes @astrojs/react
, @astrojs/renderer-vue
becomes @astrojs/vue
, and so on.
To migrate: update Astro to v0.25.0
and then run astro dev
or astro build
with your old configuration file containing the outdated "renderers"
config. You will immediately see a notice telling you the exact changes you need to make to your astro.config.mjs
file, based on your current config. You can also update your packages yourself, using the table below.
For a deeper walkthrough, read our step-by-step guide to learn how to replace existing renderers with a new Astro framework integration.
# Install your new integrations and frameworks:
# (Read the full walkthrough: https://docs.astro.build/en/guides/integrations-guide)
npm install @astrojs/lit lit
npm install @astrojs/react react react-dom
// Then, update your `astro.config.mjs` file:
// (Read the full walkthrough: https://docs.astro.build/en/guides/integrations-guide)
import lit from '@astrojs/lit';
import react from '@astrojs/react';
export default {
renderers: ['@astrojs/renderer-lit', '@astrojs/renderer-react'],
integrations: [lit(), react()],
}
Deprecated Renderers on npm | v0.25+ Integrations on npm |
---|---|
@astrojs/renderer-react | @astrojs/react |
@astrojs/renderer-preact | @astrojs/preact |
@astrojs/renderer-solid | @astrojs/solid-js |
@astrojs/renderer-vue | @astrojs/vue |
@astrojs/renderer-svelte | @astrojs/svelte |
Handling Peer Dependencies
Section titled Handling Peer DependenciesUnlike the old renderers, integrations no longer mark the frameworks themselves (“react”, “svelte”, “vue”, etc.) as direct dependencies of the integration. Instead, you should now install your framework packages in addition to your integrations.
# Example: Install integrations and frameworks together
npm install @astrojs/react react react-dom
If you see a "Cannot find package 'react'"
(or similar) warning when you start up Astro, that means that you need to install that package into your project. See our note on peer dependencies in the troubleshooting guide for more information.
If you are using npm
& Node v16+, then this may be automatically handled for you by npm
, since the latest version of npm
(v7+) installs peer dependencies like this for you automatically. In that case, installing a framework like “react” into your project is an optional but still recommended step.
Updated: Syntax Highlighting
Section titled Updated: Syntax HighlightingWe love to find sensible defaults that “just work” out-of-the-box. As part of this, we decided to make Shiki our new default syntax highlighter. This comes pre-configured with the github-dark
theme, providing zero-config highlighting in your code blocks without extraneous CSS classes, stylesheets, or client-side JS.
Check our new syntax highlighting docs for full details. If you prefer to keep Prism as your syntax highlighter, set the syntaxHighlight
option to 'prism'
in your project’s markdown configuration.
The <Prism />
component has a new home
Section titled The <Prism /> component has a new homeAs part of our mission to keep Astro core as lean as possible, we’ve moved the built-in Prism
component out of astro/components
and into the @astrojs/prism
package. You can now import this component from @astrojs/prism
like so:
---
import { Prism } from '@astrojs/prism';
---
Since the @astrojs/prism
package is still bundled with astro
core, you won’t need to install anything new, nor add Prism as an integration! However, note that we do plan to extract @astrojs/prism
(and Prism syntax highlighting in general) to a separate, installable package in the future. See the <Prism />
component API reference for more.
CSS Parser Upgrade
Section titled CSS Parser UpgradeOur internal CSS parser has been updated, and comes with better support for advanced CSS syntax, like container queries. This should be a mostly invisible change for most users, but hopefully advanced users will enjoy the new CSS feature support.
Migrate to v0.24
Section titled Migrate to v0.240.24 introduced a new static build strategy that changes the behavior of a few features. In previous versions of Astro this was available behavior with an opt-in flag: --experimental-static-build
.
To migrate for the transition, be aware of the following changes that will be required to move to this new build engine. You can make these changes to your codebase at any time so that you are ready ahead of schedule.
Deprecated: Astro.resolve()
Section titled Deprecated: Astro.resolve()Astro.resolve()
allows you to get resolved URLs to assets that you might want to reference in the browser. This was most commonly used inside of <link>
and <img>
tags to load CSS files and images as needed. Unfortunately, this will no longer work due to Astro now building assets at build time rather than at render time. You’ll want to upgrade your asset references to one of the following future-proof options available going forward:
How to Resolve CSS Files
Section titled How to Resolve CSS Files1. ESM Import (Recommended)
Example: import './style.css';
When to use this: If your CSS file lives inside of the src/
directory, and you want automatic CSS build and optimization features.
Use an ESM import to add some CSS onto the page. Astro detects these CSS imports and then builds, optimizes, and adds the CSS to the page automatically. This is the easiest way to migrate from Astro.resolve()
while keeping the automatic building/bundling that Astro provides.
---
// Example: Astro will include and optimize this CSS for you automatically
import './style.css';
---
<html><!-- Your page here --></html>
Importing CSS files should work anywhere that ESM imports are supported, including:
- JavaScript files
- TypeScript files
- Astro component front matter
- non-Astro components like React, Svelte, and others
When a CSS file is imported using this method, any @import
statements are also resolved and inlined into the imported CSS file. All url()
references are also resolved relative to the source file, and any url()
referenced assets will be included in the final build.
2. Absolute URL Path
Example: <link href="/style.css">
When to use this: If your CSS file lives inside of public/
, and you prefer to create your HTML link
element yourself.
You can reference any file inside of the public/
directory by absolute URL path in your component template. This is a good option if you want to control the <link>
tag on the page yourself. However, this approach also skips the CSS processing, bundling and optimizations that are provided by Astro when you use the import
method described above.
We recommend using the import
approach over the abolute URL approach since it provides the best possible CSS performance and features by default.
How to Resolve JavaScript Files
Section titled How to Resolve JavaScript Files1. Absolute URL Path
Example: <script src="/some-external-script.js" />
When to use this: If your JavaScript file lives inside of public/
.
You can reference any file inside of the public/
directory by absolute URL path in your Astro component templates. This is a good default option for external scripts because it lets you control the <script>
tag on the page yourself.
Note that this approach skips the JavaScript processing, bundling and optimizations that are provided by Astro when you use the import
method described below. However, this may be preferred for any external scripts that have already been published and minified separately from Astro. If your script was downloaded from an external source, then this method is probably preferred.
2. ESM Import via <script hoist>
Example: <script hoist>import './some-external-script.js';</script>
When to use this: If your external script lives inside of src/
and it supports the ESM module type.
Use an ESM import inside of a <script hoist>
element in your Astro template, and Astro will include the JavaScript file in your final build. Astro detects these JavaScript client-side imports and then builds, optimizes, and adds the JavaScript to the page automatically. This is the easiest way to migrate from Astro.resolve()
while keeping the automatic building/bundling that Astro provides.
<script hoist>
import './some-external-script.js';
</script>
Note that Astro will bundle this external script with the rest of your client-side JavaScript, and load it in the type="module"
script context. Some older JavaScript files may not be written for the module
context, in which case they may need to be updated to use this method.
How to Resolve Images & Other Assets
Section titled How to Resolve Images & Other Assets1. Absolute URL Path (Recommended)
Example: <img src="/penguin.png">
When to use this: If your asset lives inside of public/
.
If you place your images inside of public/
you can safely reference them by absolute URL path directly in your component templates. This is the simplest way to reference an asset that you can use today, and it is recommended for most users who are getting started with Astro.
2. ESM Import
Example: import imgUrl from './penguin.png'
When to use this: If your asset lives inside of the src/
directory, and you want automatic optimization features like filename hashing.
This works inside of any JavaScript or Astro component, and returns a resolved URL to the final image. Once you have the resolved URL, you can use it anywhere inside of the component template.
---
// Example: Astro will include this image file in your final build
import imgUrl from './penguin.png';
---
<img src={imgUrl} />
Similar to how Astro handles CSS, the ESM import allows Astro to perform some simple build optimizations for you automatically. For example, any asset inside of src/
that is imported using an ESM import (ex: import imgUrl from './penguin.png'
) will have its filename hashed automatically. This can let you cache the file more aggressively on the server, improving user performance. In the future, Astro may add more optimizations like this.
Tip: If you dislike static ESM imports, Astro also supports dynamic ESM imports. We only recommend this option if you prefer this syntax: <img src={(await import('./penguin.png')).default} />
.
Deprecated: <script>
Default Processing
Section titled Deprecated: <script> Default ProcessingPreviously, all <script>
elements were read from the final HTML output and processed + bundled automatically. This behavior is no longer the default. Starting in 0.24, you must opt-in to <script>
element processing via the hoist
attribute. The type="module"
is also required for hoisted modules.
<script>
// Will be rendered into the HTML exactly as written!
// ESM imports will not be resolved relative to the file.
</script>
<script type="module" hoist>
// Processed! Bundled! ESM imports work, even to npm packages.
</script>
Migrate to v0.23
Section titled Migrate to v0.23Missing Sass Error
Section titled Missing Sass ErrorPreprocessor dependency "sass" not found. Did you install it?
In our quest to reduce npm install size, we’ve moved Sass out to an optional dependency. If you use Sass in your project, you’ll want to make sure that you run npm install sass --save-dev
to save it as a dependency.
Deprecated: Unescaped HTML
Section titled Deprecated: Unescaped HTMLIn Astro v0.23+, unescaped HTML content in expressions is now deprecated. In future releases, content within expressions will have strings escaped to protect against unintended HTML injection.
<h1>{title}</h1> <!-- <h1>Hello <strong>World</strong></h1> -->
<h1>{title}</h1> <!-- <h1>Hello <strong>World</strong></h1> -->
To continue injecting unescaped HTML, you can now use set:html
.
<h1>{title}</h1>
<h1 set:html={title} />
To avoid a wrapper element, set:html
can work alongside <Fragment>
.
<h1>{title}!</h1>
<h1><Fragment set:html={title}>!</h1>
You can also protect against unintended HTML injection with set:text
.
<h1 set:text={title} /> <!-- <h1>Hello <strong>World</strong></h1> -->
Migrate to v0.21
Section titled Migrate to v0.21Starting in v0.21, Astro is built with Vite.
As a result, configurations written in snowpack.config.mjs
should be moved into astro.config.mjs
.
// @ts-check
/** @type {import('astro').AstroUserConfig} */
export default {
renderers: [],
vite: {
plugins: [],
},
};
To learn more about configuring Vite, please visit their configuration guide.
Vite Plugins
Section titled Vite PluginsIn Astro v0.21+, Vite plugins may be configured within astro.config.mjs
.
import { imagetools } from 'vite-imagetools';
export default {
vite: {
plugins: [imagetools()],
},
};
To learn more about Vite plugins, please visit their plugin guide.
Vite Changes to Renderers
Section titled Vite Changes to RenderersIn Astro v0.21+, plugins should now use viteConfig()
.
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default {
name: '@astrojs/renderer-svelte',
client: './client.js',
server: './server.js',
snowpackPlugin: '@snowpack/plugin-svelte',
snowpackPluginOptions: { compilerOptions: { hydratable: true } },
viteConfig() {
return {
optimizeDeps: {
include: ['@astrojs/renderer-svelte/client.js', 'svelte', 'svelte/internal'],
exclude: ['@astrojs/renderer-svelte/server.js'],
},
plugins: [
svelte({
emitCss: true,
compilerOptions: { hydratable: true },
}),
],
};
},
}
To learn more about Vite plugins, please visit their plugin guide.
Aliasing
Section titled AliasingIn Astro v0.21+, import aliases can be added from tsconfig.json
or jsconfig.json
.
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/components/*": ["src/components/*"]
}
}
}
These aliases are integrated automatically into VSCode and other editors.
File Extensions in Imports
Section titled File Extensions in ImportsIn Astro v0.21+, files need to be referenced by their actual extension, exactly as it is on disk. In this example, Div.tsx
would need to be referenced as Div.tsx
, not Div.jsx
.
import Div from './Div.jsx' // Astro v0.20
import Div from './Div.tsx' // Astro v0.21
This same change applies to a compile-to-css file like Div.scss
:
<link rel="stylesheet" href={Astro.resolve('./Div.css')}>
<link rel="stylesheet" href={Astro.resolve('./Div.scss')}>
Removed: Components in Frontmatter
Section titled Removed: Components in FrontmatterPreviously, you could create mini Astro Components inside of the Astro Frontmatter, using JSX syntax instead of Astro’s component syntax. This was always a bit of a hack, but in the new compiler it became impossible to support. We hope to re-introduce this feature in a future release of Astro using a different, non-JSX API.
To migrate to v0.21+, please convert all JSX Astro components (that is, any Astro components created inside of another component’s frontmatter) to standalone components.
Styling Changes
Section titled Styling ChangesAutoprefixer
Section titled AutoprefixerAutoprefixer is no longer run by default. To enable:
- Install the latest version (
npm install autoprefixer
) - Create a
postcss.config.cjs
file at the root of your project with:module.exports = { plugins: { autoprefixer: {}, }, };
Tailwind CSS
Section titled Tailwind CSSEnsure you have PostCSS installed. This was optional in previous releases, but is required now:
- Install the latest version of postcss (
npm install -D postcss
) - Create a
postcss.config.cjs
file at the root of your project with:module.exports = { plugins: { tailwindcss: {}, }, };
Known Issues
Section titled Known IssuesImports on top
Section titled Imports on topIn Astro v0.21+, a bug has been introduced that requires imports inside components to be at the top of your front matter.
---
import Component from '../components/Component.astro'
const whereShouldIPutMyImports = "on top!"
---