The SEO discover for Vuejs
SEO is a indispensable part for websites. A good SEO can help website to be indexed easily by search engine. My website is built by Vuejs and hosting on firebase. In this article, I will share the SEO experience on:
1. sitemap
2. custom 404 page
3. facebook open graph
4. asset cache ability
If you are interesting in other SEO topics, you can check:
Sitemap
Sitemap can help search engines to know which pages are important and relevant on site. However, search engine can’t recognize sitemap which includes # links. Therefore, I suggest to use vue-router history mode to develop web application.
const router = new VueRouter({
mode: 'history',
routes: [...]
})
To generate the sitemap.xml, we use the sitemap webpack plugin
// webpack.config.prod.jsconst SitemapPlugin = require('sitemap-webpack-plugin').default;
const prettydata = require('pretty-data');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.config.base');const paths = [
'/'
'/docs',
'/pricing',
'/about'
]const prettyPrint = xml => {
const result = prettydata.pd.xml(xml);
return result;
};const config = merge(baseWebpackConfig, {
mode: 'production',
plugins: [
new SitemapPlugin('https://my.website.com/', paths, {
changeFreq: 'monthly',
skipGzip: true,
formatter: prettyPrint,
}),
],
});
After deploying the sitemap, we can go to search console to add the sitemap reference.
If your sitemap can’t be indexed successfully, goto Crawl → Crawl Errors to see the detail messages and use Fetch as Google to check whether the page is rendered successfully or not.
Custom 404 page
If user try to visit the none-exist url of website, we should give user a custom 404 page. It can reduce user frustration and help user to find out which part they can visit on website. ( reference: Great 404 error pages)
Example:
Implementation:
Using vue-router history mode only handle 1 case for 404 not found page. (e.g. https://mysite.com/page/not/found). When we set the vue-router to history mode, we should catch-all fallback route to server. Here is the example for firebase hosting configuration:
// firebase.json{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Bue, how to catch-all fallback in development ?
we use the devSer.historyApiFallback to configure webpack file.
// webpack.config.dev.jsconst config = merge(baseWebpackConfig, {
mode: 'development',
devServer: {
contentBase: path.join(__dirname, 'static'),
historyApiFallback: {
index: '/your-public-path/'
}
}
});
Now, we can implement a catch-all route to show a 404 page.
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '*', component: NotFoundComponent }
]
})
Facebook Open Graph
Facebook Open Graph can enrich website content when we sharing the link on social medias. ( use Facebook debug tool to verify after adding the meta tags.)
<meta property="og:site_name" content="My Website"/>
<meta property="og:type" content="article"/>
<meta property="og:title" content="my website title"/>
<meta property="og:url" content="https://my.website.com/">
<meta property="og:description" content="my website description"/>
<meta property="og:image" content="https://my.storage/image.png"/>
Ideally, we want to add different meta tags to each page. However, Vuejs is Single Page Application (SPA), which means all links are handled by single route. The crawler don’t run our Javascript to find the meta data. Therefore, we need to simulate the static HTML files for each route.
There are two common approaches to solve SPA problems
- Prerendering
- Server-Side Rendering
Prerendering is a methods to generate static HTML files to each route at build time. It’s a simpler solution than Server-Side Rendering. Following is the example webpack configurations which use prerender-spa-plugin.
// webpack.config.prod.jsconst config = merge(baseWebpackConfig, {
mode: 'production',
....
plugins: [
new PrerenderSPAPlugin({
staticDir: path.resolve(__dirname, 'dist/'),
routes: ['/', '/about', '/docs'],
postProcess(context) {
context.path = context.originalPath;
const titles = {
'/': 'My Website',
'/about': 'DeepQ AI Platform - About',
'/docs': 'DeepQ AI Platform - Docs',
};
const desc = {
'/': 'Home Page Descriptions',
'/about': 'About Page Descriptions',
'/docs': 'Docs Page Descriptions',
}; context.html = context.html.replace(
/<title>[^<]*<\/title>/i,
'<title>' + titles[context.route] + '</title><meta name="description" content="'+desc[context.route]+'">'
);
return context;
},
}),
],
});
Although prerender-spa-plugin is easy to use, it’s not perfect. It can’t support multi-language. It’s hard to maintain when website has a large amount of routes.
Browser Caching
Consider the web performance and user experience, we don’t want user download assets every time. Therefore, we need to set cache to static files.
// firebase.json"headers": [ {
"source" : "**/*.@(jpg|jpeg|gif|png)",
"headers" : [ {
"key" : "Cache-Control",
"value" : "max-age=7200"
} ]
}, {
// Sets the cache header for 404 pages to cache for 5 minutes
"source" : "404.html",
"headers" : [ {
"key" : "Cache-Control",
"value" : "max-age=300"
} ]
} ]
Summary
In conclusion, for a vue developer to do SEO I will suggest:
- vue-router use history mode
- let sitemap.xml can be indexed by google search engine
- handle the single case for 404 not found page
( in hash mode, you need to handle https://mysite.com/page/not/found/# and https://mysite.com/#/page/not/found)
2. If your website is a static or small website, I recommend to use prerender-spa-plugin to add meta-tags to each route.