Coder Social home page Coder Social logo

vikejs / vike-react Goto Github PK

View Code? Open in Web Editor NEW
73.0 3.0 11.0 625 KB

๐Ÿ”จ React integration for Vike

Home Page: https://vike.dev

License: MIT License

TypeScript 100.00%
full-stack node react react-ssr server-rendering ssr static-site-generator vite vite-plugin vite-ssr

vike-react's People

Contributors

brillout avatar ivangreene avatar lourot avatar nitedani avatar phonzammi avatar renovate[bot] avatar usk94 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

vike-react's Issues

Need a way to add html attributes to the root `<html>` element

First of all, thank you for this great library!

I'm creating this issue to share a hiccup I ran into. I'm using the Mantine-UI library and for the dark mode / light mode to work properly, you need a way to add a data-mantine-color-scheme html attribute to the root HTML element.

Currently, there is no way to manage this with the Head component to modify the html element.

Maybe a solution could look like this:

const Head: React.FC = () => {
  return (
    <>
      <html my-custom-attribute="foo" />
    </>
  )
}

Thank you!

vike-react-query questions

  1. Is there any recommended approach for setting the page title dynamically when using vike-react-query? I am using useSuspenseQuery with telefunc, and want to avoid fetching the same data twice, one time just for setting the page title

  2. Is there a way to prevent a useSuspenseQuery from refetching (on the server) when the client already has the data for the specific cache key from another page?

Add hook for obtaining page and root

I'm working on using safetest in my Vike app, and it requires calling a bootstrap function with the root component. This requires access to the main page JSX.Element, and the React root. I have accomplished this by putting my own +onRenderClient.tsx in my project, but it would be nice if there was some kind of configurable hook so I didn't have to copy onRenderClient from vike-react

For reference, here is the diff from the vike-react onRenderClient:

diff --git a/frontend/renderer/+onRenderClient.tsx b/frontend/renderer/+onRenderClient.tsx
index bb5a374..c0c47c8 100644
--- a/frontend/renderer/+onRenderClient.tsx
+++ b/frontend/renderer/+onRenderClient.tsx
@@ -2,6 +2,7 @@ import ReactDOM from 'react-dom/client'
 import { getHeadSetting } from '../node_modules/vike-react/dist/renderer/getHeadSetting'
 import type { OnRenderClientSync } from 'vike/types'
 import { getPageElement } from '../node_modules/vike-react/dist/renderer/getPageElement'
+import { bootstrap } from 'safetest/react';

 let root: ReactDOM.Root
 const onRenderClient: OnRenderClientSync = (pageContext): ReturnType<OnRenderClientSync> => {
@@ -31,6 +32,12 @@ const onRenderClient: OnRenderClientSync = (pageContext): ReturnType<OnRenderCli

     root.render(page)
   }
+
+  void bootstrap({
+    element: page,
+    importGlob: import.meta.glob('../**/*.safetest.{j,t}s{,x}'),
+    render: (element) => root.render(element),
+  });
 }

 // https://stackoverflow.com/questions/260857/changing-website-favicon-dynamically/260876#260876

Upstream dependency conflict with Vite 5 when using npm

Description

When attempting to use vike-react in a project with Vite 5 as a dependency, I am encountering an upstream dependency conflict. This issue occurs specifically when using npm as the package manager. Strangely, the same package.json configuration works without issues when using pnpm, which leads me to believe there might be a compatibility issue with npm.

I am not familiar with pnpm and prefer using npm as it is the default package manager for Node.js. However, due to this issue, I am considering switching to pnpm, though I believe compatibility with npm should be maintained in vike-react.

Steps to Reproduce

  1. Set up a new project with the specified package.json configuration.
  2. Run npm install to install dependencies.
  3. Observe the dependency conflict error.

Expected Behavior

Given that vike-react specifies compatibility with vite@^5.0.10 in its peer dependencies, I would expect npm to resolve these dependencies without any conflicts.

"peerDependencies": {
  "react": "18.x.x",
  "react-dom": "18.x.x",
  "vike": "^0.4.151",
  "vite": "^4.3.8 || ^5.0.10"
},

Actual Behavior

npm throws an upstream dependency conflict error when attempting to install the packages, specifically citing an issue with vike-react and Vite 5. This does not occur with pnpm, suggesting a specific issue with npm's resolution process.

