2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-06-07 16:02:26 +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
}
}
+1 -2
View File
@@ -114,11 +114,10 @@
"standard-version": "^7.1.0",
"tib": "^0.7.4",
"typescript": "^3.8.3",
"vue": "^2.6.11",
"vue": "^3.0.0-alpha.10",
"vue-jest": "^3.0.5",
"vue-loader": "^15.9.1",
"vue-router": "^3.1.6",
"vue-server-renderer": "^2.6.11",
"vue-template-compiler": "^2.6.11",
"vuepress": "^1.4.0",
"vuepress-theme-vue": "^1.1.0",
+69 -2
View File
@@ -1855,6 +1855,25 @@
"@vue/babel-plugin-transform-vue-jsx" "^1.1.2"
camelcase "^5.0.0"
"@vue/compiler-core@3.0.0-alpha.10":
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.0-alpha.10.tgz#39e8de2d7fe8a932cd08958200f37086a9d6841a"
integrity sha512-YXJJyFfkgmX3Rnf+sEcL8RR9a9UiHqB6ng1pzN1Dy8STASqUBdwinvi/xBuuCS7mDls12xn562y5CEATAwZs/Q==
dependencies:
"@babel/parser" "^7.8.6"
"@babel/types" "^7.8.6"
"@vue/shared" "3.0.0-alpha.10"
estree-walker "^0.8.1"
source-map "^0.6.1"
"@vue/compiler-dom@3.0.0-alpha.10":
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.0-alpha.10.tgz#be9ec1d24d0c4d96d164f8e00a479bd88a45e55d"
integrity sha512-hOasMBUsmqccY9Qyytqmrup4AnxQ6zBHT8tC9QpfdtygvxrFK2uNvNZlPoZay2hB13fJjZgRdCyxELM0zB4Hww==
dependencies:
"@vue/compiler-core" "3.0.0-alpha.10"
"@vue/shared" "3.0.0-alpha.10"
"@vue/component-compiler-utils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.1.0.tgz#64cd394925f5af1f9c3228c66e954536f5311857"
@@ -1870,6 +1889,30 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
"@vue/reactivity@3.0.0-alpha.10":
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.0-alpha.10.tgz#d859acd384e42d42086cfefbefe478825aaa9b82"
integrity sha512-H4E0kbQQuc9W0eVKkPLK5g1CwUQkMh4pUWEE/Gl2pZsnDVNJlvbZIMwKu6P5cjd30Nnbv2sG3+wcUGS4TplDuA==
dependencies:
"@vue/shared" "3.0.0-alpha.10"
"@vue/runtime-core@3.0.0-alpha.10":
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.0-alpha.10.tgz#abba11b4c8ed4933632050c0319f63fffe66bb86"
integrity sha512-b4YPU+DnowcthtcZSPgAxEExAq/dz31aQasiY1lvSB54y4T2QNYOydVYnZsFUMOFhN0Fh3+k5s1dTolorem1cw==
dependencies:
"@vue/reactivity" "3.0.0-alpha.10"
"@vue/shared" "3.0.0-alpha.10"
"@vue/runtime-dom@3.0.0-alpha.10":
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.0-alpha.10.tgz#005880179a52001b4e4e76c816555cc0ce5d16a9"
integrity sha512-X0UcZlXBwZ0OW4yw3hA+8uE2CArPDf2LKk9aTIi3xrCeluQmJSEUsgDNxHBqvmNhVGqdi0kPB09NrOxfEtyPhw==
dependencies:
"@vue/runtime-core" "3.0.0-alpha.10"
"@vue/shared" "3.0.0-alpha.10"
csstype "^2.6.8"
"@vue/server-test-utils@^1.0.0-beta.30":
version "1.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@vue/server-test-utils/-/server-test-utils-1.0.0-beta.30.tgz#960a6383de81ba5ff763bdd6e961b9443e98fa82"
@@ -1878,6 +1921,11 @@
"@types/cheerio" "^0.22.10"
cheerio "^1.0.0-rc.2"
"@vue/shared@3.0.0-alpha.10":
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.0-alpha.10.tgz#7026d9a81fa5f03ea03e9434be6286ed167684b8"
integrity sha512-b6VYQrhsp/N0QpuXdxs1xIDrBiqVzFNyAvyQgPk2ssQgWD6H2StoySDj99DWrum2+pJUDO2/2dLfGH8l180R6g==
"@vue/test-utils@^1.0.0-beta.30":
version "1.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.30.tgz#d5f26d1e2411fdb7fa7fdedb61b4b4ea4194c49d"
@@ -4469,6 +4517,11 @@ cssstyle@^2.2.0:
dependencies:
cssom "~0.3.6"
csstype@^2.6.8:
version "2.6.9"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098"
integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
@@ -5460,6 +5513,11 @@ estree-walker@^0.6.1:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
estree-walker@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.8.1.tgz#6230ce2ec9a5cb03888afcaf295f97d90aa52b79"
integrity sha512-H6cJORkqvrNziu0KX2hqOMAlA2CiuAxHeGJXSIoKA/KLv229Dw806J3II6mKTm5xiDX1At1EXCfsOQPB+tMB+g==
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -12674,7 +12732,7 @@ vue-router@^3.1.6:
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.6.tgz#45f5a3a3843e31702c061dd829393554e4328f89"
integrity sha512-GYhn2ynaZlysZMkFE5oCHRUTqE8BWs/a9YbKpNLi0i7xD6KG1EzDqpHQmv1F5gXjr8kL5iIVS8EOtRaVUEXTqA==
vue-server-renderer@^2.6.10, vue-server-renderer@^2.6.11:
vue-server-renderer@^2.6.10:
version "2.6.11"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.11.tgz#be8c9abc6aacc309828a755c021a05fc474b4bc3"
integrity sha512-V3faFJHr2KYfdSIalL+JjinZSHYUhlrvJ9pzCIjjwSh77+pkrsXpK4PucdPcng57+N77pd1LrKqwbqjQdktU1A==
@@ -12709,11 +12767,20 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue@^2.6.10, vue@^2.6.11:
vue@^2.6.10:
version "2.6.11"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==
vue@^3.0.0-alpha.10:
version "3.0.0-alpha.10"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-alpha.10.tgz#0f1cb5471edc41e0b0153ff07f462e376e03b0ae"
integrity sha512-USdgVs1bQfuiM5ivt2S2XGKOmDC+gKhhc3RNKjASUnh9kWv/vhNJlQiqIaUFiPN9SE9833fWy3PKOJFj9yZjPQ==
dependencies:
"@vue/compiler-dom" "3.0.0-alpha.10"
"@vue/runtime-dom" "3.0.0-alpha.10"
"@vue/shared" "3.0.0-alpha.10"
vuepress-html-webpack-plugin@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz#219be272ad510faa8750d2d4e70fd028bfd1c16e"