2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-06-06 20:12:29 +03:00

chore: prepare ssr example

This commit is contained in:
pimlie
2021-01-19 12:22:57 +01:00
parent e68b53573e
commit 2e2c08e1f8
19 changed files with 195 additions and 330 deletions
+2 -2
View File
@@ -10,8 +10,8 @@
<!-- li><a href="basic">Basic</a></li>
<li><a href="basic-render">Basic Render</a></li>
<li><a href="keep-alive">Keep alive</a></li>
<li><a href="multiple-apps">Usage with multiple apps</a></li>
<li><a href="ssr">SSR</a></li -->
<li><a href="multiple-apps">Usage with multiple apps</a></li -->
<li><a href="ssr">SSR</a></li>
<li><a href="vue-router">Usage with vue-router</a></li>
<!-- li><a href="vuex">Usage with vuex</a></li>
<li><a href="vuex-async">Usage with vuex + async actions</a></li>
+1 -1
View File
@@ -3,7 +3,7 @@ import VueMeta from 'vue-meta'
Vue.use(VueMeta)
Vue.component('child', {
Vue.component('Child', {
name: 'Child',
props: {
page: {
+1 -1
View File
@@ -3,7 +3,7 @@ import VueMeta from 'vue-meta'
Vue.use(VueMeta)
Vue.component('foo', {
Vue.component('Foo', {
template: '<p>Foo component</p>',
metaInfo: {
title: 'Keep me Foo'
+1 -1
View File
@@ -39,10 +39,10 @@ app.use((req, res, next) => {
if (req.url.endsWith('.js')) {
res.setHeader('Content-Type', 'application/javascript')
res.send('')
next()
} else if (req.url.endsWith('.css')) {
res.setHeader('Content-Type', 'text/css')
res.send('')
} else {
next()
}
})
-161
View File
@@ -1,161 +0,0 @@
import { createSSRApp } from 'vue'
import { createRouter, createMemoryHistory } from 'vue-router'
/* Vue.use(Router)
Vue.use(VueMeta, {
tagIDKeyName: 'hid'
}) */
export default function createMyApp () {
const Home = {
template: `<div>
<router-link to="/about">About</router-link>
<p>Hello World</p>
</div>`,
metaInfo: {
title: 'Hello World',
meta: [
{
hid: 'og:title',
name: 'og:title',
content: 'Hello World'
},
{
hid: 'description',
name: 'description',
content: 'Hello World'
}
]
}
}
const About = {
template: `<div>
<router-link to="/">Home</router-link>
<p>About</p>
</div>`,
metaInfo: {
title: 'About World',
meta: [
{
hid: 'og:title',
name: 'og:title',
content: 'About World'
},
{
hid: 'description',
name: 'description',
content: 'About World'
}
]
}
}
const router = createRouter({
history: createMemoryHistory('/ssr'),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
const app = createSSRApp({
router,
metaInfo () {
return {
title: 'Boring Title',
htmlAttrs: { amp: true },
bodyAttrs: { class: 'main-app' },
meta: [
{
skip: this.count < 1,
hid: 'og:title',
name: 'og:title',
template: chunk => `${chunk} - My Site`,
content: 'Default Title'
},
{
hid: 'description',
name: 'description',
content: 'Say something'
}
],
script: [
{
hid: 'ldjson-schema',
type: 'application/ld+json',
innerHTML:
'{ "@context": "http://www.schema.org", "@type": "Organization" }'
},
{
type: 'application/ld+json',
innerHTML: '{ "body": "yes" }',
body: true
},
{
hid: 'my-async-script-with-load-callback',
src: '/user-1.js',
body: true,
defer: true,
callback: this.loadCallback
},
{
skip: this.count < 1,
src: '/user-2.js',
body: true,
callback: this.loadCallback
}
],
__dangerouslyDisableSanitizersByTagID: {
'ldjson-schema': ['innerHTML']
}
}
},
data () {
return {
count: 0,
users: process.server ? [] : window.users
}
},
mounted () {
const { set, remove } = this.$meta().addApp('client-only')
set({
bodyAttrs: { class: 'client-only' }
})
setTimeout(() => remove(), 3000)
},
methods: {
loadCallback () {
this.count++
}
},
template: `
<div id="app">
<p>{{ count }} users loaded</p>
<ul>
<li
v-for="user in users"
:key="user.id"
>
{{ user.id }}: {{ user.name }}
</li>
</ul>
<router-view />
</div>`
})
app.use(router)
/* const { set } = app.$meta().addApp('custom')
set({
bodyAttrs: { class: 'custom-app' },
meta: [{ charset: 'utf-8' }]
}) */
return { app, router }
}
+5 -2
View File
@@ -1,6 +1,9 @@
import createApp from './App'
import { createApp } from 'vue'
import { App, createRouter, metaManager } from '../vue-router/main'
window.users = []
const { app } = createApp()
const app = createApp(App)
app.use(createRouter('/ssr'))
app.use(metaManager)
app.mount('#app')
+11 -3
View File
@@ -1,8 +1,9 @@
import path from 'path'
import fs from 'fs-extra'
import { createSSRApp } from 'vue'
import template from 'lodash/template'
import createApp from './App'
const { renderToString } = require('@vue/server-renderer')
import { renderToString } from '@vue/server-renderer'
import { App, createRouter, metaManager } from '../vue-router/main'
const templateFile = path.resolve(__dirname, 'app.template.html')
const templateContent = fs.readFileSync(templateFile, { encoding: 'utf8' })
@@ -13,11 +14,18 @@ const compiled = template(templateContent, { interpolate: /{{([\s\S]+?)}}/g })
process.server = true
export async function renderPage ({ url }) {
const { app, router } = await createApp()
console.log('renderPage', url)
const app = createSSRApp(App)
const router = createRouter('/ssr', true)
app.use(router)
// app.use(metaManager)
console.log('renderPage', 'push')
await router.push(url.substr(4))
await router.isReady()
console.log('renderPage', 'eady')
/* console.log(router)
const matchedComponents = router.getMatchedComponents()
// no matched routes, reject with 404
@@ -1,62 +1,8 @@
import {
createApp,
defineComponent,
reactive,
toRefs,
h,
watch
} from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { defaultConfig, createManager, useMeta, useMetainfo, resolveOption } from 'vue-meta'
// import About from './about.vue'
import { watch } from 'vue'
import { useMeta, useMetainfo } from 'vue-meta'
const metaUpdated = 'no'
const ChildComponent = defineComponent({
name: 'child-component',
props: {
page: String
},
template: `
<div>
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
</div>
`,
setup (props) {
const state = reactive({
date: null,
metaUpdated
})
const title = props.page[0].toUpperCase() + props.page.slice(1)
console.log('ChildComponent Setup')
useMeta({
charset: 'utf16',
title,
description: 'Description ' + props.page,
og: {
title: 'Og Title ' + props.page,
},
})
return toRefs(state)
}
})
function view (page) {
return {
name: `section-${page}`,
render () {
return h(ChildComponent, { page })
}
}
}
const App = {
export default {
setup () {
// console.log('App', getCurrentInstance())
const { meta } = useMeta({
base: { href: '/vue-router', target: '_blank' },
charset: 'utf8',
@@ -99,7 +45,7 @@ const App = {
// TODO { rawContent: 'window.b = "<br/>"; </script><script> alert(\'123321\');' },
{ src: 'body-script2.js', to: 'body' },
{ src: 'body-script3.js', to: '#put-it-here' }
],
]
/* esi: {
children: [
{
@@ -145,9 +91,11 @@ const App = {
const metadata = useMetainfo()
window.$metadata = metadata
if (!process.server) {
window.$metadata = metadata
}
watch(metadata, (newValue, oldValue) => {
watch(metadata, (newValue) => {
console.log('UPDATE', newValue)
})
@@ -216,41 +164,3 @@ const App = {
</div>
`
}
const decisionMaker5000000 = resolveOption((prevValue, context) => {
const { uid = 0 } = context.vm || {}
if (!prevValue || prevValue < uid) {
return uid
}
})
const metaManager = createManager({
...defaultConfig,
esi: {
group: true,
namespaced: true,
attributes: ['src', 'test', 'text']
}
}, decisionMaker5000000)
useMeta(
{
og: {
something: 'test',
},
},
metaManager
) /**/
const router = createRouter({
history: createWebHistory('/vue-router'),
routes: [
{ name: 'home', path: '/', component: view('home') },
{ name: 'about', path: '/about', component: view('about') }
]
})
const app = createApp(App)
app.use(router)
app.use(metaManager)
app.mount('#app')
+40
View File
@@ -0,0 +1,40 @@
import { defineComponent, reactive, toRefs } from 'vue'
import { useMeta } from 'vue-meta'
const metaUpdated = 'no' // TODO: afterNavigation hook?
export default defineComponent({
name: 'ChildComponent',
props: {
page: {
type: String,
required: true
}
},
setup (props) {
const state = reactive({
date: null,
metaUpdated
})
const title = props.page[0].toUpperCase() + props.page.slice(1)
console.log('ChildComponent Setup')
useMeta({
charset: 'utf16',
title,
description: 'Description ' + props.page,
og: {
title: 'Og Title ' + props.page
}
})
return toRefs(state)
},
template: `
<div>
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
</div>
`
})
-29
View File
@@ -1,29 +0,0 @@
<template>
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
</template>
<script>
/*
<head type="template">
<title v-if="title">{{ title }}</title>
<meta v-for="meta in metas" :name="meta.name" :content="meta.content" />
</head>
*/
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
export default {
props: {
page: String
},
setup(props) {
const metaUpdated = ref()
const route = useRoute()
onMounted(() => console.log(route))
return { metaUpdated, page: route.name }
}
}
</script>
+7
View File
@@ -0,0 +1,7 @@
import { createApp } from 'vue'
import { App, createRouter, metaManager } from './main'
const app = createApp(App)
app.use(createRouter('/vue-router'))
app.use(metaManager)
app.mount('#app')
+54
View File
@@ -0,0 +1,54 @@
import { h } from 'vue'
import { createRouter as createVueRouter, createMemoryHistory, createWebHistory } from 'vue-router'
import { createManager, defaultConfig, resolveOption, useMeta } from 'vue-meta'
import App from './App'
import ChildComponent from './Child'
function createView (page) {
return {
name: `section-${page}`,
render () {
return h(ChildComponent, { page })
}
}
}
const decisionMaker5000000 = resolveOption((prevValue, context) => {
const { uid = 0 } = context.vm || {}
if (!prevValue || prevValue < uid) {
return uid
}
})
const metaManager = createManager({
...defaultConfig,
esi: {
group: true,
namespaced: true,
attributes: ['src', 'test', 'text']
}
}, decisionMaker5000000)
useMeta(
{
og: {
something: 'test'
}
},
metaManager
) /**/
const createRouter = (base, isSSR) => createVueRouter({
history: isSSR ? createMemoryHistory(base) : createWebHistory(base),
routes: [
{ name: 'home', path: '/', component: createView('home') },
{ name: 'about', path: '/about', component: createView('about') }
]
})
export {
App,
metaManager,
createRouter,
createView
}
+1 -1
View File
@@ -49,7 +49,7 @@ export default new Vuex.Store({
publishedPosts (state) {
return state.posts.filter(post => post.published)
},
publishedPostsCount (state, getters) {
publishedPostsCount (_, getters) {
return getters.publishedPosts.length
}
},
+1 -1
View File
@@ -46,7 +46,7 @@ export default new Vuex.Store({
publishedPosts (state) {
return state.posts.filter(post => post.published)
},
publishedPostsCount (state, getters) {
publishedPostsCount (_, getters) {
return getters.publishedPosts.length
}
},
+14 -25
View File
@@ -7,7 +7,7 @@ import { VueLoaderPlugin } from 'vue-loader'
// const srcDir = path.join(__dirname, '..', 'src')
export default {
devtool: 'source-map',
devtool: 'inline-source-map',
mode: 'development',
entry: fs.readdirSync(__dirname)
.reduce((entries, dir) => {
@@ -16,11 +16,17 @@ export default {
if (dir === 'ssr') {
entries[dir] = path.join(fullDir, 'browser.js')
} else if (dir === 'vue-router') {
const entry = path.join(fullDir, 'app.js')
if (fs.statSync(fullDir).isDirectory() && fs.existsSync(entry)) {
entries[dir] = entry
const possibleEntries = ['browser', 'app']
for (const entryName of possibleEntries) {
const entry = path.join(fullDir, entryName + '.js')
if (fs.statSync(fullDir).isDirectory() && fs.existsSync(entry)) {
entries[dir] = entry
break
}
}
}
return entries
}, {}),
output: {
@@ -39,22 +45,7 @@ export default {
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: '3',
targets: { ie: 9, safari: '5.1' }
}]
]
}
}
},
{
resourceQuery: /blockType=head/,
loader: require.resolve('./meta-loader.js')
use: 'babel-loader'
},
{
test: /\.vue$/,
@@ -63,7 +54,7 @@ export default {
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
extensions: ['.tsx', 'd.ts', '.ts', '.js', '.vue'],
alias: {
// this isn't technically needed, since the default `vue` entry for bundlers
// is a simple `export * from '@vue/runtime-dom`. However having this
@@ -83,11 +74,9 @@ export default {
new VueLoaderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
__DEV__: process.env.NODE_ENV !== 'production'
}),
new webpack.DefinePlugin({
__DEV__: JSON.stringify(process.env.NODE_ENV !== 'production'),
__VUE_OPTIONS_API__: JSON.stringify(true),
__VUE_PROD_DEVTOOLS__: JSON.stringify(true),
__VUE_PROD_DEVTOOLS__: JSON.stringify(true)
})
],
devServer: {