package.json Configuration

{
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@vitejs/plugin-react": "^4.2.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "vike": "^0.4.156",
    "vike-react": "^0.3.8"
  },
  "devDependencies": {
    "@types/react": "^18.2.48",
    "@types/react-dom": "^18.2.18",
    "typescript": "^5.3.3",
    "vite": "^5.0.11"
  }
}

Error Log

# npm resolution error report

While resolving: [email protected]
Found: [email protected]
node_modules/vite
  dev vite@"^5.0.11" from the root project
  peer vite@">=3.1.0" from [email protected]
  node_modules/vike
    vike@"^0.4.156" from the root project
    peer vike@"^0.4.151" from [email protected]
    node_modules/vike-react
      vike-react@"^0.3.8" from the root project

Could not resolve dependency:
peer vite@"^4.3.8" from [email protected]
node_modules/vike-react
  vike-react@"^0.3.8" from the root project

Fix the upstream dependency conflict, or retry
this command with --force or --legacy-peer-deps
to accept an incorrect (and potentially broken) dependency resolution.

Environment

  • Node.js Version: v20.11.0
  • npm Version: 10.30.0
  • Operating System: Linux Mint 21.2

How to `vike-react-redux` ?

Hi saw the open pull #57 ๐Ÿš€, I'm very interested in something similar for redux.
But adding a full abstraction over redux seems a little overkill for my case ( & annoying to maintain? )

I'd rather just be able to add a redux provider and global store to renderHtml & renderClient,
whilst using vike-react but without maintaining a seperate plug-in?

