Do you know about Hulu's fail story? JavaScript Back in 2016, the online video streaming service experienced a . 56% visibility drop due to bad JS handling A nightmare no business wants to go through. To avoid such disasters, you have to know what you're doing when working with modern JavaScript frameworks. Here at Snipcart, , but are entirely aware of the issues with a Vue.js singe-page application. we love Vue.js SEO In this post, I want to show JS developers how easy it is to make Vue SEO-friendly. I'll go through: General SEO tips you should always apply. Specific Vue.js SPA SEO issues. Tools to fix them with server-rendering & prerendering. A technical Vue.js SEO example using . prerender-spa-plugin This post was followed by two other pieces about JS frameworks SEO issues, , and . for React Angular General SEO tips Before we explore SEO issues specific to JavaScript SPAs, let's cover the best practices developers should adopt when building search engine optimized sites. As someone already said: “The best place to hide a dead body is the second page of Google search.” This shortlist is inspired by some of the biggest SEO players such as Moz, Backlinko, and Ahrefs. I've added links to their resources should you want to dig deeper. → Meta tags 🏷️ Meta tags are low-hanging fruits. They let you show search engines precisely what your content is about. However, not all tags are born equal. You should focus your energy on only a few of them, namely: —Has to be present on every page, declares your character set for the page. Meta content type —Choose a unique title that catches searchers attention while accurately describing the content of the page. Keep it concise! Title —It should convince SERP (Search Engine Results Page) visitors to click on your link to find answers to their specific research intent. Meta description —Essential for a good mobile experience. Viewport Learn more: , by Moz. SEO Meta Tags is a solid tool to manage page meta info in Vue 2.0 components. vue-meta can also have a significant impact on SEO as they help your content to spread on social platforms, thus increasing your SEO social signals. There are specific tags for all the big platforms (Facebook, Twitter, Pinterest, Google+). Social tags Learn more: , by Moz. Must-Have Social Meta Tags for Twitter, Google+, Facebook, and More → Mobile optimization 📱 If you're not aware of , well, consider this a wake-up call! Google is now giving more love to smooth mobile experiences than desktop ones, and so should you. Google's mobile-first indexing Learn more: , by Backlinko. Mobile SEO: The Definitive Guide powers cross-platorm Vue.js mobile apps. NativeScript → HTTPS 🛡️ A missing HTTPS certification or a broken config could penalize your website. Isn't it understandable that search engines are inclined to push sites that are trusted and certified, after all? Even if it wasn't for SEO, you probably want to offer a platform as secure as possible for your users. So no reason not to meet this criterion! Learn more: by ahrefs. HTTP vs. HTTPS for SEO: What You Need to Know to Stay in Google’s Good Graces → Page speed 🚀 People's attention span is short—searchers are quick to abandon slow-loading pages. Google knows that and, to offer the best UX to searchers, will penalize slow sites. Googlebots themselves are pretty impatient and won't wait for a script . If you don't meet this timeout, you risk not getting your content rendered adequately. Speed it up! longer than 5 seconds Learn more: , by Moz. On-Site SEO: Page Speed → Sitemap 🗺️ A sitemap act as a map of your site's architecture for searchbots. Included in it should be the pages you consider to be good-quality landing & navigation pages, worthy of indexation. Sitemaps might not be that useful for smaller websites, but it's still a valuable SEO tool to consider. Learn more: , by Moz. XML Sitemaps: The Most Misunderstood Tool in the SEO's Toolbox You can generate a sitemap.xml by . vue-router configuration → Link building ⛓️ Building your domain authority remains a key SEO tactic. How does Google know that you've become an authoritative resource? By having other relevant domains linking to yours. There's no secret formula here, . Content that others want to share and use as a resource on their own site! to accomplish this you need to work hard at crafting great content The more links you get from relevant sources, the more your authority will rise, the more you'll earn Google favors when it comes to rankings. Learn more: , by Backlinko. Link Building for SEO: The Definitive Guide Specific Vue.js SPA SEO issues For the following tutorial, I decided to use the blog demo we made in an earlier post because, honestly, it looks awesome. If you're interested in knowing how it was built, see . this post Although it's a great piece of work visually, it's not set up ideally SEO-wise. It's a complete SPA that search engines might have a hard time crawling & indexing. Why is that? A single-page application adds content to pages dynamically, which has its benefits, but brings two significant issues: . They've been saying for a few years now that Googlebots are capable of doing so. However, these claims are always followed by a "but" or two. We don't really know to which extent Google is able to crawl and correctly render JS . If things are still shaky on its side, we know for a fact that the other players out there don't crawl JS yet, thus not encountering the actual content of the page. Google isn't the only search engine out there So there's no way around it. If you want to make sure your Vue.js website/app ranks on SERPs, you have to act on it. Your options? Server-side rendering With a SSR setup, you have the rendering logic done directly in the backend, in a Node.js environment. HTML views are then returned to the client, ready to be served to search bots. It's excellent for time-sensitive apps where you want to offload as much logic as possible on the server, but comes with a cost. You're going to need a robust infrastructure to handle the stress added to the server, asking for more development time. You might also slow down your system in the process. But if you can handle it, it's definitely the way to go for bigger apps. is without a doubt the tool to use for your . Nuxt.js server-rendered Vue.js SPA Nuxt.js rendering process [source] Prerendering Sometimes though, server-side rendering might feel overkill, like in my demo's case. For a small SPA with only a few pages, prerendering will do the trick just fine. Even more so if your only concern is SEO. This way, there's no need to attach your Vue.js app to any server. Rendering is done client-side with the use of such as: third-party plugins - Compatible with all the most popular JS frameworks, including Vue.js. Prerender.io - A webpack plugin that will compile your pages into static pages. Makes all the content available in the source, and indexing is a breeze. prerender-spa-plugin The latter is very easy to use and was build by a Vue.js core team member, so it suits my use case perfectly here. Vue.js SEO technical example using prerendering Time to fix the Vue.js blog shown earlier. Using , I'll have a Vue.js SPA that's in Google's good graces in no time. [prerender-spa-plugin](https://github.com/chrisvfritz/prerender-spa-plugin) Prerequisites Basic knowledge of Vue.js Node.js & npm installations 1. Installing prerender-spa-plugin Configuring the plugin is very easy. In this setup, I'll run the plugin only when building for production. You don't need prerendering when actively developing components. Start by installing the plugin from npm. npm install prerender-spa-plugin Then, open the file. There, you'll find custom things for production build. You'll need to import the plugin and add these lines at the top of the file: build/build.js Why ? Because you'll need to customize the renderer. You need to inject some data to let the application know when it's being prerendered. There are things like Disqus comments that you won't be able to prerender. PrerenderSPAPlugin.PuppeteerRenderer In a 100% SEO-friendly app it would be preferable to benefit from these comments as rendered content on your pages. If your working with a static site generator, you should consider for static user-generated content. Staticman You'll need to fetch all your blog entries and generate a list of routes that will be prerendered. In a real production scenario, you'd probably want to call your headless CMS API or an external service that provides your content. In this case, the data lives in simple JSON files. Read the file and generate your routes: feed.json Add the plugins to webpack configuration: You'll have access to the variable when the site is prerendering. This will be useful to exclude content you don't want to prerender. window.__PRERENDER_INJECTED.prerendered You also need to specify the wait for the event. app.rendered In this demo, I'll use , which is an awesome library to add a progress bar on a site quickly. However, you need to make sure the loading is complete before prerendering the site if not, you'll end up getting a random progress bar on multiple pages. [Pace](https://github.hubspot.com/pace/docs/welcome/) 2. Configuring Vue.js for prerender You'll then need to apply some minor changes in some components. To do so, I changed the way Pace was started. I got rid of the file and put everything in . startup.cs main.js Open the file and change how your components are included: main.js App Once your main component is mounted, start and dispatch the event when initial loading is completed. Pace app.rendered The last update you have to do is to make sure Disqus is not loaded when the site is being prerendered. Open file where you'll include the Disqus component. BlogPost.vue Because of the way the was configured at first, you'll have access to a variable that indicates you that the site is being prerendered. prerender-spa-plugin Update the method this way: showComments 3. Building your SEO-friendly Vue.js site You're now ready to build your site. In your terminal use this command: npm run build Then, if you look at the folder, you should see all the posts in the folder. A static HTML file has been generated for each post: dist read That's it! How easy was that, right? Live demo, Github repo See the live demo here See GitHub repo here Closing thoughts is a neat plugin. It's effortless to configure and flexible enough to handle async use cases like the one we had with . prerender-spa-plugin Pace I spent about 2 hours to figure out how to wire all these things together and update our initial application to support prerendering. As I mentioned earlier, the plugin is straightforward and best suited for simple applications like a static blog. If you want to build something more complicated, I'd suggest you look at Nuxt instead! If you enjoyed this post, please take a second to share it on Twitter. Got comments, questions? Hit the section below! I originally published this post on the Snipcart blog and shared it in our newsletter .