Migration of Sitecore Vue Website to Astro
Vue.js is a flexible and customizable web framework for building user interfaces. Vue doesn’t have any ability to generate pages on the server side. There could be a few options, on how to add it. One of them is the Astro web framework. It supports server-side rendering.
Astro pioneered and popularized island architecture. This approach has better front-end performance by helping you avoid monolithic JavaScript patterns. You can split your pages by areas and control the lifecycle of each area with simple attributes.
Astro framework officially provides the ability of Vue.js integration. It simplifies the migration process and makes the barrier to entry sufficiently low for Vue.js developers. Our unofficial Sitecore JSS SDK contains the Astro template and provides the ability to use all Astro benefits on Sitecore headless projects like site static generation, island architecture, etc. Also, it has a sample of usage Vue.js components. It means that we can easily and quickly migrate the Vue.js project to Astro with minimal changes in Vue.js components.
Let’s go through the full migration process, imagine we have the existing Sitecore Vue.js JSS project. We want to use Astro in future development but we don't want to lose earlier developed functionality on Vue.js. And we don’t have a final decision, what framework would we like to use for each component. Which components do we want to simplify with Astro? Which components should we leave on Vue.js? No worries about this, we can save all our existing work, start to use Astro, and continue to use both frameworks’ features. If we would like to migrate some Vue components to Astro, we will be able to make this decision later.
Here is the list of steps that we will need to do:
- Creation the Astro JSS project. We need a new Astro Sitecore JSS project as a base for our migration. First of all, we will install the clean Astro JSS project and verify that it works with Sitecore. Run the command and set the configurations:
npx @astro-sitecore-jss/create-astro-sitecore-jss@latest
Note: Ensure your settings are equal in Sitecore node and Astro app:
App name: (vue-astro-migration)
- Field: “App Name” of Item: /sitecore/content/Samples/Vue Astro Migration/Settings
- Field: “Site name” of Item: /sitecore/content/Samples/Vue Astro Migration/Settings/Site Grouping/Vue Astro Migration
- Property: “jssAppName” of File ./scjssconfig.json
- Field: Server side rendering engine endpoint URL - http://host.docker.internal:4321/api/editing/render
- Field: ServerSideRenderingEngineApplicationUrl - http://host.docker.internal:4321/
- Add or Update .gitignore by:
node_modules
/dist
/src/temp
Ensure the Astro project works in all modes:
- Run Astro dev mode
npm run dev
- Run Astro build mode
npm run build
npm run preview
- Run Sitecore Experience Editor
npm run dev
- Moving Vue.js components. When we have a new Astro JSS project we can move all Vue.js components from the Vue.js JSS project. In the default structure of the Vue.js JSS project, all components should be located in ./src/components folder. If you want to leave Astro components for future work, add the Vue components to a separate folder. If you don't need sample Astro components, remove them and add Vue.js components.
- Adding Vue.js component factory. The component factory automatically generates a file by
bootstrap
npm task. It finds all project components in the source and compiles them into one file for resolving renderings from the Sitecore Layout service. Every Sitecore JSS template package compilates only components of the current project type (Vue.js JSS only *.vue, Astro JSS only *.astro, etc.). For supporting Vue.js components we should update the current code of component factory generation or just move this code from migrating the Vue.js project (it is the simplest way)
- Copy the Vue Component factory generator from your Vue project ./scripts/generate-component-factory.js and include it to ./scripts/bootstrap.ts in Astro Project
/* GENERATE CONFIG */
import "./generate-config";
/* GENERATE COMPONENT FACTORY */
import "./generate-component-factory";
/* GENERATE VUE FACTORY */
import "./generate-vue-component-factory.js";
- Replace the name of the output Vue.js component factory file ./scripts/generate-vue-component-factory.js
const componentFactoryPath = path.resolve('src/temp/vueComponentFactory.js');
- Delete the code that removes the extension of the vue component file ./scripts/generate-vue-component-factory.js
imports.push(
`import ${importVarName} from '../components/${componentFile
.replace(path.join(componentRootPath, '/'), '')
.replace(/\\/g, '/')}';`
);
- Adding Vue.js Sitecore JSS Store Plugin. JSS Store Plugin is a specific pattern for a Vue.js JSS template that saves the data of the application state like Sitecore context and routing. Some components use the data set by the plugin ($jss object in code). If you don’t use the components depending on this object you can skip this step. You can use
SitecoreContextMap
object which is more natural for Astro and more lightweight and stable in general.
- add ./src/lib/SitecoreJssStorePlugin.js from the Vue project
- add the initialization script for the Vue application. We should create the script where Astro will initialize set the needed for the Vue.js app before starting. ./src/components/integrations/vue/initVueApp.ts
import type { App } from 'vue';
import componentFactory from '../../../temp/vueComponentFactory';
import SitecoreJssStorePlugin from '../../../lib/SitecoreJssStorePlugin';
import { SitecoreJssPlaceholderPlugin } from '@sitecore-jss/sitecore-jss-vue';
export default (app: App) => {
app.use(SitecoreJssPlaceholderPlugin, { componentFactory });
app.use(SitecoreJssStorePlugin);
};
- add the path of the created script as appEntryPoint for vue integration config in astro config ./astro.config.mjs
vue({
appEntrypoint: '/src/components/integrations/vue/initVueApp'
})
- If we use any Vue.js components directly in the layout, we need to import them. For our case, we want to use Vue.js navigation instead of Astro ones.
- Adopting application. Before switching components to Astro processing, we should remove/update specifically Vue.js functionality that is rudimental in the Astro project or generates any warnings/errors/conflicts.
- Vue allows the import of components without a file extension. Astro allows the same for Astro components. But, if we have two types of components (*.astro, *.vue) we should update the imports in the code to clarify for the application how to resolve every one of them (like Astro or like Vue). Adding of extension for imports will resolve it.:
- The next thing that should be adopted is routing: Astro has its own routing so we don't need Vue.js anymore. We should replace all
router-link
toa
andto
tohref
- Using the Vue.js
$jss
store can cause unexpected behavior on Astro. Better to useSitecoreContextMap
which exists in the Astro template out of the box. Replace all Vue$jss
usings in the Vue components to AstroSitecoreContextMap
import { SitecoreContextMap } from '@astro-sitecore-jss/astro-sitecore-jss';
...
computed: {
sitecoreContext() {
return SitecoreContextMap.get()["scContext"];
},
},
- Astro has a translation feature out of the box. We shouldn't migrate i18n Vue.js (or any other additional plugin) for translations provided by the dictionary service. We will a uniform translation approach across both Vue and Astro componentsю Update translation functionality to the Astro
useTranlsations
import { useTranslations } from '@astro-sitecore-jss/astro-sitecore-jss';
...
methods: {
$t(message) {
const t = useTranslations();
return t(message);
},
},
- If we use the Vue.js tracking component we should add the script that provides the data directly for it. You can skip this step if tracking components and functionality from the Vue.js JSS is not used in your project. Add tracking data Fetcher from the Vue project
import axios from 'axios';
/**
* Implements a data fetcher using Axios - replace with your favorite
* SSR-capable HTTP or fetch library if you like. See HttpDataFetcher<T> type
* in sitecore-jss library for implementation details/notes.
* @param {string} url The URL to request; may include query string
* @param {any} data Optional data to POST with the request.
*/
export function dataFetcher(url, data) {
return axios({
url,
method: data ? 'POST' : 'GET',
data,
// note: axios needs to use `withCredentials: true` in order for Sitecore cookies to be included in CORS requests
// which is necessary for analytics and such
withCredentials: true,
});
}
- Switch layout/(placeholder). After all preparations, we can switch the Astro Layout/Placeholder to the Vue.js Layout/Placeholder
- When all steps were done we should check if all functionality works stable and as expected. Run dev mode and check the Experience Editor. Then run build/preview mode and check the prod version.
Summary
After finishing migration we will be able to:
- use all the benefits of the Astro
- save exciting functionality of Vue.js components and continue to use them
- be able to replace Vue components if we would like to do it in the future or leave it as it is.
- continue the development on Vue.js
- continue the development of Astro
- use site static generation
- use all features of the Sitecore Experience editor mode for both Astro and Vue components
The whole process is pretty straightforward. If you don’t have complex customizations inside your Vue project, the initial phase could be finished very quickly. You will be able to start getting the best of two worlds: the blazing-fast Astro performance based on static site generation and complex client-side application logic using Vue.js.