vikejs / vike-vue Goto Github PK
View Code? Open in Web Editor NEWπ¨ Vue integration for Vike
Home Page: https://vike.dev/vike-vue
License: MIT License
π¨ Vue integration for Vike
Home Page: https://vike.dev/vike-vue
License: MIT License
_headAlreadySet
has the same problem as _configFromHook
.
I made a simple repro for the problem in #179
useConfig
(in useConfig-client) the check is against _headAlreadySet
from reactive pageContext_headAlreadySet
(in onRenderClient) pageContext is not created reactive with a _headAlreadySet
keyWhat I can see is:
Rest of comments are here: #178 (comment)
Since vike-react
now has a <ClientOnly>
component, it would be great to align vike-vue
to also have such component.
It'd be nice if we could have proper completion when using ClientOnly
.
E.g.
// Component.vue
<template>
<p>{{ msg }}</p>
</template>
<script lang="ts" setup>
defineProps<{ msg: string }>()
</script>
// App.vue
<template>
<ClientOnly
:load="() => import('./Component.vue')"
msg="Hello World"
/>
</template>
Here we don't get a hint for msg
even though it's passed to Component.vue
.
I just read the doc and code that found there is no way to install and use the vue plugin with this adapter. Could you please tell me how to do or add a way to do that?
I have a catch all route which works fine from SSR but when we navigate from one page to another on the client side, the navigation doesn't happen.
Repo to reproduce: https://github.com/mohammadsiddiqui/h3-vike
Steps to reproduce:
Catch all on client seems to be working for the first route occurrence but second time it fails.
This is the error i am getting
chunk-CRYGExF-.js:13 Error: You stumbled upon a vike-vue bug. Go to https://github.com/vikejs/vike-vue/issues/new and copy-paste this error. A maintainer will fix the bug (usually under 24 hours). at _l (chunk-CRYGExF-.js:17:5413) at ml (chunk-CRYGExF-.js:17:5691) at chunk-h72aJ6Vq.js:1:74 at Dn.fn (chunk-CRYGExF-.js:9:8919) at Dn.run (chunk-CRYGExF-.js:9:1446) at get value (chunk-CRYGExF-.js:9:9163) at li (chunk-CRYGExF-.js:9:1618) at get dirty (chunk-CRYGExF-.js:9:1165) at I.l.update (chunk-CRYGExF-.js:13:27958) at Ue (chunk-CRYGExF-.js:13:46)
chunk-B8FgST7x.js:2 Error: [vike][Wrong Usage] Can't access pageContext.pinia on the client side. Because it can't be serialized, see server logs.
at w (chunk-DIG79TLW.js:1:1502)
at ae (chunk-DIG79TLW.js:2:954)
at Object.get (chunk-B8FgST7x.js:1:16082)
at op (chunk-BxOFPIm6.js:2:103)
at chunk-BxOFPIm6.js:18:13078
at Array.map ()
at An (chunk-BxOFPIm6.js:18:13043)
at xp (chunk-BxOFPIm6.js:18:14464)
at chunk-B8FgST7x.js:2:9396
at chunk-DIG79TLW.js:2:2638
**"vike": "^0.4.193",
"vike-vue": "^0.8.3",
"vike-vue-pinia": "^0.1.1"**
This is a mini repo
https://stackblitz.com/edit/vitejs-vite-sysrfj?file=package.json
In addition to the title, favicon, and lang, I would find it handy to be able to specify a canonical URL in the page config.
This could be beneficial for other SSG sites optimized for search engines (see How to specify a canonical with rel="canonical" and other methods.
I currently implement this in my HeadDefault.vue
as below, but it seems to closely match the pattern in the latest onRender{Client|Html} code, and may have broader appeal beyond my specific use case, so if you think it would be beneficial, please let me know and I'll submit a PR. Curious also why it appears that description was removed in the latest code, as I also configure description on page-by-page basis.
e.g.
const canonical = getHeadSetting('canonical', pageContext)
const canonicalTag = !canonical ? '' : escapeInject`<link rel="canonical" href="${canonical}" />`
Replaces my specific implementation:
<template class="h-100">
<meta charset="UTF-8" />
<link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
<link v-if="canonical" rel="canonical" :href="canonical">
<link rel="manifest" href="/favicons/site.webmanifest">
<link rel="shortcut icon" type="image/x-icon" href="/favicons/favicon.ico">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="msapplication-config" content="/favicons/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</template>
<script lang="ts" setup>
import { usePageContext } from 'vike-vue/usePageContext'
import { PageContext } from 'vike/types';
const pageContext = usePageContext();
function getCanonical(pageContext: PageContext): null | string {
const canonicalConfig = pageContext.configEntries.canonical?.[0]
if (!canonicalConfig) {
return null
}
const canonical = canonicalConfig.configValue
if (typeof canonical === 'string') {
return canonical
}
const { configDefinedAt } = canonicalConfig;
if (canonical instanceof Function || typeof canonical === 'function') {
const val = canonical(pageContext)
if (typeof val !== 'string') {
throw new Error(configDefinedAt + ' should return a string')
}
return val
}
throw new Error(configDefinedAt + ' should be a string or a function returning a string')
}
const canonical = getCanonical(pageContext);
</script>
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Location: .github/renovate.json5
Error type: Invalid JSON5 (parsing failed)
Message: JSON5.parse error: JSON5: invalid character '\"' at 21:7
The user may change the lang
setting per-page based on i18n. On client-side navigation, onRenderClient should adapt lang
in the existing DOM.
Same as vikejs/vike-react#59
How to add some className to body?
For example I want initially to have dark
class for tailwind dark theme by default for all my pages.
Comparison with vike-react
:
vike-react
: Call updateDocument()
first, followed by the useConfig()
hook during page navigation.vike-vue
: Call the useConfig()
hook first, followed by updateDocument()
(renamed applyHeadSettings()
) during page navigation.Since pageContext.isHydration
is false
during page navigation (after the first render), then this :
will return pageContext._headAlreadySetWrapper = { val: false }
Consequently, useConfig()
hook will get pageContext._headAlreadySetWrapper = { val: false }
and never call apply()
function.
One solution I can tell is to place applyHeadSettings()
twice, after app.mount()
and before await changePage(pageContext)
.
Edit: A better solution I've tried is to place applyHeadSettings()
twice :
1. After app.mount()
, and
We only need to call applyHeadSettings()
after onChangePage?.(pageContext)
With the above solution, we donβt need the workaround involving _headAlreadySetWrapper?: { val: boolean }
. We can use the previous method with _headAlreadySet?: true
instead.
import type { Config } from 'vike/types'
import vikeVue from 'vike-vue/config'
- import vikePinia from 'vike-pinia'
+ import vikePinia from 'vike-pinia/config'
export default {
extends: [vikeVue, vikePinia],
} satisfies Config
Same for vike-vue-query
.
How about we advertise using Vue with JSX? Projects like Vuetify are written in TSX and Vue plans to support vapor for JSX.
We could write blog posts, documentation, go to conferences etc. to advertise the vike-vue + JSX combo.
@pdanpdan @4350pChris WDYT?
See also:
I haven't check in other places, on my mobile today.
Unable to extract CSS and put it into tag. For example:
import { createSSRApp } from 'vue'
import { renderToString } from '@vue/server-renderer'
import { setup } = from '@css-render/vue3-ssr'
// For each request, you need to create a new app
const ssrApp = createSSRApp(App)
const { collect } = setup(ssrApp)
renderToString(ssrApp).then(appHtml => {
const css = collect()
const page = `<!DOCTYPE html>
<html>
<head>${css}</head>
<body><div id="app">${appHtml}</div></body>
</html>`
})
as you see here we can extract CSS and render as part of HTML template.
I didn't found a way how to do it properly. Probably a new functionality should be added
A comparison of features could be neat.
To give confidence to users that Vike Vue supports Nuxt features.
Also for us, so what we know where Vike Vue is lacking compared to Nuxt.
Hey, I'm in the process of converting a project I'm working on to use this integration and replace my custom one.
However, one thing I don't know how to solve right now is registering client-side plugins that don't use app.use
- specifically, the Sentry plugin.
Here's the code I'm currently using in my +onRenderClient.ts
file (truncated):
import { init as sentryInit, BrowserTracing } from "@sentry/vue";
// ...
export async function onRenderClient(pageContext: PageContextClient) {
if (!app) {
// ...
const { sentryRelease, sentryDsn } = pageContext;
sentryInit({
app,
dsn: sentryDsn,
integrations: (defaults) =>
defaults.concat(
new BrowserTracing({
tracingOrigins: [/.*.example.com/, /^\//],
})
),
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 0.2,
logErrors: !import.meta.env.PROD,
environment,
release: sentryRelease,
});
// ...
}
// ...
}
Now, I could move this to the client init code or do it in my root component using import.meta.env.SSR
- however, that would delay the plugin's registration and I'm worried some errors might not be propagated to Sentry in that case, which is why this is one of the first things I'm doing right now in the aforementioned file.
Any suggestions how I could leverage what's available right now to do this properly?
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
.github/workflows/ci.yml
actions/checkout v4
pnpm/action-setup v4
actions/setup-node v4
.github/workflows/discord.yml
.github/workflows/formatting.yml
actions/checkout v4
pnpm/action-setup v4
package.json
@biomejs/biome ^1.7.0
@brillout/test-e2e ^0.5.34
@brillout/test-types ^0.1.14
playwright ^1.44.1
prettier ^3.2.5
pnpm 9.6.0
packages/vike-vue-pinia/package.json
@brillout/release-me ^0.3.8
@types/node ^22.1.0
pinia ^2.1.7
typescript ^5.4.5
vike ^0.4.183
vue ^3.4.36
vue-tsc ^2.0.13
pinia >=2.0.0
vike-vue >=0.7.0
vue >=3.0.0
packages/vike-vue-query/package.json
@brillout/release-me ^0.3.8
@tanstack/vue-query ^5.29.0
@types/node ^22.1.0
typescript ^5.4.5
vike ^0.4.183
vue ^3.4.36
vue-tsc ^2.0.13
@tanstack/vue-query >=5.0.0
vike-vue >=0.7.0
vue >=3.0.0
packages/vike-vue/package.json
@brillout/release-me ^0.3.8
@types/node ^22.1.0
@vitejs/plugin-vue ^5.0.4
typescript ^5.5.4
vike ^0.4.183
vite ^5.4.0
vite-plugin-dts ^3.8.3
vue ^3.4.36
vue-tsc ^2.0.13
vike >=0.4.183
vue >=3.0.0
See reprod #186:
The issue here is that the setup script of hello/+Page.vue
isn't called upon same-page navigation.
@phonzammi @pdanpdan Ideas for how to fix this?
Is something missing for a non-experimental release? Do we foresee any feature the user will eventually want? π
In createVueApp
in changePage
the content of pageContext
is placed in pageContextReactive
using Object.assign
.
That might lead to leftover properties from previous pageContext
if the new one is missing those properties.
The shape changing problem from dataReactive
should not creep here as pageContext
is always object.
I tested master
and v0.5.3
tagged commit too. Same error:
$ cd examples/basic/
$ pnpm install
Scope: all 6 workspace projects
../.. | +218 ++++++++++++++++++++++
../.. | Progress: resolved 218, reused 201, downloaded 17, added 218, done
dependencies:
+ @types/node 20.10.5
+ @types/node-fetch 2.6.9
+ @vitejs/plugin-vue 4.6.0
+ cross-fetch 4.0.0
+ node-fetch 3.3.2
+ typescript 5.3.3
+ unplugin-vue-markdown 0.25.2
+ vike 0.4.152
+ vike-vue 0.5.3 <- ../../vike-vue
+ vite 5.0.10
+ vue 3.3.13
Done in 2.8s
$ pnpm run dev
> @ dev /MY_DIRS_HERE/vike-vue/examples/basic
> vite dev
19:28:05 [vike][config][Wrong Usage] The import path 'vike-vue' in /pages/+config.h.ts couldn't be resolved: does 'vike-vue' exist?
VITE v5.0.10 ready in 576 ms
β Local: http://localhost:3000/
β Network: use --host to expose
β press h + enter to show help
19:28:09 [vike][request(1)] HTTP request: /
19:28:09 [vike][request(1)] Couldn't load configuration: see error above.
19:28:11 [vike][request(2)] HTTP request: /sw.js
19:28:11 [vike][request(2)] Couldn't load configuration: see error above.
And in browser I see blank page with one line: Cannot GET /
I have:
$ node --version
v18.17.1
$ pnpm --version
8.11.0
onBeforeMount()
in favor of onCreateApp()
? AFAICT the onBeforeMount()
hooks of vike-{pinia,vue-query}
can be merged into onCreateApp()
.onAfterRenderSSRApp()
in favor of a new hook onAfterRenderHtml()
that is called right before escapeInject
? Users could use !!pageContext.Page
to check whether the app is SSR'ing. Also, a neat thing here is that the new name would then align with vike-react
's hooks.See:
I think we can & should also deprecate the <ClientOnly>
wrapper component in favor of a clientOnly()
function. It's a much nicer DX.
hi,
i realise when using js cookie, it does reflect on browser side calling to server as i can see the headers is set.
but it does not seems to show on server side when rendering.
cookie storage:
https://github.com/u007/vike-admin/blob/main/store/storage.cookie.ts
the pinia using it:
https://github.com/u007/vike-admin/blob/main/store/alert.ts
New docs for vike-vue
live at vike.dev
, for example:
But for vike-vue-pinia
and vike-vue-query
I think it's better we write the docs in the README.md
file.
So far vike-vue-pinia
and vike-vue-query
don't have any documentation, contribution welcome to create some.
Thank you for making such awesome middleware. It is working well on my local setup, but I need some assistance with deploying it on an IIS server.
Could you please guide me on how to deploy this in an IIS server? Specifically, is there a way to run the ssr.js file in IIS?
Using examples/full
:
An error will occur.
useData
will return the original object from http://localhost:3000/star-wars/1 combined with the array from http://localhost:3000/star-wars (because the base structure is an object the array content is converted to objects keys also)
I think the data should always be re-created
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#charset
It should be rendered in the first 1024 bytes of HTML, but placing stylesheets before cannot guarantee this.
And if it's not the stylesheets might load as another charset (if the server does not send the right content-type).
What is rendered by examples/full
:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="/components/Link.vue?vue&type=style&index=0&scoped=409c8661&lang.css?direct">
<link rel="stylesheet" type="text/css" href="/pages/global.css?direct">
<link rel="stylesheet" type="text/css" href="/pages/+Layout.vue?vue&type=style&index=0&lang.css?direct">
<link rel="stylesheet" type="text/css" href="/pages/+Layout.vue?vue&type=style&index=1&scoped=c1413baa&lang.css?direct">
<link rel="stylesheet" type="text/css" href="/pages/images/Image.vue?vue&type=style&index=0&scoped=c8a68a87&lang.css?direct">
<meta charset="UTF-8" />
<title>My Vike + Vue App</title>
<meta property="og:title" content="My Vike + Vue App">
import vikeVue from "vike-vue/config";
import type { Config } from "vike/types";
import Head from "../layouts/HeadDefault.vue";
import Layout from "../layouts/LayoutDefault.vue";
import vikeVuePinia from 'vike-vue-pinia/config'
// Default config (can be overridden by pages)
export default {
Layout,
Head,
// <title>
title: "BackOffice",
extends: [vikeVue, vikeVuePinia],
} satisfies Config;
error:
4:45:05 PM [vike][request(1)] Following error was thrown by the onRenderHtml() hook defined at vike-vue/renderer/onRenderHtml
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property '_context' -> object with constructor 'Object'
--- property 'app' closes the circle
at JSON.stringify (<anonymous>)
at Object.toDisplayString (/Users/james/www/admin/node_modules/.pnpm/@[email protected]/node_modules/@vue/shared/dist/shared.cjs.js:465:154)
at Module.ssrInterpolate (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:180:35)
at _sfc_ssrRender (/Users/james/www/admin/pages/index/+Page.vue:1:1)
at renderComponentSubTree (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:693:9)
at renderComponentVNode (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:637:12)
at renderVNode (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:753:14)
at renderVNodeChildren (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:769:5)
at ssrRenderSlotInner (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:118:7)
at Module.ssrRenderSlot (/Users/james/www/admin/node_modules/.pnpm/@[email protected][email protected]/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:93:3)
4:45:05 PM [vike][request(1)] HTTP response / 500
4:45:05 PM [[email protected]][Bug] You stumbled upon a Vike bug. Go to https://github.com/vikejs/vike/issues/new and copy-paste this error. A maintainer will fix the bug (usually under 24 hours).
import vikeVue from "vike-vue/config";
import type { Config } from "vike/types";
import Head from "../layouts/HeadDefault.vue";
import Layout from "../layouts/LayoutDefault.vue";
// Default config (can be overridden by pages)
export default {
Layout,
Head,
// <title>
//# BATI.has("auth0") || BATI.has("firebase-auth") || BATI.has("authjs")
passToClient: ["user"],
title: "My Vike App",
extends: vikeVue,
stream: "web",
bodyHtmlEnd: '
After switching pages, all clicking and other functions became invalid
my-app.zip
React 18 introduced Progressive Rendering.
Does Vue support this? If not, it could be nice to find/create/follow a Vue GitHub issue about this.
For example examples/vue-query/
: when replacing import.meta.env.SSR ? 0 : 3000
with 3000
then the whole rendering of the page is blocked. There doesn't seem to be any progressive rendering going on, but maybe the trick is to add a <Suspense>
boundary?
I'm not sure if this should be solved in vike
or in devtools-next
(https://github.com/vuejs/devtools-next) or in both.
When inspecting components that use usePageContext
in script setup
devtools will try to check some marker/well-known keys for internal purposes in prepare.js
.
let n = G(()=>St(t.setupState[o])), r = e[o], s, a = typeof n == "function" || typeof (n == null ? void 0 : n.render) == "function" || typeof (n == null ? void 0 : n.__asyncLoader) == "function" || typeof n == "object" && n && ("setup"in n || "props"in n) || /^v[A-Z]/.test(o);
This will produce calls to getPageContextProxyForUser
for key render
at least, and that will produce an [vike][Wrong Usage] pageContext.render isn't defined on the client-side
error.
It looks like normal (non-next) vue devtools works.
@brillout Maybe this should be forwarded to the vue devtools team, but I think you can decide better.
The PR #170 introduced the useConfig()
component hook to vike-vue
, see this usage example.
The only thing missing to align with vike-react
is to implement the <Config>
and <Head>
components.
My failed attempt to implement it: #174.
I wonder: does Nuxt have something like Next.js's <Head>
component?
Contribution welcome.
After updating a number of package dependencies this morning, I started getting the following:
src/pages/+config.ts:2:8 - error TS1192: Module '"/Users/tjohns/Src/epic-roadtrip-planner-webapp/node_modules/vike-vue/dist/+config"' has no default export.
2 import vikeVue from 'vike-vue/config'
~~~~~~~
Found 1 error in src/pages/+config.ts:2
I conjecture this is probably due to whatever TypeScript or ESLint change also resulted in vikejs/vike#1838
I'm not a modules expert, so not sure of side effects, but I suspect changing export { config }
to export { config as default}
may resolve the specific issue, and indeed changing it by hand in node_modules as a quick check did allow the build to succeed without error.
I have meetings all day, but if I get free I'll try for an actual fix/workaround and if it's good, will submit a PR, but I'm hoping someone beats me to it.
useConfig
may set _configFromHook
from components_configFromHook
is cleared_configFromHook
should be used to fill attributesSlightly but negligible DX regression, but very well worth it as it's much cleaner (much less potential for bugs) and probably a lot more performant. It will also enable Vike to remove this ugly workaround.
Hello.
When using vike-vue
the general structure of HTML is fixed in onRenderHml
and in order to add support for teleport in SSR (https://vuejs.org/guide/scaling-up/ssr.html#teleports) one needs to:
render...
functionsctx.teleports
in various places in HTMLIs there a way to do this while still using vike-vue
or a full custom implementation is required?
Now if we defined bodyAttributes: { class: 'dark' }
in +config
and defined bodyAttributer: { 'data-test': 'test' }
using useConfig
only the value from _configFromHook
will be used.
Is this what is expected?
And if they are cumulative maybe content merge should be implemented at least for class
.
There is already an example of using Vike with vue-unhead
here.
It'd be nice to have an extension that automatically integrates vue-unhead
.
Curious: with the latest improvements to head management, is there a rationale for using vue-unhead
?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.