vikejs / vike Goto Github PK
View Code? Open in Web Editor NEWπ¨ Flexible, lean, community-driven, dependable, fast Vite-based frontend framework.
Home Page: https://vike.dev
License: MIT License
π¨ Flexible, lean, community-driven, dependable, fast Vite-based frontend framework.
Home Page: https://vike.dev
License: MIT License
The docs indicate that this plugin can be used with Vue Router for client-side routing, but does not go into any more detail. Is an example planned for this integration? Curious to see how one might get the file-based routing information into Vue Router routes.
Similar to https://github.com/nodejs/nodejs.dev/issues/917
Safari throws an error when scrolling up and down on any clientRouter enabled page.
[Error] SecurityError: Attempt to use history.replaceState() more than 100 times per 30 seconds
replaceState (vite-plugin-ssr_client_router.js:1108)
saveScrollPosition (vite-plugin-ssr_client_router.js:1108)
As discussed in #24, the project has e2e tests, but granular unit tests are still on the todo list.
I have a need for global data that is available to all pages. I am aware that this is possible within the server entrypoint of the application, however that is not a perfect solution in all cases for the following reasons:
import.meta.env
. One could maybe run dotenv.config
to get around this, but it feels inconsistent and hacky to be accessing env vars in two different waysI am proposing the addition of API that would allow for global additions to context props covering all of these areas. I don't have a specific API in mind yet, just opening the discussion as I see a need here.
Repro Steps:
import.meta.env
from inside a page's prerender hookcross-env NODE_ENV=production && npm run build && vite-plugin-ssr prerender --clientRouter
MODE: 'production'
DEV: true
PROD: false
Expected Results:
Having specified NODE_ENV=production, I would expect DEV=false, PROD=true. Additionally, I would expect SSR=true to come through, but it is not showing up at all.
Dear @brillout,
We are encountering circular dependencies when using recursive functions. I was wondering if this is something to do with vite & ssr, or whether it was perhaps your package. I thought it might be just vite & ssr because there is an issue about it, but I thought it might be your package as all the circular dependencies begin with this: /Users/home1/code/lt/csvite/node_modules/vite-plugin-ssr/user-files/infra.node.vite-entry.ts -> /src/pages/tests/index.page.tsx -> ...
I tried putting this in vite.config.ts, but it didn't do anything.
build: {
rollupOptions: {
onwarn(warning, rollupWarn) {
if (warning.code !== 'CIRCULAR_DEPENDENCY') {
rollupWarn(warning)
}
},
},
},
Thank you (again!) for any pointers and apologies if this is nothing to do with vite-plugin-ssr!
With very large sites, it is possible that the prerender process will fail with an EMFILE, too many open files
error. Currently this can be mitigated only be editing os configuration to increase open file limit. If we exposed an option for configuring the max number of open files, users would have more control over this issue, making the plugin more scalable.
Having trouble putting together a minimal reproduction for this, but the stack is below.
Error: [[email protected]][Internal Failure] You stumbled upon a bug in `vite-plugin-ssr`'s source code (an internal assertion failed). This should definitely not be happening, and you should create a new issue at https://github.com/brillout/vite-plugin-ssr/issues/new that includes this error stack (the error stack is enough to debug this). Or reach out on Discord. A fix will be written promptly.
at /Users/chrismcc/workspace/ss/node_modules/vite-plugin-ssr/dist/getPreloadTags.node.js:33:22
at Array.forEach (<anonymous>)
at Object.getPreloadTags (/Users/chrismcc/workspace/ss/node_modules/vite-plugin-ssr/dist/getPreloadTags.node.js:23:22)
at renderHtmlDocument (/Users/chrismcc/workspace/ss/node_modules/vite-plugin-ssr/dist/renderPage.node.js:222:53)
at async renderPageId (/Users/chrismcc/workspace/ss/node_modules/vite-plugin-ssr/dist/renderPage.node.js:116:30)
at async renderPage (/Users/chrismcc/workspace/ss/node_modules/vite-plugin-ssr/dist/renderPage.node.js:96:24)
at async Object.<anonymous> (/Users/chrismcc/workspace/ss/server.js:1713:20)
Vite v2.2.3
It's trying to look up the manifest entry for pages/all.page.tsx
, which doesn't exist in client or server manifest for some reason, even though the page does + works great in dev mode. It's meant to be a SSR page, I don't have any static or prerendered pages. It's also a catchall, the route is defined as:
export default function () {
return {
match: -2
};
}
{
'node_modules/vite-plugin-ssr/page-files/pageFiles.node.ts': {
file: 'pageFiles.node.js',
src: 'node_modules/vite-plugin-ssr/page-files/pageFiles.node.ts',
isEntry: true,
dynamicImports: [
'pages/_error.page.tsx',
'_all.page.97a49683.js',
'pages/onboard.page.tsx',
'pages/session.page.tsx',
'pages/shops.page.tsx',
'pages/_default/_default.page.client.tsx',
'pages/all.page.server.ts',
'pages/onboard.page.server.tsx',
'pages/session.page.server.tsx',
'pages/shops.page.server.tsx',
'pages/_default/_default.page.server.tsx',
'pages/all.page.route.js',
'pages/onboard.page.route.js',
'pages/session.page.route.js',
'pages/shops.page.route.js'
]
},
'pages/_error.page.tsx': {
file: 'assets/_error.page.797e0037.js',
src: 'pages/_error.page.tsx',
isDynamicEntry: true,
imports: [ '_TwoPanelLayout.5aed1da0.js' ]
},
'_TwoPanelLayout.5aed1da0.js': {
file: 'assets/TwoPanelLayout.5aed1da0.js',
assets: [ 'assets/pattern2x.bb73d710.png' ]
},
'_all.page.97a49683.js': {
file: 'assets/all.page.97a49683.js',
isDynamicEntry: true,
imports: [
'_index.4f9d37b7.js',
'_use-graphql.4e21b4ca.js',
'_types.62a059e8.js',
'pages/_error.page.tsx'
],
dynamicImports: [ 'components/PageEditor.tsx' ]
},
'_types.62a059e8.js': { file: 'assets/types.62a059e8.js' },
'_index.4f9d37b7.js': { file: 'assets/index.4f9d37b7.js' },
'_use-graphql.4e21b4ca.js': { file: 'assets/use-graphql.4e21b4ca.js' },
'pages/onboard.page.tsx': {
file: 'assets/onboard.page.b445335a.js',
src: 'pages/onboard.page.tsx',
isDynamicEntry: true,
imports: [
'_TwoPanelLayout.5aed1da0.js',
'_BrandButton.36c3ecbe.js',
'_graphql.e071fc6a.js',
'_use-graphql.4e21b4ca.js',
'_logo.65f94883.js',
'_enums.f99be063.js',
'_types.62a059e8.js'
],
assets: [
'assets/airtablekey900k.534aaf1b.mp4',
'assets/airtablekey900k.5770f3fb.webm',
'assets/airtableshare700k.bc2dac47.mp4',
'assets/airtableshare700k.2685e756.webm',
'assets/googleoutput700k.cbf09c54.mp4',
'assets/googleoutput700k.0d8460f6.webm'
]
},
'_BrandButton.36c3ecbe.js': { file: 'assets/BrandButton.36c3ecbe.js' },
'_graphql.e071fc6a.js': { file: 'assets/graphql.e071fc6a.js' },
'_logo.65f94883.js': {
file: 'assets/logo.65f94883.js',
assets: [ 'assets/logo.85f87099.svg' ]
},
'_enums.f99be063.js': { file: 'assets/enums.f99be063.js' },
'pages/session.page.tsx': {
file: 'assets/session.page.32c80824.js',
src: 'pages/session.page.tsx',
isDynamicEntry: true,
imports: [
'_TwoPanelLayout.5aed1da0.js',
'_graphql.e071fc6a.js',
'_use-graphql.4e21b4ca.js',
'_logo.65f94883.js'
]
},
'pages/shops.page.tsx': {
file: 'assets/shops.page.9f3e6ba7.js',
src: 'pages/shops.page.tsx',
isDynamicEntry: true,
imports: [ '_use-graphql.4e21b4ca.js', '_logo.65f94883.js' ]
},
'pages/_default/_default.page.client.tsx': {
file: 'assets/_default.page.client.b5770ade.js',
src: 'pages/_default/_default.page.client.tsx',
isDynamicEntry: true
},
'pages/all.page.server.ts': {
file: 'assets/all.page.server.e439a3de.js',
src: 'pages/all.page.server.ts',
isDynamicEntry: true,
imports: [
'_types.62a059e8.js',
'_widget-fragment.15763a42.js',
'_shop.699429dc.js'
]
},
'_widget-fragment.15763a42.js': { file: 'assets/widget-fragment.15763a42.js' },
'_shop.699429dc.js': { file: 'assets/shop.699429dc.js' },
'pages/onboard.page.server.tsx': {
file: 'assets/onboard.page.server.fcbbdb8b.js',
src: 'pages/onboard.page.server.tsx',
isDynamicEntry: true,
imports: [ '_enums.f99be063.js' ]
},
'pages/session.page.server.tsx': {
file: 'assets/session.page.server.e7258d58.js',
src: 'pages/session.page.server.tsx',
isDynamicEntry: true
},
'pages/shops.page.server.tsx': {
file: 'assets/shops.page.server.6f2e1061.js',
src: 'pages/shops.page.server.tsx',
isDynamicEntry: true,
imports: [ '_shop.699429dc.js' ]
},
'pages/_default/_default.page.server.tsx': {
file: 'assets/_default.page.server.09a6d56f.js',
src: 'pages/_default/_default.page.server.tsx',
isDynamicEntry: true,
imports: [
'_logo.65f94883.js',
'_BrandButton.36c3ecbe.js',
'_index.4f9d37b7.js'
],
css: [ 'assets/_default.page.server.704ed2fd.css' ]
},
'pages/all.page.route.js': {
file: 'assets/all.page.route.dc102e33.js',
src: 'pages/all.page.route.js',
isDynamicEntry: true
},
'pages/onboard.page.route.js': {
file: 'assets/onboard.page.route.287b457d.js',
src: 'pages/onboard.page.route.js',
isDynamicEntry: true
},
'pages/session.page.route.js': {
file: 'assets/session.page.route.cabbba58.js',
src: 'pages/session.page.route.js',
isDynamicEntry: true
},
'pages/shops.page.route.js': {
file: 'assets/shops.page.route.e0261f54.js',
src: 'pages/shops.page.route.js',
isDynamicEntry: true
},
'components/PageEditor.tsx': {
file: 'assets/PageEditor.9b8afbb3.js',
src: 'components/PageEditor.tsx',
isDynamicEntry: true,
imports: [
'_all.page.97a49683.js',
'_use-graphql.4e21b4ca.js',
'_types.62a059e8.js',
'_widget-fragment.15763a42.js',
'_index.4f9d37b7.js',
'pages/_error.page.tsx',
'_TwoPanelLayout.5aed1da0.js'
]
}
}
{
'pages/_default/_default.page.client.tsx': {
file: 'assets/pages/_default/_default.page.client.tsx.5bd00183.js',
src: 'pages/_default/_default.page.client.tsx',
isEntry: true,
isDynamicEntry: true,
imports: [ '_vendor.2ab1f7ad.js' ],
css: [ 'assets/pages/_default/_default.page.client.tsx.d82a5d3f.css' ]
},
'_vendor.2ab1f7ad.js': {
file: 'assets/vendor.2ab1f7ad.js',
dynamicImports: [
'pages/_error.page.tsx',
'_all.page.15209e07.js',
'pages/onboard.page.tsx',
'pages/session.page.tsx',
'pages/shops.page.tsx',
'pages/_default/_default.page.client.tsx',
'pages/all.page.route.js',
'pages/onboard.page.route.js',
'pages/session.page.route.js',
'pages/shops.page.route.js'
]
},
'pages/_error.page.tsx': {
file: 'assets/_error.page.a5a13a3d.js',
src: 'pages/_error.page.tsx',
isDynamicEntry: true,
imports: [ '_TwoPanelLayout.2282149a.js', '_vendor.2ab1f7ad.js' ]
},
'_TwoPanelLayout.2282149a.js': {
file: 'assets/TwoPanelLayout.2282149a.js',
imports: [ '_vendor.2ab1f7ad.js' ],
assets: [ 'assets/pattern2x.bb73d710.png' ]
},
'_all.page.15209e07.js': {
file: 'assets/all.page.15209e07.js',
isDynamicEntry: true,
imports: [
'_vendor.2ab1f7ad.js',
'pages/_default/_default.page.client.tsx',
'_use-graphql.968707a4.js',
'_types.b4659228.js',
'pages/_error.page.tsx'
],
dynamicImports: [ 'components/PageEditor.tsx' ]
},
'_types.b4659228.js': { file: 'assets/types.b4659228.js' },
'_use-graphql.968707a4.js': {
file: 'assets/use-graphql.968707a4.js',
imports: [ '_vendor.2ab1f7ad.js' ]
},
'pages/onboard.page.tsx': {
file: 'assets/onboard.page.a6f81a5a.js',
src: 'pages/onboard.page.tsx',
isDynamicEntry: true,
imports: [
'_TwoPanelLayout.2282149a.js',
'pages/_default/_default.page.client.tsx',
'_graphql.4e80b5a8.js',
'_vendor.2ab1f7ad.js',
'_use-graphql.968707a4.js',
'_logo.31f1c087.js',
'_types.b4659228.js'
],
assets: [
'assets/airtablekey900k.534aaf1b.mp4',
'assets/airtablekey900k.5770f3fb.webm',
'assets/airtableshare700k.bc2dac47.mp4',
'assets/airtableshare700k.2685e756.webm',
'assets/googleoutput700k.cbf09c54.mp4',
'assets/googleoutput700k.0d8460f6.webm'
]
},
'_graphql.4e80b5a8.js': {
file: 'assets/graphql.4e80b5a8.js',
imports: [ '_vendor.2ab1f7ad.js' ]
},
'_logo.31f1c087.js': {
file: 'assets/logo.31f1c087.js',
imports: [ '_vendor.2ab1f7ad.js' ]
},
'pages/session.page.tsx': {
file: 'assets/session.page.205b7aa6.js',
src: 'pages/session.page.tsx',
isDynamicEntry: true,
imports: [
'_TwoPanelLayout.2282149a.js',
'_graphql.4e80b5a8.js',
'_use-graphql.968707a4.js',
'_logo.31f1c087.js',
'_vendor.2ab1f7ad.js',
'_useEffectOnce.9167af87.js'
]
},
'_useEffectOnce.9167af87.js': {
file: 'assets/useEffectOnce.9167af87.js',
imports: [ '_vendor.2ab1f7ad.js' ]
},
'pages/shops.page.tsx': {
file: 'assets/shops.page.9ce44a2b.js',
src: 'pages/shops.page.tsx',
isDynamicEntry: true,
imports: [
'_use-graphql.968707a4.js',
'_logo.31f1c087.js',
'_vendor.2ab1f7ad.js'
]
},
'pages/all.page.route.js': {
file: 'assets/all.page.route.56b20769.js',
src: 'pages/all.page.route.js',
isDynamicEntry: true
},
'pages/onboard.page.route.js': {
file: 'assets/onboard.page.route.d1d214e5.js',
src: 'pages/onboard.page.route.js',
isDynamicEntry: true
},
'pages/session.page.route.js': {
file: 'assets/session.page.route.5daa49cd.js',
src: 'pages/session.page.route.js',
isDynamicEntry: true
},
'pages/shops.page.route.js': {
file: 'assets/shops.page.route.6973bf40.js',
src: 'pages/shops.page.route.js',
isDynamicEntry: true
},
'components/PageEditor.tsx': {
file: 'assets/PageEditor.df7c5aa1.js',
src: 'components/PageEditor.tsx',
isDynamicEntry: true,
imports: [
'_all.page.15209e07.js',
'_vendor.2ab1f7ad.js',
'_use-graphql.968707a4.js',
'_useEffectOnce.9167af87.js',
'_types.b4659228.js',
'pages/_default/_default.page.client.tsx',
'pages/_error.page.tsx',
'_TwoPanelLayout.2282149a.js'
]
}
}
Let me know if you need some additional info to hunt this one down...
It seems like any URL ending in #
will easily trigger this error if you useClientRouter
, like http://localhost:3000/signup#
. Don't see any negative impact really, just saw the console message and figured I'd let ya know!
I'm on v0.1.0-beta.26, vite 2.1.4.
Uncaught (in promise) Error: [vite-plugin-ssr][Internal Error] Something unexpected happened. Please open a new issue at https://github.com/brillout/vite-plugin-ssr/issues/new and include this error stack.
at newError2 (newError.ts:18)
at assert (assert.ts:20)
at getUrl (getUrl.client.ts:13)
at fetchAndRender (useClientRouter.client.ts:78)
at useClientRouter.client.ts:55
at useClientRouter.client.ts:219
Me again π
I (think) I can't get @vitejs/plugin-legacy working properly, I've set up helmet
for express to generate the Content-Security-Policy
headers for the script hashes and it's generating the legacy bundles, but I think it's not actually referencing anything in my html not in <head/>
nor in <body/>
My vite.config.js
plugins looks like this
plugins: [legacy(), reactRefresh(), ssr()],
Also tried different ordering just to make sure.
Do I have to include anything in my _default.page.server.tsx
manually?
I guess it's due to vite-plugin-ssr
not using Vites static index.html
file π€
Hello People,
I'm trying to create blog on this tool with vue, but I don't know how to map /posts/:post
in homepage? my setup: WindiCSS, Markdown, Vue (without TS) and of course vite-plugin-ssr
. Is it possible to do this using tools I have?
If you don't understand something, please write, then I will describe this.
Thank You
Parameters in Route Strings are passed to contextProps.routeParams
. It should be the same for Route Functions.
Reproduction Steps
// my-page.page.server.js
import { foo } from './bar';
export async function addContextProps() {}
export function setPageProps() {}
// bar.js
const baz = require('./baz')
exports.foo = baz
// baz.js
module.exports = 'foo';
[vite] Error when evaluating SSR module /pages/bar.js:
ReferenceError: require is not defined
Expected Results:
Commonjs dependencies should be transpiled to ES per Vite documentation and supported without throwing errors.
Notes:
What is the plan for getting Vite up to date? We're currently pinned to 2.1.4, 2.1.5 has been out for a while and 2.2.1 just dropped. Also what is the deal with vite-fix-2390
? We expect that to go away eventually?
Currently addContextProps()
is defined in .page.server.js
and always called in Node.js which is an important invariant for people who use SQL/ORM queries in their addContextProps()
functions.
This ticket is about enabling addContextProps()
to be called in the browser by defining it in .page.js
instead of .page.server.js
. It would still always be called in Node.js when rendering a page to HTML, but for any susequent page navigation addContextProps()
would be called in the browser (when using useClientRouter()
).
Dear @brillout,
Thank you for this plugin, it looks very promising.
update: seems to be working perfectly now!
If you have time, would you mind creating a very basic example using apollo client? I am probably doing something stupid but I don't think I can figure it out on my own.
// apollo/index.ts
import 'cross-fetch/polyfill';
import { ApolloClient } from '@apollo/client'
import { InvalidationPolicyCache } from 'apollo-invalidation-policies';
export const client = new ApolloClient({
cache: new InvalidationPolicyCache({}),
uri: 'https://countries.trevorblades.com'
})
// pages/tests/index.page.server.ts
import { gql } from '@apollo/client'
import {client} from '../../apollo'
export { addContextProps }
export { setPageProps }
export const LIST_COUNTRIES = gql`
{
countries {
name
code
}
}
`;
async function addContextProps({ contextProps }) {
const response = await client.query({query: LIST_COUNTRIES})
return { countries: response.data.countries }
}
function setPageProps({ contextProps: { countries } }) {
return { countries }
}
// pages/tests/index.page.tsx
import React from "react";
import { useQuery } from '@apollo/client'
import "./index.css";
import {client} from '../../apollo'
import {LIST_COUNTRIES} from './index.page.server'
export { Page };
function Page({countries}) {
const {data} = useQuery(LIST_COUNTRIES, {client});
console.log('countries', countries) // This is not working
console.log('data', data) // This works
return (
<>
<h1>TEsts</h1>
<p>A okay text.</p>
</>
);
}
Thank you very much,
Lydia
Sitemaps are an extremely common need. Basically every application should have one for SEO purposes. Since this plugin is taking on responsibility for rendering out all the routes of an application, I feel like there should be a solution (or at least guidance) facilitating the generation of a sitemap file.
One possibility would be to simply treat a sitemap as any other page file. There may be issues around it showing up as a route alongside "real" application routes though, not sure. Sitemaps are also xml, generally placed at root as sitemap.xml, so I'm not sure if the prerendering logic could currently handle that.
Another option would be to automatically generate sitemaps for users based on their prerender routes. There would need to be some additional configurability in order to facilitate things like i18n, lastmod, etc. This also means users who didn't bother to fill in prerender hooks (perhaps they're just using straight SSR) won't get a sitemap. Otherwise though, it seems like a more user-friendly option.
Thoughts / ideas?
You can just call me the #
guy...
Vite 2.1.4
vite-plugin-ssr 0.1.0-beta.33 (really appreciate all the previous fixes, library is looking really good!)
Two things I'm seeing:
On vite-plugin-ssr/examples/react
, isOriginalUrl
is returning false when navigating to /#
, which leads to a fetch of /index.contextProps.json
, because /#
!== /
. I believe this is an unnecessary and not expected fetch. https://github.com/brillout/vite-plugin-ssr/blob/a91ffcae2d8fc525202855887b7b409b752de328/src/client/navigationState.client.ts#L16-L18
Somewhat related as I think this would be resolved if 1 is resolved, but might be a different underlying issue. On vite-plugin-ssr/examples/react
, define a file index.page.route.js
that contains:
export default function ({ contextProps }) {
if (contextProps.url === "/") {
return {
match: -1
};
}
return { match: false };
}
Loading the index with a hash at the end, /#
, you'll see it correctly SSRs, but during hydration it is actually matching and hydrating the error page and not the index page, which leads to a hydration error as the html doesn't match. I believe this is because contextProps
aren't being passed to the route function during the client side routing.
Forgive me for opening a new problem, but I did not understand how it is possible to get on the server in the lower levels of components where I will call ServerPrefetch () and receive data in Vieks and transfer data from the router there.
Example:
<script>
import { mapState, mapActions } from 'vuex'
export default {
name: 'SearchBar',
serverPrefetch() {
return this.getSearch()
},
mounted() {
if(!this.searchLocation && !this.searchCategory)
this.getSearch()
},
computed: {
...mapState('application', ['viewPort', 'categories']),
...mapState('search', ['searchCategory', 'searchLocation', 'searchLoading'])
},
methods: {
...mapActions('search', ['setSearch']),
getSearch() {
if(this.$route && this.$route.params && (!this.searchCategory || !this.searchLocation))
return this.setSearch({
location: this.$route.params.location ? this.$route.params.location : null,
category: this.$route.params.category ? this.$route.params.category : null
})
else return null
},
toSearch() {
window.location.href = `/search/${
this.searchLocation && this.searchLocation.nameEnLowercase
? this.searchLocation.nameEnLowercase : 'all_cities'
}/${
this.searchCategory && this.searchCategory.translit
? this.searchCategory.translit : 'all_categories'
}`
}
}
}
</script>
I see route params in *.page.server.js contextProps.url but how I can recive this parameters in components in serverPrefetch()
Hi, at first thanks for your job!
But I have some question about pass some routing props into components to render active link or etc.
As example, I have a navigation component with set of links, and one of link need to have an active class.
Via Vue-Router I have a global props $router
or $route.path
into templates scope, but I don't know how to do that with your tool.
<a :class="{active: $route.path === href }" ></a>
Hey there, your plugin looks very promising, thanks a lot for your efforts π
I'm completely new to vite, worked only with Gatsby and Next so far with Tailwind.
I tried WindiCSS in a "raw" Vite scaffold (using the CLI) then installing Windi according to the vite-plugin-windicss docs which worked just as expected.
Trying to do replicate this in my beforehand scaffolded vite-plugin-ssr project using the CLI failed to import the CSS styles (only the custom properties --tw-* are included in the final build .css).
I've put the import "virtual:windi.css";
"everywhere" starting in _default.page.client.tsx
than added to index.page.tsx
without any changes.
Uh I'm also using useClientRouter
in _default.page.client.tsx
.
What am I missing or doing wrong?
Currentlly, the server has to be manually restarted for server-side code changes.
Related ticket: vitejs/vite#2392. The proposed solution would enable not only auto-reload but also HMR.
The problem was when using sΡoped styles together with a router-link in one component, I took a ready-made example that was here but it gave an error
file: pages/Home.vue
<template>
<h1>Home</h1>
<p>This content is rendered to HTML.</p>
<router-link to="/lol">Home</router-link>
</template>
<style scoped>
h1 {
color: green;
}
</style>
Error
Error: Unable to parse {"file":"/","line":4,"column":299}
2 | <html>
3 | <body>
4 | <div id="app"><!--[--><div><a aria-current="page" href="/" class="router-link-active router-link-exact-active">Home</a> | <a href="/about" class="">About</a><!--[--><h1 data-v-7f245110>Home</h1><p data-v-7f245110>This content is rendered to HTML.</p><a href="/lol" class="" data-v-7f245110 data-v-7f245110>Home</a><!--]--></div><div><button>count is: 0</button></div><!--]--></div>
|
^
5 | </body>
6 | </html>
at traverseHtml (D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\node_modules\vite\dist\node\chunks\dep-efe32886.js:23936:15)
at async devHtmlHook (D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\node_modules\vite\dist\node\chunks\dep-efe32886.js:59458:5)
at async applyHtmlTransforms (D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\node_modules\vite\dist\node\chunks\dep-efe32886.js:24202:21)
at async applyViteHtmlTransform (D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\node_modules\vite-plugin-ssr\dist\renderPage.node.js:227:20)
at async renderPageId (D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\node_modules\vite-plugin-ssr\dist\renderPage.node.js:114:20)
at async renderPage (D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\node_modules\vite-plugin-ssr\dist\renderPage.node.js:63:24)
at async D:\vite-plugin-ssr-master\vite-plugin-ssr-master\examples\vue-router\server\index.js:28:20
[vite-plugin-ssr][Warning] No `_error.page.js` found. We recommend creating a `_error.page.js` file. (This warning is not shown in production.)
Hello
Thanks for this perfect library. It is amazing. I am working on this vue-router example and need to use vueuse/head package to manage titles dynamically but not made work it. Are there any configs etc. about this?
Here are my app.js
import { createSSRApp } from "vue";
import { createRouter } from "./router";
import { createStore } from "../store/store";
import { createHead } from "@vueuse/head";
export { createApp };
function createApp({ Page }) {
const app = createSSRApp(Page);
const router = createRouter();
const store = createStore();
const head = createHead();
app.use(store);
app.use(router);
app.use(head);
return { app, router, store, head };
}
all.page.server.js
import { renderToString } from "@vue/server-renderer";
import { html } from "vite-plugin-ssr";
import { createHead, renderHeadToString } from "@vueuse/head";
import { createApp } from "./app";
export { render };
export { addContextProps };
export { setPageProps };
async function render({ contextProps }) {
const { appHtml } = contextProps;
const head = createHead();
const { headTags, htmlAttrs, bodyAttrs } = renderHeadToString(head);
return html`<!DOCTYPE html>
<html>
<head>
${html.dangerouslySetHtml(headTags)}
</head>
<body>
<div id="app">${html.dangerouslySetHtml(appHtml)}</div>
</body>
</html>`;
}
async function addContextProps({ Page, contextProps }) {
const { app, store, router } = createApp({ Page });
await router.push(contextProps.url);
await router.isReady();
const appHtml = await renderToString(app);
const INITIAL_STATE = store.state;
return {
INITIAL_STATE,
appHtml,
};
}
function setPageProps({ contextProps }) {
const { INITIAL_STATE } = contextProps;
return { INITIAL_STATE };
}
About.vue component
<template>
<p>The count is preserved when switching between "Home" and "About".</p>
</template>
<script setup>
import { useHead } from "@vueuse/head";
useHead({
title: "My About Page",
});
</script>
I cant see my title in SSR rendered code.
I have a seperate tsconfig for code in server/
called tsconfig.server.json
.
This crashes the SSR.
err: {
"type": "Error",
"message": "[vite-plugin-ssr][Wrong Usage] The file /tsconfig.server.json should be name `*.page.server.*`. Add the missing `.page`.",
"stack":
Error: [vite-plugin-ssr][Wrong Usage] The file /tsconfig.server.json should be name `*.page.server.*`. Add the missing `.page`.
at /Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/user-files/getUserFiles.shared.ts:66:7
at Array.forEach (<anonymous>)
at /Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/user-files/getUserFiles.shared.ts:64:46
at Array.forEach (<anonymous>)
at assertExtensions (/Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/user-files/getUserFiles.shared.ts:59:34)
at Object.getUserFiles (/Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/user-files/getUserFiles.shared.ts:20:3)
at getPageIds (/Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/route.node.ts:141:21)
at Object.route (/Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/route.node.ts:24:22)
at render (/Users/moeriki/Projects/flex-template/node_modules/vite-plugin-ssr/render.node.ts:29:22)
}
Renamed tsconfig.server.json
to tsconfig.backend.json
.
Let me know if I should PR. π
I would like to use prerender
function with a different base
set in vite.config.json
. Prerendering works except the paths to the rendered css/js/asset
files is nog pre-pended with the base
.
Example result with a base set to /tests/vite/
:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="/tests/vite/assets/logo.bebe2e90.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<link rel="modulepreload" crossorigin href="/assets/pages/_default/_default.page.client.ts.e43e8364.js">
<link rel="stylesheet" href="/assets/pages/_default/_default.page.client.ts.824b1405.css">
<link rel="preload" href="/assets/logo.bebe2e90.svg">
</head>
<body>
<div id="app">
<div class="layout" data-v-0d0df46e>
<div class="navigation" data-v-0d0df46e><a href="/" class="logo" data-v-0d0df46e><img src="/tests/vite/assets/logo.bebe2e90.svg" height="64" width="64" data-v-0d0df46e></a><a href="/" data-v-0d0df46e>Home</a><a href="/about" data-v-0d0df46e>About</a><a href="/star-wars" data-v-0d0df46e>Star Wars</a></div>
<div class="content" data-v-0d0df46e>
<!--[--><!--[-->
<h1>Star Wars Movies</h1>
<ol>
<!--[-->
<li><a href="/star-wars/1">A New Hope</a> (1977-05-25) </li>
<li><a href="/star-wars/2">The Empire Strikes Back</a> (1980-05-17) </li>
<li><a href="/star-wars/3">Return of the Jedi</a> (1983-05-25) </li>
<li><a href="/star-wars/4">The Phantom Menace</a> (1999-05-19) </li>
<li><a href="/star-wars/5">Attack of the Clones</a> (2002-05-16) </li>
<li><a href="/star-wars/6">Revenge of the Sith</a> (2005-05-19) </li>
<!--]-->
</ol>
<p> Source: <a href="https://swapi.dev/api/films/">swapi.dev/api/films/</a>. </p>
<p> Data can be fetched by using <code>addContextProps</code> and <code>setPageProps</code>. </p>
<!--]--><!--]-->
</div>
</div>
</div>
<script>window.__vite_plugin_ssr = {pageId: "\u002Fpages\u002Fstar-wars\u002Findex", pageProps: {movies:[{title:"A New Hope",release_date:"1977-05-25",id:"1"},{title:"The Empire Strikes Back",release_date:"1980-05-17",id:"2"},{title:"Return of the Jedi",release_date:"1983-05-25",id:"3"},{title:"The Phantom Menace",release_date:"1999-05-19",id:"4"},{title:"Attack of the Clones",release_date:"2002-05-16",id:"5"},{title:"Revenge of the Sith",release_date:"2005-05-19",id:"6"}],docTitle:"6 Star Wars Movies"}}</script><script type="module" src="/assets/pages/_default/_default.page.client.ts.e43e8364.js"></script>
</body>
</html>
As you can see only the svg
is using the correct path.
Thanks for the great plugin!
As far as I can tell, the render
function isn't called during client-side routing, so the current way to redirect outlined in the Readme doesn't seem to work when also using client-side routing. I tried using navigate
, which worked well for client-side, but errors out when accessing the URL directly because navigate
cannot be called on the server (see also #21). Is there a universal way to use client-side routing + redirects?
I could do something like this but it feels tacky:
// movie.page.server.js
export { render }
function render({ contextProps }) {
if (contextProps.movieId === null) {
return { redirectTo: '/movie/add' }
}
}
// movie.page.js
import { navigate } from "vite-plugin-ssr/client/router";
export { Page };
const Page = ({ movieId }) => {
if (typeof window !== 'undefined' && movieId === null) {
navigate('/movie/add');
}
return ...;
};
Thanks in advance!
Hi there,
When I run yarn server:prod
the server starts fine (I see the server running at http://localhost:3000
message) but, when I try to make a request from the browser I get an error message in the console and the browser never receives a response.
The dev server (yarn dev
) does not have this problem.
I followed the "Manual Installation" section of the README for React + TypeScript so it's possible I missed something but, as far as I can tell, what I have is the same as the react-typescript boilerplate.
Error message:
(node:27112) UnhandledPromiseRejectionWarning: TypeError: __getAllUserFiles is not a function
at Object.getAllUserFiles (.../node_modules/vite-plugin-ssr/user-files/infra.node.ts:13:10)
at Object.getUserFiles (.../node_modules/vite-plugin-ssr/user-files/getUserFiles.shared.ts:18:38)
at Object.getPageIds (.../node_modules/vite-plugin-ssr/route.node.ts:166:21)
at renderPage (.../node_modules/vite-plugin-ssr/renderPage.node.ts:48:22)
at .../index.ts:25:20
package.json script:
"scripts": {
// ...
"server:prod": "cross-env NODE_ENV=production ts-node ./server",
},
server/index.ts:
import express from 'express'
import { createPageRender } from 'vite-plugin-ssr'
import * as vite from 'vite'
const isProduction = process.env.NODE_ENV === 'production'
const root = `${__dirname}/..`
async function startServer() {
const app = express()
let viteDevServer: vite.ViteDevServer | undefined
if (isProduction) {
app.use(express.static(`${root}/dist/client`, { index: false }))
} else {
viteDevServer = await vite.createServer({ root, server: { middlewareMode: true }})
app.use(viteDevServer.middlewares)
}
const renderPage = createPageRender({ viteDevServer, isProduction, root })
app.get('*', async (req, res, next) => {
const url = req.originalUrl
const contextProps = {}
const result = await renderPage({ url, contextProps })
if (result.nothingRendered) return next()
res.status(result.statusCode).send(result.renderResult)
})
const port = 3000
app.listen(port, () => {
console.log(`π server running at http://localhost:${port}`)
})
}
startServer()
Any help would be appreciated. Thanks in advance.
Reproduction Steps:
npm run prerender && echo 'hi'
Expected Results:
Any error encountered during prerender should immediately exit the process via process.exit(1)
to prevent operations downstream (e.g. deploying a broken site).
At scale, rendering pages in worker threads can become crucial. If you need this, write a comment here.
EDIT: not to be confused with Cloudflare Workers, which is already supported https://vite-plugin-ssr.com/cloudflare-workers
running vite build && vite build --ssr
in beta.17 works great, on beta.18 I'm seeing:
yarn build
yarn run v1.22.10
$ vite build && vite build --ssr
vite v2.1.2 building for production...
β 739 modules transformed.
dist/client/assets/logo.3cedc8da.svg 0.70kb
dist/client/manifest.json 1.54kb
dist/client/assets/_error.page.b5099f66.js 0.34kb / brotli: 0.18kb
dist/client/assets/all.page.92fdd9ff.js 0.20kb / brotli: 0.12kb
dist/client/assets/index.page.e794d9eb.js 0.44kb / brotli: 0.21kb
dist/client/assets/all.page.route.75506379.js 0.05kb / brotli: 0.05kb
dist/client/assets/signup.page.route.774ca72d.js 0.08kb / brotli: 0.08kb
dist/client/assets/signup.page.993c3da0.js 29.28kb / brotli: 9.13kb
dist/client/assets/pages/_default/_default.page.client.tsx.cc6ca426.js 243.40kb / brotli: 67.29kb
vite v2.1.2 building SSR bundle for production...
> node_modules/vite/dist/node/chunks/dep-efe32886.js:31549:7: error: [vite:dep-scan] No known conditions for "." entry in "vite-plugin-ssr" package
31549 β throw new Error(
β΅ ^
at bail (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:31549:8)
at resolve$1 (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:31605:32)
at resolveExports (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:32022:12)
at resolvePackageEntry (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:31950:22)
at tryNodeResolve (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:31847:11)
at Context.resolveId (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:31730:28)
at Object.resolveId (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:43592:55)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async resolve (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:43786:26)
at async /Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:43871:34
node_modules/vite/dist/node/chunks/dep-efe32886.js:43861:18: note: This error came from the "onResolve" callback registered here
43861 β build.onResolve({
β΅ ~~~~~~~~~
at setup (/Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:43861:19)
at handlePlugins (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:686:7)
at Object.buildOrServe (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:903:44)
at /Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:1436:17
at new Promise (<anonymous>)
at Object.build (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:1435:14)
at Object.build (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:1326:51)
at /Users/chrismcc/workspace/ss/node_modules/vite/dist/node/chunks/dep-efe32886.js:43740:54
at Array.map (<anonymous>)
pages/_default/_default.page.server.tsx:6:21: note: The plugin "vite:dep-scan" was triggered by this import
6 β import { html } from 'vite-plugin-ssr';
β΅ ~~~~~~~~~~~~~~~~~
error during build:
Error: Build failed with 1 error:
node_modules/vite/dist/node/chunks/dep-efe32886.js:31549:7: error: [vite:dep-scan] No known conditions for "." entry in "vite-plugin-ssr" package
at failureErrorWithLog (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:1216:15)
at buildResponseToResult (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:936:32)
at /Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:1035:20
at /Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:568:9
at handleIncomingPacket (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:657:9)
at Socket.readFromStdout (/Users/chrismcc/workspace/ss/node_modules/esbuild/lib/main.js:535:7)
at Socket.emit (events.js:315:20)
at addChunk (internal/streams/readable.js:309:12)
at readableAddChunk (internal/streams/readable.js:284:9)
at Socket.Readable.push (internal/streams/readable.js:223:10)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Seems like it may stem from this change: 4cfe4ef#diff-cc5a2f170768969f124108ad3be7fdbcbed774c11774d99a87a3a78fef4ab97bR24
[Error] Unhandled Promise Rejection: Error: [[email protected]][Internal Failure] You stumbled upon an bug in `vite-plugin-ssr`'s source code (an internal assertion failed). This should definitely not be happening, and you should create a new issue at https://github.com/brillout/vite-plugin-ssr/issues/new that includes this error stack (the error stack is enough to debug this). Or reach out on Discord. A fix will be written promptly.
(anonymous function) (vite-plugin-ssr_client_router.js:1029)
asyncFunctionResume
(anonymous function)
promiseReactionJobWithoutPromise
promiseReactionJob
Reproduction is something like:
const searchQuery = '"a"';
navigate(`/?q=${searchQuery}`);
Note changing it to:
navigate(`/?q=${encodeURIComponent(searchQuery)}`);
...works fine, so it may just be a matter of documentation / a better error message.
(this is a minor issue)
Reproduction Steps:
article.page.vue
and articles.page.vue
Error: [vite-plugin-ssr][Wrong Usage] Conflicting /pages/article.page.vue /pages/articles.page.vue
Expected Results:
I'm guessing this is guarding against some known bad / ambiguous state in the pages configuration, but being able to use plural words seems like fair use and should be supported(?)
JSDB is a 100% JavaScript database. The latest version is written in ESM. Simply importing it causes errors that do not otherwise exist in other contexts.
npm init vite-plugin-ssr
npm i @small-tech/jsdb
import JSDB from '@small-tech/jsdb'
There should not be any errors.
Initially, you get the following error:
Error: Failed to resolve import "fs/promises" from "pages/_default/_default.page.server.js". Does the file exist?
at formatError (/home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/vite/dist/node/chunks/dep-2c03f3f9.js:43582:46)
This is because the JSTable.js file in JSDB has the following import:
import fsPromises from 'fs/promises'
I donβt know if this is an issue with vite-plugin-ssr or vite itself. The workaround is to change the import to:
import fs from 'fs'
const fsPromises = fs.promises
Needless to say, while I can do this in a module I control, this would mean Iβd have to update all third-party modules that might use these sorts of imports in the future to make them compatible.
Once that error is out of the way, you get several related errors:
1:53:15 PM [vite] error while updating dependencies:
Error: Build failed with 3 errors:
node_modules/@small-tech/jsdb/lib/JSTable.js:26:9: error: No matching export in "browser-external:perf_hooks" for import "performance"
node_modules/@small-tech/jsdb/lib/Time.js:15:9: error: No matching export in "browser-external:perf_hooks" for import "performance"
node_modules/@small-tech/jsdb/lib/Util.js:15:9: error: No matching export in "browser-external:util" for import "types"
at failureErrorWithLog (/home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/esbuild/lib/main.js:1224:15)
at buildResponseToResult (/home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/esbuild/lib/main.js:936:32)
at /home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/esbuild/lib/main.js:1035:20
at /home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/esbuild/lib/main.js:568:9
at handleIncomingPacket (/home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/esbuild/lib/main.js:657:9)
at Socket.readFromStdout (/home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/esbuild/lib/main.js:535:7)
at Socket.emit (events.js:315:20)
at addChunk (internal/streams/readable.js:309:12)
at readableAddChunk (internal/streams/readable.js:284:9)
at Socket.Readable.push (internal/streams/readable.js:223:10)
This time itβs clearly an issue with esbuild. The previous error did not have the same stack trace but it might also be with viteβs use of esbuild. (If this is unreleated to vite-plugin-ssr, Iβll open separate issues on vite and/or esbuild.)
(Although I donβt think itβs esbuild as I bundle Place using esbuild and it imports JSDB without issues. And I just tried it with esbuild 0.9.3 β the same version used here β also and it worked without issues.)
Again, the fix is to rewrite the imports:
So import { performance } from 'perf_hooks'
becomes:
import perfHooks from 'perf_hooks'
const performance = perfHooks.performance
etc.
Once those changes have been made, I no longer get errors but loading the index page causes the browser to enter an infinite loading loop with no warnings or errors either in the browser or on the console.
Iβm opening the issue here as I have a straightforward way of reproducing the error and want to document it somewhere.
If this is an issue with vite and/or esbuild (which seems likely) and not due to anything vite-plugin-ssr is doing specifically, Iβll open issues on the vite and/or esbuild trackers to point to this one.
In principle, vite-pluign-ssr
can be used with Cloudflare Workers; there are no hard dependencies on Node.js APIs.
If I remember correctly, a Cloudlare Worker is defined as a single JS file, which means that the entire runtime needs to be bundled in a single file. Super neat would be a vite-plugin-cloudflare
that does this and which is compatible with vite-plugin-ssr
.
cc @schickling
We will release 0.1.0
soon.
The user specifies website infos and meta tags are automatically generated https://www.matuzo.at/blog/html-boilerplate/
This should be possible with https://discord.com/channels/804011606160703521/804061937029218334/810901252862509067
Instead of having several page files (.page.js
, .page.route.js
, .page.server.js
, .page.client.js
), we would define everything in .page.js
(while vite-plugin-ssr
automatically statically extracts the relevant parts like in https://next-code-elimination.vercel.app.)
Many people have expressed a longing for this, but I'm on the fence. Simply because I highly value clarity and simplicity: it's obvious and simple what the .page.js
, .page.route.js
, .page.server.js
, and .page.client.js
files are about, whereas if we merge everything in .page.js
it becomes less clear what is run in what environment.
This may be mostly a docs change, but it would be good to have a solution for deploying applications into serverless infrastructure like AWS Lambda. I'd imagine it wouldn't be too difficult with something like this https://github.com/vendia/serverless-express
Hello again π
I'm seeing a fun redirect loop when navigating to a 404 page that has a #
in the URL.
Vite: 2.1.4
vite-plugin-ssr: 0.1.0-beta.32 (also an issue in 0.1.0-beta.31, did not test beyond that)
Reproduction steps:
Checkout example at https://github.com/brillout/vite-plugin-ssr/tree/master/examples/react install & run.
Navigate to a 404 page with a #
at the end, like /aaa#
.
Notice the page continually loads, and %23
gets added onto the URL over and over again.
Steps to Reproduce:
collectAssets
in /dist/getPreloadTags.node.js
Expected Results:
Customizing the assetsDir should successfully prerender the site into the customized directory
Create the starter Vue app (npm init vite-plugin-ssr
)
Change the project type to ESM ("type": "module"
in package.json)
Update server.js to use import syntax:
import express from 'express'
import { createPageRender } from 'vite-plugin-ssr/dist'
import vite from 'vite'
Run it (npm run dev
)
It should run.
internal/process/esm_loader.js:74
internalBinding('errors').triggerUncaughtException(
^
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/aral/small-tech/small-web/sitekit/sandbox/vite-ssr-project/node_modules/vite-plugin-ssr/index.ts
at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:71:15)
at Loader.getFormat (internal/modules/esm/loader.js:102:42)
at Loader.getModuleJob (internal/modules/esm/loader.js:231:31)
at async ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:58:21)
at async Promise.all (index 1)
at async link (internal/modules/esm/module_job.js:63:9) {
code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
My Node server project uses ESM, not CommonJS.
Well done for your work, I really appreciate your effort towards DX.
Is it possible to add a CSS/UI framework of choice?
PrimeVue, ant-design-vue, etc!
As an example, my generated site yields:
index.html
news.html
/news
news-article-1.html
When I point a basic HTTP server at the generated files, /news/ resolves to a generic HTML index of the /news directory. This is because the news directory takes precedence over the news.html file, so news.html is ignored and there is no /news/index.html so it uses a generic index.
My suggestion would be to just name all HTML files index.html in directories with their identifiers. This should lead to more predictable routing.
For building to work vite-plugin-ssr
needs to be linked. See vitejs/vite#2390.
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.