diff --git a/packages/@vuepress/core/lib/client/index.ssr.html b/packages/@vuepress/core/lib/client/index.ssr.html
index 1c5e66bc8c..351c008efe 100644
--- a/packages/@vuepress/core/lib/client/index.ssr.html
+++ b/packages/@vuepress/core/lib/client/index.ssr.html
@@ -4,7 +4,6 @@
{{ title }}
-
{{{ userHeadTags }}}
{{{ pageMeta }}}
diff --git a/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js b/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js
index bfa818be2d..5b5228c138 100644
--- a/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js
+++ b/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js
@@ -1,15 +1,26 @@
+import unionBy from 'lodash/unionBy'
+
export default {
+ // created will be called on both client and ssr
created () {
+ this.siteMeta = this.$site.headTags
+ .filter(([headerType]) => headerType === 'meta')
+ .map(([_, headerValue]) => headerValue)
+
if (this.$ssrContext) {
+ const mergedMetaItems = this.getMergedMetaTags()
+
this.$ssrContext.title = this.$title
this.$ssrContext.lang = this.$lang
- this.$ssrContext.description = this.$page.description || this.$description
+ this.$ssrContext.pageMeta = renderPageMeta(mergedMetaItems)
}
},
-
+ // Other life cycles will only be called at client
mounted () {
+ // init currentMetaTags from DOM
+ this.currentMetaTags = [...document.querySelectorAll('meta')]
+
// update title / meta tags
- this.currentMetaTags = new Set()
this.updateMeta()
},
@@ -17,22 +28,17 @@ export default {
updateMeta () {
document.title = this.$title
document.documentElement.lang = this.$lang
- const userMeta = this.$page.frontmatter.meta || []
- const meta = userMeta.slice(0)
- const useGlobalDescription = userMeta.filter(m => m.name === 'description').length === 0
-
- // #665 Avoid duplicate description meta at runtime.
- if (useGlobalDescription) {
- meta.push({ name: 'description', content: this.$description })
- }
- // Including description meta coming from SSR.
- const descriptionMetas = document.querySelectorAll('meta[name="description"]')
- if (descriptionMetas.length) {
- descriptionMetas.forEach(m => this.currentMetaTags.add(m))
- }
+ const newMetaTags = this.getMergedMetaTags()
+ this.currentMetaTags = updateMetaTags(newMetaTags, this.currentMetaTags)
+ },
- this.currentMetaTags = new Set(updateMetaTags(meta, this.currentMetaTags))
+ getMergedMetaTags () {
+ const pageMeta = this.$page.frontmatter.meta || []
+ // pageMetaTags have higher priority than siteMetaTags
+ // description needs special attention as it has too many entries
+ return unionBy([{ name: 'description', content: this.$description }],
+ pageMeta, this.siteMeta, metaIdentifier)
}
},
@@ -47,14 +53,20 @@ export default {
}
}
-function updateMetaTags (meta, current) {
- if (current) {
- [...current].forEach(c => {
+/**
+ * Replace currentMetaTags with newMetaTags
+ * @param {Array