All Projects → based-ghost → vue-seo-friendly-spa-template

based-ghost / vue-seo-friendly-spa-template

Licence: MIT license
Vue.js PWA/SPA template initially scaffolded with vue-cli and configured for SEO. Makes use of prerendering and other techniques/packages in order to achieve a perfect "Lighthouse Score".

Programming Languages

Vue
7211 projects
typescript
32286 projects
SCSS
7915 projects
javascript
184084 projects - #8 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to vue-seo-friendly-spa-template

react-seo-friendly-spa-template
React PWA/SPA template initially scaffolded with CRA (Create React App) and configured for SEO. Makes use of prerendering and other techniques/packages in order to achieve a perfect "Lighthouse Score".
Stars: ✭ 24 (-41.46%)
Mutual labels:  spa, google-analytics, seo, prerender, netlify, lighthouse, netlify-deployment
vuetibook
Integrating Vue.js, Vuetify and Storybook
Stars: ✭ 16 (-60.98%)
Mutual labels:  spa, vue-router, netlify
Todolist Frontend Vuejs
Front-end application for Todolist Web application built with Laravel and Vue.js
Stars: ✭ 120 (+192.68%)
Mutual labels:  spa, vue-router, netlify
parcel-plugin-prerender
No description or website provided.
Stars: ✭ 42 (+2.44%)
Mutual labels:  spa, seo, prerender
Prerender Spa Plugin
Prerenders static HTML in a single-page application.
Stars: ✭ 7,018 (+17017.07%)
Mutual labels:  spa, seo, prerender
Vue Spa Project
vue.js + vuex + vue-router + fetch + element-ui + es6 + webpack + mock 纯前端SPA项目开发实践
Stars: ✭ 118 (+187.8%)
Mutual labels:  spa, vue-router
Vue Soundcloud
🎧 A SoundCloud client built with Vue and Nuxt
Stars: ✭ 141 (+243.9%)
Mutual labels:  spa, vue-router
Vue Stack 2.0
Vue 2.0 Project Boilerplate
Stars: ✭ 166 (+304.88%)
Mutual labels:  spa, vue-router
Productivity Frontend
Productivity Application - Kanban Style Productivity Management Application with Customizable Boards, Lists and Cards to Make You More Productive.
Stars: ✭ 234 (+470.73%)
Mutual labels:  spa, netlify
Running Time
Sample Single Page Application using Laravel & Vue.js + Vuex + Vue-Router
Stars: ✭ 90 (+119.51%)
Mutual labels:  spa, vue-router
Symfony Vuejs
Source code of the tutorial "Building a single-page application with Symfony 4 and Vue.js"
Stars: ✭ 170 (+314.63%)
Mutual labels:  spa, vue-router
seo-audits-toolkit
SEO & Security Audit for Websites. Lighthouse & Security Headers crawler, Sitemap/Keywords/Images Extractor, Summarizer, etc ...
Stars: ✭ 311 (+658.54%)
Mutual labels:  seo, lighthouse
Vue Laravel Spa
Single Page Application made with Vue.JS2, Vue Router, Vuex and Laravel 5.6.
Stars: ✭ 107 (+160.98%)
Mutual labels:  spa, vue-router
Rendora
dynamic server-side rendering using headless Chrome to effortlessly solve the SEO problem for modern javascript websites
Stars: ✭ 1,853 (+4419.51%)
Mutual labels:  spa, seo
Vuejs Wordpress Theme Starter
A WordPress theme with the guts ripped out and replaced with Vue.
Stars: ✭ 1,359 (+3214.63%)
Mutual labels:  spa, vue-router
Mmf Blog Vue2
mmf-blog vue2.0 (vue2, vue-router, vuex)
Stars: ✭ 232 (+465.85%)
Mutual labels:  spa, vue-router
playwright-lighthouse
🎭: Playwright Lighthouse Audit
Stars: ✭ 120 (+192.68%)
Mutual labels:  seo, lighthouse
site
RailroadPM.org 2.x Site
Stars: ✭ 18 (-56.1%)
Mutual labels:  spa, netlify
Laravel-Vue-SPA-template
Template for Single Page Applications built with Laravel and Vue.
Stars: ✭ 22 (-46.34%)
Mutual labels:  spa, vue-router
next-netlify-starter
A one-click starter project for Next and Netlify
Stars: ✭ 76 (+85.37%)
Mutual labels:  netlify, netlify-deployment

vue-seo-friendly-spa-template

Built using Vue 3.0.

Vue.js PWA/SPA template configured for SEO (initially scaffolded with vue-cli). You can find the React version here: react-seo-friendly-spa-template.

Features:

  • TypeScript
  • Custom BackToTop.vue component that uses vue-scrollto
  • Custom ToggleTheme.vue component that handles light/dark theme transitions
  • Google analytics management with vue-gtag-next
  • Route meta tag management with vue-meta
  • Configured to serve prerendered static HTML with prerender-spa-plugin

Demo

demo

General Overview

This template reflects some of the setup I went through when experimenting with the creation of my own static front-end personal site that was to be hosted on Netlify (using GitHub as a repository/pipeline). You can find that experiment live here. After playing around with this process I figured I'd build a higher-level abstraction of that project for quick re-use in the future.

