Nuxt.js SEO Practises - vue.js

I am looking for ways to refactor this:
nuxt.config.js
const headConfig = require('./config/head')
const modulesConfig = require('./config/modules')
const config = {
head: headConfig,
(...)
}
module.exports = Object.assign({}, config, modulesConfig)
config/head.js
module.exports = {
meta: [
{charset: 'utf-8'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'},
{name: 'fb:app_id', content: 'xxxx'},
{hid: 'og:url', name: 'og:url', content: 'xxxx'},
{hid: 'og:type', name: 'og:type', content: 'website'},
{hid: 'og:image', name: 'og:image', content: 'xxxx'},
{hid: 'og:site_name', name: 'og:site_name', content: 'xxxx'},
{hid: 'keywords', name: 'keywords', content: 'xxxx'}
]
}
An example of what I'd like to be able to do is to automatically set the 'og:url' to the url of the page. There is no need to repeat that every time.
At the moment I include this in each page of my Nuxt.js app:
{
hid: 'og:url',
property: 'og:url',
content: 'https://website.com' + this.$route.fullPath
},
I am sure there is a better way to automatically set that somewhere :/

Probably your best bet would be to create a global Mixin:
https://v2.vuejs.org/v2/guide/mixins.html#Global-Mixin
This should allow you to create a head mixin that will be auto-imported into every component, so you could define that og:url once and have it auto-injected everywhere.
Here's an example of how you'd register it as a plugin with Nuxt:
/plugins/headMixin.js
import Vue from 'vue'
export default ({ route }) => {
Vue.mixin({
head() {
return {
meta: [
{
hid: `og:url`,
property: 'og:url',
content: 'https://www.yoursite.com' + route.fullPath
}
]
}
}
})
}
in nuxt.config.js:
plugins: [
'~/plugins/headMixin.js'
]

this is my way
in nuxt.config.js:
head: {
title: 'default title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: 'default description'
}
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
in default.vue
export default {
head() {
return {
title: `Company - ${this.$route.meta.title}`,
meta: [
{
hid: 'description',
name: 'description',
content: this.$route.meta.description
}
],
}
},
and if you use #nuxtjs/router in router.js
routes: [
{
path: '/page',
name: 'some',
meta: {
title: 'Best seo title',
description: 'Best seo description'
},
component: someComponent,
},
All the data you write in routes. Everything works perfectly.

Related

How to get config head setting to set page og:title in Nuxt2 (vue.js)?

I am using Nuxt.js to build my project.
I have set the head in nuxt.config.js and want to get the settings in the page.
// nuxt.config.js
export default {
...
head: {
title: 'SITE NAME',
titleTemplate: '%s | SITE NAME',
meta: [
{ charset: 'utf-8' },
{ 'http-equiv': 'X-UA-Compatible', content: 'IE=edge' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'SITE DESCRIPTION' },
{ hid: 'itemprop-name', itemprop: 'name', content: 'SITE NAME' },
{ hid: 'itemprop-description', itemprop: 'description', content: 'SITE DESCRIPTION' },
{ hid: 'itemprop-image', itemprop: 'image', content: process.env.BASE_URL + '/assets/img/og_img.png' },
{ hid: 'og:site_name', property: 'og:site_name', content: 'SITE NAME' },
{ hid: 'og:title', property: 'og:title', content: 'SITE NAME' },
{ hid: 'og:description', property: 'og:description', content: 'SITE DESCRIPTION' },
{ hid: 'og:url', property: 'og:url', content: process.env.BASE_URL },
{ hid: 'og:image', property: 'og:image', content: process.env.BASE_URL + '/assets/img/og_img.png' },
{ hid: 'og:image:width', property: 'og:image:width', content: '1200' },
{ hid: 'og:image:height', property: 'og:image:height', content: '630' },
{ hid: 'og:type', property: 'og:type', content: 'website' },
{ hid: 'twitter:card', name: 'twitter:card', content: 'summary_large_image' },
{ hid: 'twitter:title', name: 'twitter:title', content: 'SITE NAME' },
{ hid: 'twitter:description', name: 'twitter:description', content: 'SITE DESCRIPTION' },
{ hid: 'twitter:image', name: 'twitter:image', content: process.env.BASE_URL + '/assets/img/og_img.png' }
],
},
}
// about.vue (page.vue)
export default {
data () {
return {
pageTitle: 'PAGE TITLE',
description: 'PAGE DESCRIPTION',
}
},
head () {
return {
title: this.pageTitle,
meta: [
{ hid: 'description', name: 'description', content: this.description },
{ hid: 'itemprop-name', itemprop: 'name', content: `${this.pageTitle} | SITE NAME` },
{ hid: 'itemprop-description', itemprop: 'description', content: this.description },
{ hid: 'og:title', property: 'og:title', content: `${this.pageTitle} | SITE NAME` },
{ hid: 'og:description', property: 'og:description', content: this.description },
{ hid: 'twitter:title', name: 'twitter:title', content: `${this.pageTitle} | SITE NAME` },
{ hid: 'twitter:description', name: 'twitter:description', content: this.description }
]
}
}
}
I try to use this.title, this.$config, this.$route.meta, all of them are wrong.
How can I get the nuxt.config.js settings in the page?
Nuxt version: 2.14.5
Node version: 14.16.1
There is no declarative way to get all Nuxt configs that exist in the nuxt.config.js file.
head property in the nuxt.config.js is for adding general head elements to all your pages.
If you want to store a global configuration throughout the project for example the SITE NAME, you need to use publicRuntimeConfig
publicRuntimeConfig: {
siteName: 'SITE NAME'
}
Then you can use it in any component by this.$config.siteName
For more resources.
https://nuxtjs.org/docs/directory-structure/nuxt-config/#publicruntimeconfig

Nuxt SSR routing problem - [vue-router] Duplicate named routes definition

I am unable to fix the warnings displayed on the console:
this is my routes/index.js
module.exports = [
{
name:'shop-page',
path: '/sklepy/:id',
component: 'pages/shop-page.vue'
},
{
name: 'shops',
path: '/sklepy',
component: 'pages/shops-list-page.vue'
},
{
name: 'categories',
path: '/kategorie',
component: 'pages/category-list-page.vue'
},
{
name: "category-page",
path: '/kategorie/:id',
component: 'pages/category-page.vue'
},
{
name: 'rules',
path: '/regulamin',
component: 'pages/rules-page.vue'
},
{
name: 'privacy policy',
path: '/polityka-prywatnosci',
component: 'pages/privacy-policy-page.vue'
},
{
name: 'new password',
path: '/new-password',
component: 'pages/new-password-page.vue'
},
{
name: 'cookies policy',
path: '/polityka-cookies',
component: 'pages/cookies-page.vue'
},
{
name: 'email-confirmed',
path: '/email-confirmed',
component: 'pages/email-confirmed-page.vue'
},
]
And this is my nuxt.config.js
const routes = require('./routes/index.js')
export default {
css: [
'#/static/css/styles.css',
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
{ src: "#/plugins/filters.js" },
{ src: "#/plugins/axios.js" }
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/tailwindcss
'#nuxtjs/tailwindcss',
'#nuxtjs/composition-api/module'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'#nuxtjs/pwa',
'#nuxtjs/proxy',
'#nuxtjs/dotenv'
],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
proxy: true
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
},
proxy: {
'/api/': {
target: process.env.VUE_APP_ROOT_API,
pathRewrite: { '^/api': '' }
}
},
router: {
extendRoutes(nuxtRoutes, resolve) {
routes.forEach((route) => {
nuxtRoutes.push({
name: route.name,
path: route.path,
component: resolve(__dirname, route.component)
})
})
}
}
}
these problems probably cause that when I reload the page from url:
http://localhost:3000/shops/4kom
(then click F5, refresh the page), the following appears:
http://localhost:3000/shop-page
Please, help.
Ok, the solution is:
the name cannot be the same as component.
you don't need to loop routes inside nuxt.config.js. try this.
routes/index.js
const extendRoutes = (routes, resolve) => {
routes.push(
{
name:'shop-page',
path: '/sklepy/:id',
component: 'pages/shop-page.vue'
},
{
name: 'shops',
path: '/sklepy',
component: 'pages/shops-list-page.vue'
},
{
name: 'categories',
path: '/kategorie',
component: 'pages/category-list-page.vue'
},
{
name: "category-page",
path: '/kategorie/:id',
component: 'pages/category-page.vue'
},
{
name: 'rules',
path: '/regulamin',
component: 'pages/rules-page.vue'
},
{
name: 'privacy policy',
path: '/polityka-prywatnosci',
component: 'pages/privacy-policy-page.vue'
},
{
name: 'new password',
path: '/new-password',
component: 'pages/new-password-page.vue'
},
{
name: 'cookies policy',
path: '/polityka-cookies',
component: 'pages/cookies-page.vue'
},
{
name: 'email-confirmed',
path: '/email-confirmed',
component: 'pages/email-confirmed-page.vue'
},
);
};
export default extendRoutes;
nuxt.config.js
import extendRoutes from "./routes/index.js";
export default {
router: {
extendRoutes
},
}

Vue named views with lazy loading

I am trying to create my routes, but I want them to all use the default router-view in my app.
Looking at the documentation:
https://router.vuejs.org/guide/essentials/named-views.html
I should be able to target views by doing something like this:
const routes = [
{
path: "/",
name: "home",
component: {
default: Home
},
},
]
I want to do this with a child, so I did this:
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: Categories,
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: { default: ProductList },
],
},
],
},
I get no compile errors, but when navigating to /categories/televisions it only shows the Categories component, not the ProductList.
So my first question is, can children target app level router-view?
I also tried to add a new router-view like this:
<router-view />
<router-view name="root" />
and then updated my routes to this:
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: Categories,
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: { root: ProductList },
},
],
},
But this didn't work either.
If it is possible to do this, then my next question, which is where I am heading.
Can I use lazy loaded components and target named/default router-views?
For example, I have this function:
const lazyLoad = (name) => {
return () => import(`../views/${name}/${name}.component.vue`);
};
Which I call from my routes like this:
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: lazyLoad("categories"),
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: lazyLoad("product-list"),
},
],
},
Can I do it like this?
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: lazyLoad("categories"),
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: { default: lazyLoad("product-list") },
},
],
},
and target the root router-view?