Is it already possible to redux with vike-react? ( I didn't manage )

How would one integrate it? ( or does it really require a separate plugin? )

SSR issue with Mui

I am trying to use Mui with Vike SSR mode however if I refresh I get a 500 error but the page works if I change the route from the button click. apparently, the error comes in SSR mode.

6:01:58 PM [vike][request(4)] HTTP response /about 500
6:02:42 PM [vike][request(5)] HTTP request: /about
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check your code at +Page.tsx:10.
    at Page
    at div
    at div
    at Content (/Users/asifsaho/Projects/posinic-website/renderer/PageShell.tsx:112:20)
    at div
    at Layout (/Users/asifsaho/Projects/posinic-website/renderer/PageShell.tsx:66:19)
    at PageContextProvider (/Users/asifsaho/Projects/posinic-website/renderer/usePageContext.tsx:12:32)
    at PageShell (/Users/asifsaho/Projects/posinic-website/renderer/PageShell.tsx:19:22)
6:02:42 PM [vike][request(5)] Following error was thrown by the onRenderHtml() hook defined at /renderer/+onRenderHtml.tsx
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6047:9)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderNode (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6263:12)
    at renderChildrenArray (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6215:7)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6145:7)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5975:9)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderIndeterminateComponent (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5789:7)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5950:7)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderNode (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6263:12)
    at renderHostElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5646:3)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5956:5)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderNode (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6263:12)
    at renderHostElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5646:3)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5956:5)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderIndeterminateComponent (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5789:7)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5950:7)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderNode (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6263:12)
    at renderChildrenArray (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6215:7)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6145:7)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderNode (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6263:12)
    at renderHostElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5646:3)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5956:5)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderIndeterminateComponent (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5789:7)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5950:7)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderContextProvider (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5924:3)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6021:11)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderIndeterminateComponent (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5789:7)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5950:7)
    at renderNodeDestructiveImpl (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    at renderNodeDestructive (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    at renderElement (/Users/asifsaho/Projects/posinic-website/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5975:9)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ To fix this error, see https://vike.dev/broken-npm-package#react-invalid-component โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
6:02:42 PM [vike][request(5)] HTTP response /about 500

Which command to run in production?

Let's say I want to deploy on Netlify. I could either:

  1. use { prerender: true } and let Netlify statically serve dist/client/, or
  2. tell Netlify to run npm run preview (is this really meant for production?), or
  3. is there a third way?

Thanks :)

React Developer Tools doesn't work on first render

Issue description

Whenever you try to render a page for the first time (in development mode), the React Developer Tools will timeout and error.

Screenshot from 2023-10-03 11-16-24

Other behaviors

  1. Some components, for some odd reason, never timeout and actually work, such as the Logo component. However, in the /examples/ssr-spa, the Link component seems to always timeout of the first render.

  2. Sometimes React Developer Tools will straight up just refuse to even load the DOM

    image

  3. Because this example is using client routing, whenever you switch to another page and then page to the same page React Developer Tools will not timeout anymore and work as expected.

    Screencast.from.03-10-2023.11.38.08.webm

Fix suggestion

I believe the root of the issue is because the first render is handled by onRenderHtml, which handles the creation of the page. The client, on the first render, only hydrates the page and therefore is lacking some information required by React Developer Tools.

After the first render, client routing takes control and therefore there's no longer the issue of the client missing any information required by the React Developer Tools.

I found out that by adding '$$typeof' to passToClient fixes this issue.

// /vike-react/renderer/+config.ts

export default {
  // ...
  passToClient: ['pageProps', 'title', '$$typeof']
  // ...
} satisfies Config

I was going to make a pull request for this, however this seems like a very small change and I don't know if it's the best approach to fixing it.

It would also be useful to extend the documentation with this information for people that are trying to build their own renderers/frameworks.

If you're happy with my proposed fix, I could go ahead and create a pull request for both the issue and the documentation. However I don't know what's the most appropriate place to document this.

Provide an export PageContextProvider

Some users may have needs that dictate they use something other than the provided onRenderClient/onRenderHtml in this package; so an export of PageContextProvider would be nice so that it can be set up to use the useData/usePageContext hooks

React-image-gallery npm package does not render

Problem

I am having issues rendering a simple example from the image gallery npm package called "react-image-gallery". This package is widely used and trusted and the documentation seems water tight on their end so I am not sure why I can not render anything from their npm package

Source Code

import ImageGallery from "react-image-gallery";
import "react-image-gallery/styles/css/image-gallery.css";

export function Collaboration () {

  const images = [
    {
      original: "https://picsum.photos/id/1018/1000/600/",
      thumbnail: "https://picsum.photos/id/1018/250/150/",
    },
    {
      original: "https://picsum.photos/id/1015/1000/600/",
      thumbnail: "https://picsum.photos/id/1015/250/150/",
    },
    {
      original: "https://picsum.photos/id/1019/1000/600/",
      thumbnail: "https://picsum.photos/id/1019/250/150/",
    },
  ];


  return (
    <div className="collaboration">
       <ImageGallery items={images} />;
    </div>
  )
}

Console Readout

[vike][request(2)] Following error was thrown by the onRenderHtml() hook defined at /renderer/+onRenderHtml.tsx
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
 To fix this error, see https://vike.dev/broken-npm-package#react-invalid-component

Browser

Cannot GET /

Config.h.ts file

import type { Config } from 'vike/types'

// https://vike.dev/config
export default {
  // https://vike.dev/clientRouting
  clientRouting: true,
  // https://vike.dev/meta
  meta: {
    // Define new setting 'title'
    title: {
      env: { server: true, client: true }
    },
    // Define new setting 'description'
    description: {
      env: { server: true }
    }
  },
  hydrationCanBeAborted: true
} satisfies Config

Additional information

The console readout suggests that I have used an incorrect export syntax for my component but this can not be the case as I have simply commented out the ImageGallery component and replaced it with a div and that exports and renders just fine. Your help would be appreciated here. thanks.

`useId()` unusable with SSR

Moved from vikejs/vike#1291

useId() is supposed to generate deterministic unique IDs. Rendering the app first on the server and then on the client should lead to the same unique ID.

However in vike-react, because we feed react with different apps on server (including <head>) and on client (without <head>), we end up with different IDs, and so with hydration mismatches.

See steps to reproduce.

FYI @AndrejNemec

Feedback on upgrading from vite-plugin-ssr to vike-react

Hi, first off, thanks for all the time you spend making this framework fast and configurable.

I've been using vite-plugin-ssr at Redwood Materials for a little over a year now and finally spent a few days updating to the latest Vike and vike-react versions. Just wanted to share some feedback on how it went and some pain points along the way:

  • Having separate files for each page template and config (e.g. +Page.ts, custom +Head.ts, +title.ts) is a clear pattern, but gets really verbose for lots of pages. I've stuck with +Page.ts and +config.ts, where I export both title and sometimes a custom Head (e.g. a version w/ particular meta tags for a subset of pages)
  • Glad to see we'll soon be able to configure the html and body tags. I ended up adding my Tailwind styles globally as a workaround.
  • As part of the upgrade, I realized that my Head meta tags never change between client-side page transitions. That's not ideal when they contain important SEO data like noindex tags (certain pages should be indexed, others not). It'd be great if there was a lightweight escape hatch to transition important meta properties, similar to how you do currently for page title. I could use Helmet, but would rather avoid a heavy dependency.
  • The favicon solution is so barebones it doesn't feel that useful. Maybe others use a single favicon tag, but I've often found that for cross-browser compat, PWAs, etc I often have at least 4 of them, with different file types, etc.
image
  • It took me a while to figure out that if I wanted to use a global provider (e.g. for SWR) I'd have to use a global +Layout.tsx. Would have been nice if the docs had that as an example of using a provider in +Layout.tsx since it seems like a more sustainable pattern than having to roll your own +onRenderClient.tsx (which is what I started doing before I realized I didn't have to)
  • Is there any reason to stick config files in the renderer folder vs the pages folder? I eventually moved them all to pages.
  • I stuck my tracking scripts at the bottom of +Layout.tsx, but ideally there'd be a way to inject them outside of React.