Technology Stack Overview

vue-cli

initial scaffolding

vue-meta

vue-meta - plugin that allows you to manage your app's meta information, much like react-helmet does for React. However, instead of setting your data as props passed to a proprietary component, you simply export it as part of your component's data using the metaInfo property.

I have meta data configured to be handled via a simple, reusable compostion (@/composables/useMetaRoute.ts) - simply import and execute this composable function in the setup function of your component and it will attempt to resolve any meta data definitions you configure for that route:

useMetaRoute.ts

import { useRoute } from 'vue-router';
import { useMeta, type MetaSourceProxy } from 'vue-meta';

export default function useMetaRoute(): MetaSourceProxy {
  const route = useRoute();
  const { title, description } = route?.meta ?? {};
  const url = window?.location.href || 'unknown';

  const { meta } = useMeta({
    title,
    description,
    link: {
      rel: 'canonical',
      href: url
    },
    og: {
      url,
      title,
      description
    }
  });

  return meta;
}

About.vue

<script setup>
  import { Alert } from '@/components';
  import { useMetaRoute } from '@/composables';

  useMetaRoute();
</script>

vue-gtag-next

vue-gtag-next - The global site tag (gtag.js) is a JavaScript tagging framework and API that allows you to send event data to Google Analytics, Google Ads, and Google Marketing Platform.

Inititial plugin configuration found in config/vue-gtag.config.ts and then hooked up in the setup function of the application's root component (App.vue).

vue-gtag.config.ts

import type { Options } from 'vue-gtag-next';

const isEnabled = true;
const isProduction = process.env.NODE_ENV === 'production';
const useDebugger = isEnabled && !isProduction;

export const VUE_GTAG_OPTIONS: Options = {
  isEnabled,
  useDebugger,
  property: {
    id: 'UA-000000-01',
    params: {
      send_page_view: false,
    }
  }
};

App.vue

<script setup>
  import { watch, unref } from 'vue';
  import { useRouter } from 'vue-router';
  import { useGtag } from 'vue-gtag-next';
  import { useActiveMeta } from 'vue-meta';

  const router = useRouter();
  const { pageview } = useGtag();
  const activeMeta = useActiveMeta();

  function trackPageView() {
    setTimeout(() => {
      const { currentRoute, getRoutes } = router;
      const { path } = unref(currentRoute);
      const isValidPath = getRoutes().some((x) => x.path === path);

      if (isValidPath) {
        pageview(path);
      }
    }, 10);
  }

  watch(
    () => activeMeta,
    () => trackPageView(),
    { deep: true }
  );
</script>

prerender-spa-plugin

prerender-spa-plugin - Prerenders static HTML in a single-page application. This is a more straightforward substitue for SSR (Server Side Rendering) and the primary benefit is SEO.

Configured in the app as follows:

vue.config.js

const path = require("path");
const cheerio = require("cheerio");
const PrerenderSPAPlugin = require("prerender-spa-plugin-next");
const PuppeteerRenderer = require("@prerenderer/renderer-puppeteer");

module.exports = {
  lintOnSave: false,

  // define port
  devServer: {
    port: "3000",
    hot: true,
  },

  configureWebpack: (config) => {
    if (process.env.NODE_ENV !== "production") {
      return {};
    }

    return {
      performance: {
        hints: false,
      },
      plugins: [
        // https://github.com/chrisvfritz/prerender-spa-plugin
        new PrerenderSPAPlugin({
          staticDir: config.output.path,
          routes: ["/", "/about"],
          renderer: PuppeteerRenderer,
          postProcess(context) {
            if (context.route === "/404") {
              context.outputPath = path.join(config.output.path, "/404.html");
            }

            // Add 'data-server-rendered' attribute so app knows to hydrate with any changes
            const $ = cheerio.load(context.html);
            $("#app").attr("data-server-rendered", "true");
            context.html = $.html();

            return context;
          },
        }),
      ],
    };
  }
};

Remainder of the configuration takes place in vue.config.js file where the plugin is added and configured. In the postProcess callback I am editing the prerendered content using cheerio so you can load the raw prerendered html string into a usable document and modify it using JQuery-like syntax, rather than parsing a long string and calling .replace().

Note: I found that dynamically adding the data-server-rendered='true' attribute in the postProcess (rather than hard-coding in the index.html file) seems to work well - this lets the client know that this nodes contents was served as prerendered content and to hydrate the HTML with updates, rather than re-render/replace.

Scripts

Project setup

npm install

Compiles and hot-reloads for development

npm run serve

Compiles and minifies for production

npm run build

Lints and fixes files

npm run lint
  • Run the linter (configured in the tslint.json file found in the root of this project)

Generate sitemap.xml file

npm run sitemap
  • This command will execute code in the sitemap-generator.js. Using the sitemapUrl parameter defined in that file (should reflect your registered domain name) a sitemap.xml is generated and persisted under the 'public' folder - this file is referenced in the robots.txt file. This uses the sitemap-generator package.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].