2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-06-16 19:30:34 +03:00

feat: add poc vue-compiler

This commit is contained in:
pimlie
2020-04-05 10:28:12 +02:00
parent 3ecaf28e33
commit 6d25ff2f37
13 changed files with 296 additions and 88 deletions
+4 -4
View File
@@ -7,15 +7,15 @@
<body style="padding: 0 20px">
<h1>Vue Meta Examples</h1>
<ul>
<li><a href="basic">Basic</a></li>
<!-- 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="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">Usage with vuex</a></li>
<li><a href="vuex-async">Usage with vuex + async actions</a></li>
<li><a href="async-callback">Async Callback</a></li>
<li><a href="async-callback">Async Callback</a></li -->
</ul>
</body>
</html>
+75
View File
@@ -0,0 +1,75 @@
const {
baseParse,
transform,
generate,
processIf,
getBaseTransformPreset,
createObjectExpression,
createObjectProperty,
} = require('@vue/compiler-core')
const { parse } = require('@vue/compiler-dom')
function headTransform(node, context) {
console.log('NODE', node)
if (node.type === 1 /* NodeTypes.ELEMENT */) {
return () => {
if (!context.parent.codegenNode) {
context.parent.codegenNode = createObjectExpression([])
}
const options = context.parent.codegenNode
const option = createObjectProperty(
node.tag,
node.children.length === 1 ? node.children[0] : 'null'
)
//options.properties.push(option)
}
}
}
module.exports = function (source, map) {
// TODO: add options
const ast = parse(source)
//console.log('AST', ast)
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset({
prefixIdentifiers: true
})
transform(ast, {
prefixIdentifiers: true,
nodeTransforms: [
...nodeTransforms,
headTransform
],
directiveTransforms
})
const result = generate(ast, { mode: 'module' })
console.log(result.code)
this.callback(null, `
import { computed } from 'vue'
${result.code}
export default function (component) {
const setup = component.setup
component.setup = function (...args) {
console.log(component)
const __htmlMetaData = computed(() => {
})
return {
...setup.apply(this, args),
__htmlMetaData
}
}
}`, map)
/**/
}
+4
View File
@@ -0,0 +1,4 @@
export default {
}
+18 -17
View File
@@ -20,28 +20,29 @@
},
"homepage": "https://github.com/nuxt/vue-meta#readme",
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/node": "^7.6.1",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.6.0",
"babel-loader": "^8.0.6",
"@babel/core": "^7.9.0",
"@babel/node": "^7.8.7",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.9.0",
"@vue/compiler-sfc": "^3.0.0-alpha.10",
"@vue/server-renderer": "^3.0.0-alpha.10",
"babel-loader": "^8.1.0",
"babel-plugin-dynamic-import-node": "^2.3.0",
"consola": "^2.10.1",
"consola": "^2.11.3",
"core-js": "3",
"cross-env": "^5.2.1",
"cross-env": "^7.0.2",
"express": "^4.17.1",
"express-urlrewrite": "^1.2.0",
"fs-extra": "^8.1.0",
"fs-extra": "^9.0.0",
"lodash": "^4.17.15",
"vue": "^2.6.10",
"vue-loader": "^15.7.1",
"vue-meta": "^2.2.2",
"vue-router": "^3.1.3",
"vue-server-renderer": "^2.6.10",
"vue-template-compiler": "^2.6.10",
"vuex": "^3.1.1",
"webpack": "^4.39.3",
"webpack-dev-server": "^3.8.0",
"vue": "next",
"vue-loader": "next",
"vue-meta": "^2.3.3",
"vue-router": "next",
"vue-template-compiler": "^2.6.11",
"vuex": "^3.1.3",
"webpack": "^4.42.1",
"webpack-dev-server": "^3.10.3",
"webpackbar": "^4.0.0"
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ const app = express()
app.use(webpackDevMiddleware(webpack(WebpackConfig), {
publicPath: '/__build__/',
writeToDisk: false,
writeToDisk: true,
stats: {
colors: true,
chunks: false
+13 -11
View File
@@ -1,13 +1,13 @@
import Vue from 'vue'
import Router from 'vue-router'
import { createSSRApp } from 'vue'
import { createRouter, createMemoryHistory } from 'vue-router'
import VueMeta from '../../'
Vue.use(Router)
/*Vue.use(Router)
Vue.use(VueMeta, {
tagIDKeyName: 'hid'
})
})*/
export default function createApp () {
export default function createMyApp () {
const Home = {
template: `<div>
<router-link to="/about">About</router-link>
@@ -54,16 +54,15 @@ export default function createApp () {
}
}
const router = new Router({
mode: 'history',
base: '/ssr',
const router = createRouter({
history: createMemoryHistory('/ssr'),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
const app = new Vue({
const app = createSSRApp({
router,
metaInfo () {
return {
@@ -145,13 +144,16 @@ export default function createApp () {
<router-view />
</div>`
})
const { set } = app.$meta().addApp('custom')
app.use(router)
/*const { set } = app.$meta().addApp('custom')
set({
bodyAttrs: { class: 'custom-app' },
meta: [{ charset: 'utf-8' }]
})
})*/
return { app, router }
}
+1 -1
View File
@@ -3,4 +3,4 @@ import createApp from './App'
window.users = []
const { app } = createApp()
app.$mount('#app')
app.mount('#app')
+27 -19
View File
@@ -1,11 +1,9 @@
import path from 'path'
import fs from 'fs-extra'
import template from 'lodash/template'
import { createRenderer } from 'vue-server-renderer'
const { renderToString } = require('@vue/server-renderer')
import createApp from './App'
const renderer = createRenderer({ runInNewContext: false })
const templateFile = path.resolve(__dirname, 'app.template.html')
const templateContent = fs.readFileSync(templateFile, { encoding: 'utf8' })
@@ -17,24 +15,34 @@ process.server = true
export async function renderPage ({ url }) {
const { app, router } = await createApp()
router.push(url.substr(4))
await router.push(url.substr(4))
return new Promise((resolve, reject) => {
router.onReady(async () => {
const matchedComponents = router.getMatchedComponents()
// no matched routes, reject with 404
if (!matchedComponents.length) {
return reject({ code: 404 })
}
await router.isReady()
/*console.log(router)
const matchedComponents = router.getMatchedComponents()
// no matched routes, reject with 404
if (!matchedComponents.length) {
return reject({ code: 404 })
}*/
const appHtml = await renderer.renderToString(app)
const appHtml = await renderToString(app)
const pageHtml = compiled({
app: appHtml,
...app.$meta().inject()
})
resolve(pageHtml)
})
const pageHtml = compiled({
app: appHtml,
htmlAttrs: {
text: () => {}
},
headAttrs: {
text: () => {}
},
bodyAttrs: {
text: () => {}
},
head: () => {},
bodyPrepend: () => {},
bodyAppend: () => {}
//...app.$meta().inject()
})
return pageHtml
}
+30
View File
@@ -0,0 +1,30 @@
<template>
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
</template>
<head type="template">
<title v-if="title">{{ title }}</title>
<meta v-for="meta in metas" :name="meta.name" :content="meta.content" />
</head>
<script>
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.value.name }
}
}
</script>
useMeta()
+29 -25
View File
@@ -1,16 +1,18 @@
import Vue from 'vue'
import { createApp, defineComponent, reactive, toRefs, h } from 'vue'
import VueMeta from 'vue-meta'
import Router from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import About from './about.vue'
Vue.use(Router)
Vue.use(VueMeta, {
/*Vue.use(VueMeta, {
refreshOnceOnNavigation: true
})
})*/
let metaUpdated = 'no'
const ChildComponent = {
const ChildComponent = defineComponent({
name: 'child-component',
props: ['page'],
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>
@@ -26,21 +28,25 @@ const ChildComponent = {
}
}
},
data () {
return {
setup () {
const state = reactive({
date: null,
metaUpdated
})
return {
...toRefs(state)
}
},
mounted () {
/*mounted () {
this.interval = setInterval(() => {
this.date = new Date()
}, 1000)
},
destroyed () {
clearInterval(this.interval)
}
}
}*/
})
// this wrapper function is not a requirement for vue-router,
// just a demonstration that render-function style components also work.
@@ -48,25 +54,21 @@ const ChildComponent = {
function view (page) {
return {
name: `section-${page}`,
render (h) {
return h(ChildComponent, {
props: { page }
})
render () {
return h(ChildComponent, { page })
}
}
}
const router = new Router({
mode: 'history',
base: '/vue-router',
const router = createRouter({
history: createWebHistory('/vue-router'),
routes: [
{ path: '/', component: view('home') },
{ path: '/about', component: view('about') }
{ name: 'home', path: '/', component: view('home') },
{ name: 'about', path: '/about', component: About }
]
})
const App = {
router,
template: `
<div id="app">
<h1>vue-router</h1>
@@ -80,8 +82,10 @@ const App = {
`
}
const app = new Vue(App)
const app = createApp(App)
app.use(router)
/*
const { set, remove } = app.$meta().addApp('custom')
set({
@@ -93,8 +97,8 @@ set({
]
})
setTimeout(() => remove(), 3000)
app.$mount('#app')
*/
app.mount('#app')
/*
const waitFor = time => new Promise(r => setTimeout(r, time || 1000))
+24 -6
View File
@@ -2,7 +2,7 @@ import fs from 'fs'
import path from 'path'
import webpack from 'webpack'
import WebpackBar from 'webpackbar'
import VueLoaderPlugin from 'vue-loader/lib/plugin'
import { VueLoaderPlugin } from 'vue-loader'
const srcDir = path.join(__dirname, '..', 'src')
@@ -15,7 +15,7 @@ export default {
if (dir === 'ssr') {
entries[dir] = path.join(fullDir, 'browser.js')
} else {
} else if (dir === 'vue-router') {
const entry = path.join(fullDir, 'app.js')
if (fs.statSync(fullDir).isDirectory() && fs.existsSync(entry)) {
entries[dir] = entry
@@ -47,13 +47,24 @@ export default {
}
}
},
{ test: /\.vue$/, use: 'vue-loader' }
{
resourceQuery: /blockType=head/,
loader: require.resolve('./meta-loader.js')
},
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
resolve: {
alias: {
'vue': 'vue/dist/vue.js',
'vue-meta': process.env.NODE_ENV === 'development' ? srcDir : 'vue-meta'
// this isn't technically needed, since the default `vue` entry for bundlers
// is a simple `export * from '@vue/runtime-dom`. However having this
// extra re-export somehow causes webpack to always invalidate the module
// on the first HMR update and causes the page to reload.
'vue': 'vue/dist/vue.esm.js',
'vue-meta': path.resolve(__dirname, './next/')
}
},
// Expose __dirname to allow automatically setting basename.
@@ -67,5 +78,12 @@ export default {
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
})
]
],
devServer: {
inline: true,
hot: true,
stats: 'minimal',
contentBase: __dirname,
overlay: true
}
}