@brillout , feel free to close this issue, just wasn't sure the best way to get you feedback. Thanks!

Expose `pageContext` to `Head`

A site I'm working on needs to have access to pageContext (particularly routeParams) in Head, in order to emit OpenGraph metadata that depends upon it. However, the current onRenderHtml does not wrap the Head in PageContextProvider.

react-query failing with Cannot find module '.../vike-react/examples/react-query/node_modules/vike-react-query/dist/renderer/StreamedHydration

To reproduce:

  • Clone repository
  • change dependency versions in examples/react-query/package.json to
    "vike-react": "0.3.7",
    "vike-react-query": "0.0.1",
  • run npm run dev
  • visit http://localhost:3000/
  • check logs in the output
|- Error: Cannot find module 'vike-react/examples/react-query/node_modules/vike-react-query/dist/renderer/StreamedHydration' imported from vike-react/examples/react-query/node_modules/vike-react-query/dist/renderer/VikeReactQueryWrapper.js
    at finalizeResolution (node:internal/modules/esm/resolve:264:11)
    at moduleResolve (node:internal/modules/esm/resolve:917:10)
    at defaultResolve (node:internal/modules/esm/resolve:1130:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:396:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:365:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:240:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
    at link (node:internal/modules/esm/module_job:84:36)```

How to change the html tag?

I'm using tailwind and my page always blink switching from light theme to dark theme on client render. I would like to add the dark class by default to the html tag, but I can not find how to change it on server side.

Support having titles that are asynchronously generated based on `routeParams`

I have a site where I have tutorials that are chosen by a route parameter, and I need the title to include the name of the tutorial. This requires that I:

  1. Access the pageContext, and then the routeParams.
  2. await import the appropriate tutorial (it's an AsciiDoc document).
  3. Use the AsciiDoc parser on it, producing a data structure doc.
  4. Use doc.getDocumentTitle() to extract the tutorial title.
  5. Format it into my overall page title.

This is currently impossible with vike-react.

ssr:false doesn't work in latest version

I'm trying to follow the ssr-spa example and set ssr: false in my +config.h but it isn't having any effect.

After further research, I can see that work was done in a previous commit to support this, but the change doesn't exist in the latest version of onRenderClient or onRenderHTML.

Where did this work go?

It looks like there was a reorganization at some point, but it's very confusing to have the config value appear in the examples and documentation but not supported in the actual repo (and also really confusing for the examples' package.json to link to workspace:*).

If we could get an update or maybe a new repo to point to or something that would be very helpful. Thanks in advance for you work and help on this.

For the time being, I'm going to try and recreate the onRenderClient and onRenderHTML from the version I found previously in the repo and see if that gets picked up and works.

Error running on vercel

Hi,

I've got a good setup running with telefunc, vike, vike-react and vike-authjs using node 20+ on vercel. I just included vike-react-query which runs ok in a local environment but fails with the following error only when rendering pages. The other vercel routes (auth and telefunc) work ok.
The error disappears once I remove vike-react-query. I've included some helpful information, please let me know if you need more.

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'react-dom' imported from /var/task/node_modules/.pnpm/@[email protected]/node_modules/@brillout/import/dist/index.js
    at packageResolve (node:internal/modules/esm/resolve:849:9)
    at moduleResolve (node:internal/modules/esm/resolve:906:20)
    at moduleResolveWithNodePath (node:internal/modules/esm/resolve:1126:12)
    at defaultResolve (node:internal/modules/esm/resolve:1169:79)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:396:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:365:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:240:38)
    at ModuleLoader.import (node:internal/modules/esm/loader:328:34)
    at importModuleDynamically (node:internal/modules/cjs/loader:1261:33)
    at importModuleDynamicallyWrapper (node:internal/vm/module:431:21)

Vercel ssr route

import { renderPage } from "vike/server";
import { getSession } from "vike-authjs";
import utils from "./_utilities.js";
import authConfig from "../utilities/authConfig.js";

/**
 * @param {import('@vercel/node').VercelRequest} req
 * @param {import('@vercel/node').VercelResponse} res
 */
export default async (req, res) => {
  const { url } = req;
  if (url === undefined) throw new Error("req.url is undefined");
  const request = utils.makeRequest(req);
  const session = await getSession(request, authConfig);

  console.log("ssr url", url);
  const pageContextInit = { urlOriginal: url, data: { session } };
  const pageContext = await renderPage(pageContextInit);
  const { httpResponse } = pageContext;

  console.log("ssr url", url);
  if (!httpResponse) {
    res.statusCode = 200;
    res.end();
    return;
  }

  const { body, statusCode, headers } = httpResponse;
  //copy all headers from response
  headers.forEach(([name, value]) => res.setHeader(name, value));
  res.status(statusCode).end(body);
};

Dependency list

"devDependencies": {
    "@repo/eslint-config": "workspace:*",
    "@repo/typescript-config": "workspace:*",
    "@types/react": "^18.2.48",
    "@types/react-dom": "^18.2.18",
    "@types/serve-static": "^1.15.5",
    "@typescript-eslint/eslint-plugin": "^6.18.1",
    "@typescript-eslint/parser": "^6.18.1",
    "@vercel/node": "^3.0.17",
    "autoprefixer": "^10.4.16",
    "daisyui": "^4.6.0",
    "eslint": "^8.56.0",
    "eslint-config-react-app": "^7.0.1",
    "postcss": "^8.4.33",
    "prisma": "^5.8.0",
    "tailwindcss": "^3.4.1",
    "typescript": "^5.3.3"
  },
  "dependencies": {
    "@auth/core": "^0.20.0",
    "@hattip/polyfills": "^0.0.38",
    "@prisma/client": "^5.8.0",
    "@repo/ui": "workspace:*",
    "@tanstack/react-query": "^5.17.19",
    "@vite-plugin-vercel/vike": "^2.0.0",
    "@vitejs/plugin-react": "^4.2.1",
    "cross-fetch": "^4.0.0",
    "dotenv": "^16.3.2",
    "h3": "~1.9.0",
    "imapflow": "^1.0.148",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-hot-toast": "^2.4.0",
    "serve-static": "^1.15.0",
    "telefunc": "^0.1.70",
    "tsx": "^4.7.0",
    "vike": "^0.4.160",
    "vike-authjs": "^0.1.4",
    "vike-react": "^0.4.4",
    "vike-react-query": "^0.0.2",
    "vite": "^5.0.12",
    "vite-plugin-vercel": "^2.0.0"
  }

Ouput from pnpm why react-dom

dependencies:
@vite-plugin-vercel/vike 2.0.0
โ”œโ”€โ”ฌ vike 0.4.160 peer
โ”‚ โ””โ”€โ”ฌ react-streaming 0.3.19 peer
โ”‚   โ””โ”€โ”€ react-dom 18.2.0 peer
โ””โ”€โ”ฌ vite-plugin-vercel 2.0.1 peer
  โ””โ”€โ”ฌ vike 0.4.160 peer
    โ””โ”€โ”ฌ react-streaming 0.3.19 peer
      โ””โ”€โ”€ react-dom 18.2.0 peer
react-dom 18.2.0
react-hot-toast 2.4.1
โ””โ”€โ”€ react-dom 18.2.0 peer
telefunc 0.1.70
โ””โ”€โ”ฌ react-streaming 0.3.19 peer
  โ””โ”€โ”€ react-dom 18.2.0 peer
vike 0.4.160
โ””โ”€โ”ฌ react-streaming 0.3.19 peer
  โ””โ”€โ”€ react-dom 18.2.0 peer
vike-react 0.4.4
โ”œโ”€โ”€ react-dom 18.2.0 peer
โ”œโ”€โ”ฌ react-streaming 0.3.19
โ”‚ โ””โ”€โ”€ react-dom 18.2.0 peer
โ””โ”€โ”ฌ vike 0.4.160 peer
  โ””โ”€โ”ฌ react-streaming 0.3.19 peer
    โ””โ”€โ”€ react-dom 18.2.0 peer
vike-react-query 0.0.2
โ””โ”€โ”€ react-dom 18.2.0 peer

GraphQL integrations

Without vike-react, the renderer is owned by the user, which means that the user has full control over integrating GraphQL.

With vike-react, the renderer lives in node_modules/vike-react/, how can we enable vike-react users to integrate GraphQL?

New component hook `useDocument()`

import { useDocument } from 'vike-react'

function MyComponent() {
  const document = useDocument()
  document.title = 'Awesome Product'
  document.head.add(
    <meta name="description" content="This product helps you with...">
  )
  // ...
}

It's particularly relevant when the data fetching logic is co-located with the component, for example when using Telefunc:

// /pages/product/@id/+Page.jsx
// Environement: client, server

import { loadProductInfo } from './Page.telefunc.js'
import { useDocument, usePageContext, useAsync } from 'vike-react'

function MyComponent() {
  const pageContext = usePageContext()
  const product = useAsync(() => loadProductInfo(pageContext.routeParams.id))
  const document = useDocument()
  document.title = product.name
  document.head.set(
    <meta name="description" content={product.description}>
  )
  // ...
}
// /pages/product/@id/Page.telfeunc.js
// Environement: server

export { loadProductInfo }

async function loadProductInfo(id) {
  const product = await sql.run(`SELECT { name, description } FROM products WHERE id = ${id};`)
  return prodcut
}

Some implementation details: #36 (comment).

Related: #67.

`import vikeReact from 'vike-react/config'` gives error `Cannot find module`

I'm following these installation instructions: https://github.com/vikejs/vike-react/tree/dfd748b139d678dc93ff4570663648e5eb87cd36/packages/vike-react#add-to-existing-app

It tells me to add this line:

import vikeReact from 'vike-react/config'

This gives me the TypeScript error:

Cannot find module 'vike-react/config' or its corresponding type declarations.

The following seems to be type-correct:

import vikeReact from 'vike-react'

However it results in this error when running vite:

โœ˜ [ERROR] Could not resolve "react-dom/client"

    ../../node_modules/vike-react/dist/renderer/onRenderClient.js:3:21:
      3 โ”‚ import ReactDOM from 'react-dom/client';
        โ•ต                      ~~~~~~~~~~~~~~~~~~

Versions:

    "vike": "^0.4.159",
    "vike-react": "^0.4.2"

vike-react-query withFallback error prop does not include error properties

Using vike-react-query (v0.0.4), I've noticed that no errors caught by withFallback's error boundary seem to have any of their standard properties, other than message.

For example:

withFallback(
    () => {
        useSuspenseQuery({
            queryKey: ["test"],
            queryFn() {
                throw new Error("Test error!", {
                    cause: new Error("Another one!")
                });
            }
        });
        return null;
    },
    {
        Error({error}) {
            console.log("ERROR LOG:", error);
            return null;
        }
    }
);

I would have expected this code to log an object with name, message, cause, and stack properties, but it only has message.

As far as I can tell, the cause of this is because Error keys are not enumerable, so they are ignored in the Object.assign call that creates the error prop. Trying this directly in the console does the same thing - Object.assign({message: "test"}, new Error("Test!")) returns {message: "test"}.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.