nuxt meta robots set to noindex when in production mode

I don't understand why my app has meta robots set to noindex when I'm in production mode only ??
Here is my nuxt.config
import i18n from './config/i18n'
export default {
head: {
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ hid: 'robots', name: 'robots', content: 'index, follow' }
],
},
buildModules: ['nuxt-lazysizes',
[
'nuxt-i18n',
{
strategy: 'prefix_except_default',
defaultLocale: 'en',
seo: true,
baseUrl: envBaseUrl,
locales: [
{
code: 'en',
name: 'English',
iso: 'en-GB'
},
{
code: 'fr',
name: 'Français',
iso: 'fr-FR'
}
],
vueI18n: i18n
}
]
],
env: {
baseUrl: envBaseUrlAdmin
},
}
I even set the meta in the layout /default.vue just in case, but still the same.
This is driving me insane !!
It's perfectly fine in dev mode. Why would any one want production with no index and dev or staging with it ? This is absurd.
head () {
return {
meta: [{ hid: 'robots', name: 'robots', content: 'index, follow' }],
}
}
Ok, it was a conflict with my Yoast plugin. Haven't found why it was only doing this in prod, and not in dev, but it's fine now. Sorry for the dumb question.

Overwrite ManifestsMeta Data

I have a Manifest with stuff like name etc. which also instantly brings out meta tags for my page. Now I wanna use Meta Tags on my individual Pages, the problem is that the Manifest Meta Tags dont get overwritten which leads to them having higher priority for sites like Facebook etc.
Example Manifest:
manifest: {
theme_color: '#1a1a1a',
name: 'Stackoverflow',
short_name: 'SO',
description: 'Questions and Answers',
lang: 'de'
},
Example change in the Page:
head () {
return {
meta: [
{ name: 'og:url', content: 'www.notstackoverflow.com' },
{ name: 'og:type', content: 'article' },
{ name: 'og:title', content: this.post.titel },
{ name: 'og:description', content: this.post.subtitel },
]
}
},
The problem is that it still uses the title and description from the manifest instead of the page. It only adds the ones from the page after the manifest ones if I go on View Source.
(Nuxt + PWA Module)
you must add the hid property for each meta:
head () {
return {
meta: [
{ hid: 'og:url', name: 'og:url', content: 'www.notstackoverflow.com' },
{ hid: 'og:type', name: 'og:type', content: 'article' },
{ hid: 'og:title', name: 'og:title', content: this.post.titel },
{ hid: 'og:description', name: 'og:description', content: this.post.subtitel },
]
}
},
see https://nuxtjs.org/faq/duplicated-meta-tags
To avoid any duplication when used in child component, please give a unique identifier with the "hid" key.