2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-05-26 18:44:05 +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
+16 -3
View File
@@ -1,15 +1,28 @@
const path = require('path')
module.exports = {
presets: [
["@babel/preset-env", {
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3,
targets: {
ie: 9
}
}]
}],
'@babel/preset-typescript',
],
plugins: [
"dynamic-import-node"
'dynamic-import-node',
['global-define', {
'__DEV__': 'true'
}],
['module-resolver', {
root: '.',
extensions: ['.ts'],
alias: {
'vue-meta': path.resolve('./src/')
}
}],
],
env: {
test: {
+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: {
+4 -1
View File
@@ -35,7 +35,8 @@
"dev": "babel-node examples/server.js",
"docs": "vuepress dev --host 0.0.0.0 --port 3000 docs",
"docs:build": "vuepress build docs",
"lint": "eslint --ext .js,.ts src test",
"examples": "babel-node --extensions '.ts,.js' examples/server.js",
"lint": "eslint --ext .js,.ts src test examples",
"prerelease": "git checkout master && git pull -r",
"release": "yarn lint && yarn test && standard-version",
"test": "yarn test:unit && yarn test:e2e-ssr && yarn test:e2e-browser",
@@ -65,6 +66,8 @@
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-global-define": "^1.0.3",
"babel-plugin-module-resolver": "^4.1.0",
"browserstack-local": "^1.4.8",
"chromedriver": "^87.0.5",
"codecov": "^3.8.1",
+29 -1
View File
@@ -2162,6 +2162,11 @@ babel-plugin-dynamic-import-node@^2.3.3:
dependencies:
object.assign "^4.1.0"
babel-plugin-global-define@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/babel-plugin-global-define/-/babel-plugin-global-define-1.0.3.tgz#262c528f0c26bf318f4ccc77cf21df43a0fa6308"
integrity sha512-M8Sby4wRLuLr+9UB8V31knVRf/rl0xkk51A7um6hUCvVPyOvLtI0u0k1OPiMgE2d7CwmeSa33NzGpaALHPQCPg==
babel-plugin-istanbul@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765"
@@ -2183,6 +2188,17 @@ babel-plugin-jest-hoist@^26.6.2:
"@types/babel__core" "^7.0.0"
"@types/babel__traverse" "^7.0.6"
babel-plugin-module-resolver@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2"
integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==
dependencies:
find-babel-config "^1.2.0"
glob "^7.1.6"
pkg-up "^3.1.0"
reselect "^4.0.0"
resolve "^1.13.1"
babel-plugin-transform-es2015-modules-commonjs@^6.26.0:
version "6.26.2"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
@@ -4403,7 +4419,7 @@ finalhandler@~1.1.2:
statuses "~1.5.0"
unpipe "~1.0.0"
find-babel-config@^1.1.0:
find-babel-config@^1.1.0, find-babel-config@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2"
integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==
@@ -7567,6 +7583,13 @@ pkg-dir@^5.0.0:
dependencies:
find-up "^5.0.0"
pkg-up@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
dependencies:
find-up "^3.0.0"
pluralize@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
@@ -8187,6 +8210,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
reselect@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
reserved-words@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1"