Coder Social home page Coder Social logo

vinxi's Introduction

The Full Stack JavaScript SDK to build full stack apps and frameworks with your own opinions.
powered by vite and nitro

vinxi

Compose full stack applications (and frameworks) using Vite, the versatile bundler and dev server, and Nitro, the universal production server. The core primitive in vinxi is a router.

Inspired by the Bun.App API.

  • Routers are handlers that tell us how specific URLs should be handled. We support various router modes: "static", "spa", "http", (and new ones can be added). Routers specify the handler file (entrypoint) to use for their base-prefixed routes. They can also specify a dir and style in some router modes to include a file system router that is provided to the handler. Routers specify their bundler configuration, via the build property. The routers tell the bundler what entry points to build, what vite plugins to use, etc.

Examples

Framework Category Example StackBlitz Link
React RSC SPA Open in StackBlitz
SPA Basic Open in StackBlitz
MDX Open in StackBlitz
TanStack Router (Pages) Open in StackBlitz
TanStack Router (App) Open in StackBlitz
Wouter Open in StackBlitz
SSR Basic Open in StackBlitz
Basic w/Cloudflare Open in StackBlitz
TanStack Router (App) Open in StackBlitz
Wouter Open in StackBlitz
Solid SPA Basic Open in StackBlitz
SSR Basic Open in StackBlitz
Solid Router Open in StackBlitz
Vanilla SPA Open in StackBlitz
TRPC Open in StackBlitz

Goals

Primary goal is to build the tools needed to build a NextJS or SolidStart style metaframework on top of vite without worrying about a lot of the wiring required to keep dev and prod working along with SSR, SPA, RSC, and all the other acronyms. etc. On top of that, we should be able to deploy anywhere easily.

Mostly trying to disappear for the user outside the app.js file

The surface layer we are intending to tackle:

  1. Full stack builds (handle manifest stuff to figure out what assets to load at prod runtime)
  2. Dev time asset handling (avoiding FOUC in SSR frameworks) and smoothing over some of vite's dev/prod mismatching behaviours by providing common manifest APIs that work in dev and prod the same way
  3. File system router (not any specific file system conventions, just an API for interfacing with FileSystemRouters and utils to implement your conventions in them)
  4. Building the server, and providing a simple opaque handler API to control the server
  5. Adapter stuff to deploy to various platforms with support for all the features they provide
  6. Not to abstract away the platforms. Let people use what they want to the fullest
  7. Have little opinion about how the app should be authored or structured

Roadmap

  • vinxi deploy
  • hooks throughout the app licycle:
    • dev: app:created, app:started, router:created

Try it out

npm install vinxi

React SSR

import reactRefresh from "@vitejs/plugin-react";
import { createApp } from "vinxi";

export default createApp({
	routers: [
		{
			name: "public",
			type: "static",
			dir: "./public",
		},
		{
			name: "client",
			type: "client",
			handler: "./app/client.tsx",
			target: "browser",
			plugins: () => [reactRefresh()],
			base: "/_build",
		},
		{
			name: "ssr",
			type: "http",
			handler: "./app/server.tsx",
			target: "server",
		},
	],
});

Solid SSR

import { createApp } from "vinxi";
import solid from "vite-plugin-solid";

export default createApp({
	routers: [
		{
			name: "public",
			type: "static",
			dir: "./public",
		},
		{
			name: "client",
			type: "client",
			handler: "./app/client.tsx",
			target: "browser",
			plugins: () => [solid({ ssr: true })],
			base: "/_build",
		},
		{
			name: "ssr",
			type: "http",
			handler: "./app/server.tsx",
			target: "server",
			plugins: () => [solid({ ssr: true })],
		},
	],
});

vinxi's People

Contributors

nksaraf avatar edivados avatar github-actions[bot] avatar birkskyum avatar ryansolid avatar tommypop2 avatar indeyets avatar albertsabate avatar alessandrojcm avatar lxsmnsyc avatar jessevelden avatar ludofischer avatar marvin-j97 avatar mkassabov avatar doeixd avatar pi0 avatar russelgal avatar yume-chan avatar zangetsu101 avatar leaysgur avatar jer3m01 avatar nvos avatar

Stargazers

Sngmn451 avatar Shin seongsu avatar Niklas Wallerstedt avatar Sam Meech-Ward avatar Kyle Mazza avatar simon avatar Jamal Shr avatar Manon Lefevre avatar Lukas Stauersbøl avatar  avatar Ben Williams avatar Rupesh avatar lasse avatar Rizkyy avatar Sven avatar Ian Macalinao avatar Danar Widi avatar Zhazha_JiaYiZhen avatar Wei Zhu avatar Neil Camilleri avatar WJ-Yuan avatar vadxq avatar Abiria avatar Arif Tunahan Deniz avatar Ramazan Akbal avatar Chad Adams avatar  avatar Amir avatar Rafael Oliveira avatar Chris McMordie avatar Jong Taek Oh avatar Kav Singh avatar Muhammad Haris avatar Jesús Ferretti avatar Aaron Hakala avatar Jems avatar Mihael Konjević avatar Josua Zurbrügg avatar Mustafa avatar Malcolm Fell avatar peetzweg/ avatar Joseph Anson avatar Budi Prakosa a.k.a Iyok avatar Brandon Orther avatar Tiago Colin avatar _nderscore avatar Cafer Can Gündoğdu avatar Artie Fuzzz avatar Shekhar K. Sharma avatar Volen avatar Maximilian Torggler avatar Yunsup Sim avatar  avatar Sean Sanker avatar Nyi Nyi Lwin avatar Josh Habdas avatar Danilo Gvozdenovic avatar Sam Carlile avatar Michael Scholle avatar Juri Sefa avatar Nikolas Barwicki avatar Thanabodee Saepui avatar Mateusz Witkowski avatar  avatar SeyyedKhandon avatar  avatar José Massigoge avatar Punith M avatar Nate Rahimizad avatar Maxime avatar patrick avatar nomura avatar Wickramaranga Abeygunawardhana avatar Ou avatar Amin Roosta avatar Travis Cooper avatar Anton Karpenko avatar Geek avatar Joachim avatar Huynh Duc Duy avatar 朱展东 avatar Yuta Takahashi avatar GG Nam avatar Dark avatar James Doyle avatar Andreas Steinkellner avatar Leo Li avatar  avatar Nick Na avatar Will G avatar Ehsan Heydari avatar Nail avatar Qingmu avatar Avery Morin avatar Sergey avatar Matheus Albuquerque avatar Aziz Chynaliev avatar  avatar keegan poppen avatar Alex Lévy avatar

Watchers

情封 avatar Sebastián Poliak avatar  avatar Jovi De Croock avatar  avatar Jayman Matthews avatar

vinxi's Issues

Exporting type definitions from a "use server" file doesn't work.

Exporting type definitions from a (top level) "use server" file like this

'use server';

export type Input = number;
export async function world2(x: Input) {
  console.log('hello world 2', x);
}

will produce the following error in development

[h3] [unhandled] H3Error: undefined does not match field "params": [Pattern] of type FunctionExpression
    at addParam (/home/projects/github-7jpzac/node_modules/ast-types/lib/types.js:455:27)
    ... 7 lines matching cause stack trace ...
    at async instantiateModule (/home/projects/github-7jpzac/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:56003:10) {
  cause: Error: undefined does not match field "params": [Pattern] of type FunctionExpression
      at addParam (/home/projects/github-7jpzac/node_modules/ast-types/lib/types.js:455:27)
      at eval (/home/projects/github-7jpzac/node_modules/ast-types/lib/types.js:505:25)
      at builder.from (/home/projects/github-7jpzac/node_modules/ast-types/lib/types.js:503:46)
      at wrapExports (/home/projects/github-7jpzac/node_modules/@vinxi/plugin-directives/plugins/wrap-exports.js:392:53)
      at Object.transform (/home/projects/github-7jpzac/node_modules/@vinxi/plugin-directives/plugins/wrap-exports.js:57:24)
      at TransformContext.transform (/home/projects/github-7jpzac/node_modules/@vinxi/plugin-directives/plugin.js:62:29)
      at Object.transform (/home/projects/github-7jpzac/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:44404:62)
      at async loadAndTransform (/home/projects/github-7jpzac/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:55078:29)
      at async instantiateModule (/home/projects/github-7jpzac/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:56003:10) {
    plugin: 'vite-server-references',
    id: '/home/projects/github-7jpzac/app/inline.tsx',
    pluginCode: "'use server';\n" +
      '\n' +
      'export type Input = number;\n' +
      'export async function world2(x: Input) {\n' +
      "  console.log('hello world 2', x);\n" +
      '}\n'
  },
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: undefined,
  data: undefined
}

When I remove the export for the Input type, it works as expected.

Tests

  • #84 passthrough for public assets (dev & prod)
  • #78 check all variations of preset being passed and the precedence rules related to that (just need to check build setup probably)
  • #79 test css/asset loading extensively across setups (this is kindof testing the Manifest)
  • #55 baseURL server
  • #47 devProxy

custom preset not working

Custom preset example linked in the Nitro docs that extends node-server does not work. Am I missing something?

Vinxi using preset example (Doesn't work)
Open in StackBlitz

Nitro using preset example (Works)
Open in StackBlitz
Note: Pinned version of nitropack and h3 to be the same as vinxi

Error:

useNitroApp is not defined

importing useNitroApp or nitroApp in the entry file doesn't help. (Not that I was expecting it to work...)

Package import specifier "#internal/nitro/virtual/plugins" is not defined in package C:\Users\Davide\Desktop\vinxi\examples\preset\.output\server\node_modules\nitropack\package.json imported from C:\Users\Davide\Desktop\vinxi\examples\preset\.output\server\node_modules\nitropack\dist\runtime\app.mjs

  at new NodeError (node:internal/errors:405:5)
  at importNotDefined (node:internal/modules/esm/resolve:250:10)
  at packageImportsResolve (node:internal/modules/esm/resolve:671:9)
  at moduleResolve (node:internal/modules/esm/resolve:825:16)
  at defaultResolve (node:internal/modules/esm/resolve:1036:11)
  at DefaultModuleLoader.resolve (node:internal/modules/esm/loader:251:12)
  at DefaultModuleLoader.getModuleJob (node:internal/modules/esm/loader:140:32)
  at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:33)
  at link (node:internal/modules/esm/module_job:75:36)



[20:35:38]  ERROR  Package import specifier "#internal/nitro/virtual/plugins" is not defined in package C:\Users\Davide\Desktop\vinxi\examples\preset\.output\server\node_modules\nitropack\package.json imported from C:\Users\Davide\Desktop\vinxi\examples\preset\.output\server\node_modules\nitropack\dist\runtime\app.mjs

Multiple SPA routers

Currently it does not seem prossible to have more than one SPA router configured. Is this intended and if so what is the reason?

Update: Better wording
Update: I think my changes work properly now (requires some tests)

Why require Nitro?

Just got done catching up on Ryan's last stream and love what you're trying to do here with Vinxi!

The JavaScript Server SDK to build full stack apps and frameworks with your own opinions.

💯, but curious if there's any reason Vinxi can't leave the server router/runtime decision to the end user as well? E.g. if the end user wants to use Hono, or Bun/Elysia, etc, rather than nitro/h3 eventHandler style approach to handling incoming server requests and streaming back the reac/solid/etc app.


Side note, was playing around with the examples and noticed the typings/intellisense (at least in vscode) isn't working in many cases. Adjusting the root tsconfig.json#moduleResolution to bundler enables support for package.json export fields and fixes the issues :).

Screenshot 2023-09-26 at 9 58 53 AM

License is not specified

Most of the Vinxi files do not have any license associated with them either inline or on the package level. There are some exceptions, but those are in minority.

[BUG] [BUN] Production builds randomly failing [ENOENT: No such file or directory] using Bun

Sometimes (seemingly randomly) when running builds using the bun adapter, the following mishap happens:

│ ⚙  Preparing app for bun...    │
└────────────────────────────────┘

ERROR  { [ENOENT: No such file or directory]
  code: 'ENOENT',
  path:
   '/.vinxi/build/client/_build/assets/app-d176a71a.js',
  syscall: 'copyfile',
  errno: -2 } 

ERROR  No such file or directory

error: "vinxi" exited with code 1
error: script "build" exited with code 1

Current workaround:

Run the build multiple times and hope that it succeeds sometime.

frameworks/solid-start, @vinxi/solid-start and examples/solid/ssr/solid-start - is it still relevant?

With the 0.4 release of SolidStart, is looks like all these might have become a bit obsolete:

https://github.com/nksaraf/vinxi/tree/main/examples/solid/ssr/solid-start
https://github.com/nksaraf/vinxi/tree/main/frameworks/solid-start
https://www.npmjs.com/package/@vinxi/solid-start

I tried to run the solid-start example, but didn't manage to. The stackblitz button in the readme to that example doesn't work, because of the use of a pnpm "workspace". The vinxi/solid-start npm package claims:

This is the SolidStart framework and CLI.

Pointing to the solidjs/start package would probably be a good idea to avoid confusion

show vite version with "vinxi dev"

Using "vinxi build" shows the vite version like this:

Screenshot 2024-01-05 at 02 24 33

It's quite convenient to check which version is active. "vinxi dev" on the other hand doesn't:

Screenshot 2024-01-05 at 02 25 29

[Issue] Dev mode is working and Build + Start mode not working

Hi,
I'm using vinxi with solid start template and currently when I develop in dev mode, i have no issue and all my plugins are loaded successfully.

But in build mode, my plugins are not loaded :

solid-devtools/vite
vite-multiple-assets
@vitejs/plugin-legacy

And my compiled version return an error :

e is not a function

How is it possible to debug the output ?

Regards

[Issue][unplugin-imagemin] Plugin is not working

ref : #44
repro : https://github.com/qlaffont/test-cmp


> test-cmp@ build /home/quentin/Documents/dev/test/test-cmp
> vinxi build

vinxi 0.0.60
start {
  appRoot: './src',
  ssr: false,
  islands: false,
  server: { base: undefined },
  solid: {}
}
vinxi Found vite.config.js with app config


┌────────────────────────────┐
│ ⚙  Building your app...    │
└────────────────────────────┘
removing /home/quentin/Documents/dev/test/test-cmp/.vinxi/build/ssr
removing /home/quentin/Documents/dev/test/test-cmp/.vinxi/build/client
removing /home/quentin/Documents/dev/test/test-cmp/.vinxi/build/server-fns


┌───────────────────────────────┐
│ 📦 Compiling ssr router...    │
└───────────────────────────────┘
vinxi building router ssr in handler mode
vite v4.5.0 building SSR bundle for production...
"createHandler" is imported from external module "h3" but never used in "node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/vinxi/runtime/server.js".
✓ 40 modules transformed.
.vinxi/build/ssr/manifest.json                   1.40 kB
.vinxi/build/ssr/assets/index-fb87c914.css      46.63 kB
.vinxi/build/ssr/_...404_.js                     0.74 kB
.vinxi/build/ssr/about.js                        0.96 kB
.vinxi/build/ssr/assets/components-86ea9901.js   1.20 kB
.vinxi/build/ssr/index.js                        3.61 kB
.vinxi/build/ssr/ssr.js                          6.50 kB


[unplugin-imagemin] 📦 📦 Process start with Mode sharp
✓ built in 743ms
✔ build done                                                                                                                                                  7:01:06 AM


┌──────────────────────────────────┐
│ 📦 Compiling client router...    │
└──────────────────────────────────┘
vinxi building router client in build mode
[
  '#vinxi/handler/client',
  '/home/quentin/Documents/dev/test/test-cmp/src/routes/[...404].tsx?pick=default&pick=$css',
  '/home/quentin/Documents/dev/test/test-cmp/src/routes/about.tsx?pick=default&pick=$css',
  '/home/quentin/Documents/dev/test/test-cmp/src/routes/index.tsx?pick=default&pick=$css'
]
plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers to support instead.
vite v4.5.0 building for production...
virtual:#vinxi/handler/client (1:106) "default" is not exported by "src/entry-client.tsx", imported by "virtual:#vinxi/handler/client".
✓ 115 modules transformed.
node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[Error: ENOENT: no such file or directory, open '/home/quentin/Documents/dev/test/test-cmp/.vinxi/build/client/_build/assets/_...404_-legacy-ca63b2ec.js'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/home/quentin/Documents/dev/test/test-cmp/.vinxi/build/client/_build/assets/_...404_-legacy-ca63b2ec.js'
}

Node.js v18.17.1
 ELIFECYCLE  Command failed with exit code 1.```
 

add /** __PURE__ */ annotation to `createReference` calls for dead code elimination: Error: Cannot access '${IDENTIFIER}' before initialization

After upgrading my Solid Start project's Vinxi from 0.0.59 -> 0.1.1, when I run pnpm build I get

Cannot access 'gr$1' before initialization

That identifier is coming from a a cache call, like:

export const getOtherPlayers = cache(gOP, "other-players");

gOP is the identifier failing. It is a server function. Perhaps the server function is missing from the client build? Or the server build?

Everything works with pnpm dev. When I build with ssr: false, this error happens during the prerender. stage of pnpm build. When I enable ssr: true, the error happens when I run node .output/server/index.mjs

vite 5 support

to allow downstream projects to use vite 5, as discussed here:
solidjs/solid-start#1139 (comment)

i tried bumping it in the packages/vinxi, and then a handful of the tests broke, so there might be some adjustment needed.

  5 failed
    [chromium] › basic-prod.test.ts:35:2 › basic build › ssr 
    [chromium] › fs-router.test.ts:36:2 › fs-router › ssr 
    [chromium] › hmr.test.ts:87:2 › hmr › client hmr 
    [chromium] › rsc.test.ts:36:2 › rsc › spa 
    [chromium] › srv-fn.test.ts:68:2 › srv-fn-prod › spa 

  3 skipped
  6 passed (10.8s)

ERROR "createHandler" is not exported by "node_modules/h3/dist/index.mjs", imported by ".vinxi/build/ssr/ssr.js".

I get the following error with vinxi when building a solid-start app for vercel:

[vinxi 9:20:39 PM]  ERROR  RollupError: "createHandler" is not exported by "node_modules/h3/dist/index.mjs", imported by ".vinxi/build/ssr/ssr.js".


1: import{createComponent as l,isServer as k,getRequestEvent as R,delegateEvents as H,ssrElement as A,escape as v,mergeProps as U,ssr as b,useAssets as j,NoHydration as O,HydrationScript as _,ssrHydrationKey as $,ssrAttribute as B,Hydration as D}from"solid-js/web";import{createHand...
                                                                                                                                                                                                                                                                                ^


 ERROR  "createHandler" is not exported by "node_modules/h3/dist/index.mjs", imported by ".vinxi/build/ssr/ssr.js".  9:20:39 PM

  at error (node_modules/rollup/dist/es/shared/parseAst.js:337:30)
  at Module.error (node_modules/rollup/dist/es/shared/node-entry.js:12759:16)
  at Module.traceVariable (node_modules/rollup/dist/es/shared/node-entry.js:13196:29)
  at ModuleScope.findVariable (node_modules/rollup/dist/es/shared/node-entry.js:11613:39)
  at Identifier.bind (node_modules/rollup/dist/es/shared/node-entry.js:7195:40)
  at CallExpression.bind (node_modules/rollup/dist/es/shared/node-entry.js:4641:23)
  at CallExpression.bind (node_modules/rollup/dist/es/shared/node-entry.js:8832:15)
  at VariableDeclarator.bind (node_modules/rollup/dist/es/shared/node-entry.js:4641:23)
  at VariableDeclaration.bind (node_modules/rollup/dist/es/shared/node-entry.js:4637:28)
  at Program.bind (node_modules/rollup/dist/es/shared/node-entry.js:4637:28)
  at Module.bindReferences (node_modules/rollup/dist/es/shared/node-entry.js:12755:18)
  at Graph.sortModules (node_modules/rollup/dist/es/shared/node-entry.js:18957:20)
  at Graph.build (node_modules/rollup/dist/es/shared/node-entry.js:18862:14)
  at async node_modules/rollup/dist/es/shared/node-entry.js:19502:13
  at async catchUnfinishedHookActions (node_modules/rollup/dist/es/shared/node-entry.js:19014:16)
  at async rollupInternal (node_modules/rollup/dist/es/shared/node-entry.js:19497:5)
  at async _build (node_modules/nitropack/dist/shared/nitro.4ea992bc.mjs:2589:20)
  at async createBuild (node_modules/vinxi/lib/build.js:312:2)
  at async Object.run (node_modules/vinxi/bin/cli.mjs:206:5)
  at async runCommand (node_modules/citty/dist/index.mjs:316:16)
  at async runCommand (node_modules/citty/dist/index.mjs:307:11)
  at async runMain (node_modules/citty/dist/index.mjs:441:7) 



 ERROR  "createHandler" is not exported by "node_modules/h3/dist/index.mjs", imported by ".vinxi/build/ssr/ssr.js".  9:20:39 PM

SolidJS basic SSR example is broken

The basic SSR example for SolidJS builds with various warnings then when a request is made to server it throws an exception about React not being found, causing a 500 error response.

Relevant warning (the rest are the same):

[vite] warning: The JSX import source cannot be set without also enabling React's "automatic" JSX transform
1  |  /** @jsxImportSource solid-js */
   |                       ^
2  |  import { Link, Style, useHead } from "@solidjs/meta";
3  |  import { splitProps } from "solid-js";

  Plugin: vite:esbuild
  File: node_modules/.pnpm/@[email protected]/node_modules/@vinxi/solid/render-asset.jsx

The 500 error after making a request:

[h3] [unhandled] ReferenceError: React is not defined
    at eval (app/server.tsx:22:83)
    ... 5 lines matching cause stack trace ...
    at async Server.toNodeHandle (file://node_modules/.pnpm/[email protected]/node_modules/h3/dist/index.mjs:1885:7) {
  cause: ReferenceError: React is not defined
      at eval (app/server.tsx:22:83)
      at file://node_modules/.pnpm/[email protected]/node_modules/solid-js/web/dist/server.js:262:34
      at createRoot (file://node_modules/.pnpm/[email protected]/node_modules/solid-js/dist/server.js:58:14)
      at Proxy.renderToStream (file://node_modules/.pnpm/[email protected]/node_modules/solid-js/web/dist/server.js:260:14)
      at eval (app/server.tsx:22:40)
      at async Object.handler (file://node_modules/.pnpm/[email protected]/node_modules/h3/dist/index.mjs:1675:19)
      at async Server.toNodeHandle (file://node_modules/.pnpm/[email protected]/node_modules/h3/dist/index.mjs:1885:7),
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: undefined,
  data: undefined
}

router handlers with same base are reversed in production

In production the config below outputs handlers in the following order and server doesn't receive any requests. Dev works fine.

Repo

const handlers = [
  { route: '', handler: _f4b49z, lazy: false, middleware: true, method: undefined }, // assets
  { route: '/_server', handler: handler$1, lazy: false, middleware: true, method: undefined }, // server fn
  { route: '/', handler: _ZIhn88, lazy: false, middleware: true, method: undefined }, // index.html content
  { route: '/', handler: handler, lazy: false, middleware: true, method: undefined }  // server
];
const app = createApp({
  routers: [
    {
      name: "server",
      mode: "handler",
      handler: "./app/server",
      target: "server"
    },
    {
      name: "public",
      mode: "static",
      dir: "./public",
    },
    {
      name: "client",
      mode: "spa",
      handler: "./index.html",
      target: "browser",
      plugins: () => [
        config("custom", {
          build: {
            minify: false
          }
        }),
        serverFunctions.client(),
        solid()
      ]
    },
    serverFunctions.router(),
  ],
});

"use server" chunks are duplicated in build

Is:
If you create a file with "use server" and use it in a component/route file, the file code will be duplicated to two chunks. It will be in server/chunks/build/someRoute.mjs and also server/chunks/nitro/node-server.mjs.

Should:
Ideally it should only be in the node-server chunk and from there exported. The someRoute chunk should only import the functions from node-server.

Feature request: CLI shortcuts in dev

Hello,
I know it's not high priority, I just wanted to suggest bringing back the CLI keyboard shortcuts solid start had.

I.e. press 'r' to restart server.

Thank you for the good work 🙇

CSS Not in Initial Document for Prod Builds (Waterfalls)

In dev mode, the initial document will render with CSS embedded
Screenshot from 2024-01-02 17-31-59

When running a production build, CSS Modules are split out and fetched after initial document load (causing waterfall)
Screenshot from 2024-01-02 17-33-27

I noticed this initially using CSS Modules (turning the "HELLO WORLD!" red with a class, and now see this can also be observed with the basic template of solid-start (no CSS Modules)

support "renderAssetUrl" and customized "assetsBase": "base" vite setting breaks solid-start build

I need to be able to pass "base:" setting to vite to be able to prepend it to asset paths.
I don't need it to affect solid app, router or anything else. Just assets, like raw vite does it.

I used it with solid-start 0.3 using a custom patch to detach this setting from router.
I started to port app to 0.4 and current versions of solid-start disable babel transformations as soon as I specify base: "http://somehost.com" in vite config which is double weird.

[Bug?] Config changes not applied on server restart

After changes the import in loadFile will return the config it loaded on the first start. I am using a timestamp query param as workaround for now.

Any better way to solve this? I have seen that there is the possibility to import modules with data urls but couldn't get that to work.

css bundling differences and issues between file-based routes and config-based routes

I have looked into two approaches for a new, basic, solid-start app

minimum repro: https://github.com/Numnumberry/solidstart-css-routing

  • in the repro, toggle between file and config based routing inside app.tsx (building and starting each)
export const configRoutes: RouteDefinition[] = [
  {
    path: '/',
    component: lazy(() => import('./routes/index'))
  },
  {
    path: '/about',
    component: lazy(() => import('./routes/about'))
  },
  {
    path: '/*all',
    component: lazy(() => import('./routes/[...404]'))
  }
]

export default function App() {
  const fileRoutes = FileRoutes()

  return (
    <Router
      root={(props) => (
        <MetaProvider>
          <Title>SolidStart - Basic</Title>
          <a href="/">Index</a>
          <a href="/about">About</a>
          <Suspense>{props.children}</Suspense>
        </MetaProvider>
      )}
    >
      {fileRoutes}
      {/* {configRoutes} */}
    </Router>
  );
}

For each case, there are issues with how the css is bundled and sent to the browser

file-based:

  • Initially loading the page results in desired behavior: the browser waits for the CSS to load before painting the screen (this is good because the user does not see a flash of style changes). This is because the CSS is loaded by a <link /> tag in the initial document.
  • However, when preloading (by mouse hovering) another route using Solid's <A /> tag, the CSS does not get loaded. The CSS only gets loaded when the <A /> tag is actually clicked (this is not desired, the user sees a flash of style changes).
file.mp4

config-based

  • Initially loading the page results in undesired behavior: the browser does not wait for the CSS to load before painting the screen (this results in a flash of style changes). This is because the CSS is is not loaded by a <link /> tag in the initial document. It is instead loaded by JavaScript: HttpStatusCode-[hash].js
  • However, when preloading (by mouse hovering) another route using Solid's <A /> tag, the CSS does get loaded in time. So when the user actually does click the <A /> tag, the CSS is already there and there is no flash of style changes.
config.mp4

So the two main questions I have are

  • should there be a difference between file-based and config-based routing? Or maybe I configured something wrong?
  • is it possible to have a setup where the CSS is fetched and loaded before loading the initial page and before loading another route through <A /> tag? To completely eliminate flashes of style changes altogether.

related

RFC: `stacks`

Now that the base implementation is getting stable and proving itself to be quite flexible, I want to figure out the UX and composition story. Right now you need an app.config.js to do anything server related. This makes it difficult to enable an experience I really wish to enable. A powerful CLI that can compose functionality from NPM on the fly to build up an app config.

I want to introduce the concept of stacks. They are the equivalent of Vite plugins but for the app itself, so more wide-reaching. In vinxi, vite plugins are applied to routers, since each one has its own dev/build pipelines. Stacks are the equivalent extension point for the app itself.

With the ability to hook into the system using the hookable hooks, we can create a really composable setup where functionality can be bundled up and comsumed easily across the ecosystem. Whatever you can do with stacks, you will be able to do with the hooks themselves too. Maybe we can keep the naming the same too.

So, what is a stack?

  1. It can add routers to the app
  2. It can modify existing routers, changing settings, or adding vite plugins
  3. More to come.. but basically hook into any step in the lifecycle and mutate stuff.

compat with yarn berry

using solid start with yarn berry result in module resolution issues with jiti, through vinxi:

repro:

  • yarn create solid
  • select bare (important step that is the bare template)
  • yarn set version berry (to use yarn v4)
  • yarn
  • yarn dev

manifest plugin doesn't work with unplugin-icons

Hi! I was just trying out the new @solidjs/start (beta) and vinxi combination, and it seems to work quite fine for a small app!

The only thing is that adding the unplugin-icons vite plugin doesn't seem to go well with vinxi's manifest plugin.

The unplugin-icons plugin actually works, the icon is shown, but because vinxi's manifest plugin tries to load the icon from a file that isn't there, so it will give an error:

Error: Failed to load url /workspace/~icons/lucide/alert-circle.tsx (resolved id: /workspace/~icons/lucide/alert-circle.tsx). Does the file exist?
    at loadAndTransform (file:///workspace/node_modules/@solidjs/start/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:55015:21)
    at async getViteModuleNode (file:///workspace/node_modules/vinxi/lib/manifest/collect-styles.js:61:5)
    at async add_by_url (file:///workspace/node_modules/vinxi/lib/manifest/collect-styles.js:93:16)
    at async Promise.all (index 4)
    at async findDeps (file:///workspace/node_modules/vinxi/lib/manifest/collect-styles.js:119:2)
    at async findDependencies (file:///workspace/node_modules/vinxi/lib/manifest/collect-styles.js:140:5)
    at async findStylesInModuleGraph (file:///workspace/node_modules/vinxi/lib/manifest/collect-styles.js:158:23)
    at async Object.assets (file:///workspace/node_modules/vinxi/lib/manifest/dev-server-manifest.js:162:16)
    at async Context.load (/workspace/node_modules/@solidjs/start/node_modules/vinxi/lib/plugins/manifest.js:56:13)
    at async Object.load (file:///workspace/node_modules/@solidjs/start/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:44323:32)
    at async loadAndTransform (file:///workspace/node_modules/@solidjs/start/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:54954:24)
    at async viteTransformMiddleware (file:///workspace/node_modules/@solidjs/start/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:64430:32) {
  code: 'ERR_LOAD_URL'
}

It seems that the collect-styles.js doesn't know that this already has been transformed:

if (!node.transformResult && !ssr) {

plugin code for unplugin-icons

I made a CodeSandbox for easy replication of the issue:
https://codesandbox.io/p/devbox/vinxi-unplugin-icons-bug-5zwww3?file=%2Fsrc%2Froutes%2Findex.tsx%3A6%2C11

Edit:
Debugging in the collect-styles.js showed I think we first need to check if the node can be retrieved by using file, if not we can use normalizedPath.

Can we do maybe something like this inside collect-styles.js?

let node = await vite.moduleGraph.getModuleById(file);
if (!node) node = await vite.moduleGraph.getModuleById(normalizedPath); // normalizedPath = resolve(id)

Also I see absolutePath:

const absolutePath = resolve(file);
is not used.

WebSockets support

I'm currently using websockets in solid-start (although it needed some modifications to the source). Will there be a way to upgrade http connections to websockets in Vinxi?
It does not seem to be support for this in Nitro unjs/nitro#678

Sandbox example errors: React - TanStack Router (App) - SSR

Whereas the React SSR Basic sandbox example works fine, this is what I get for the SSR version:

~/projects/kkvipxjky.github
❯ npm install && npm run dev
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: @gisatcz/[email protected]
npm WARN Found: [email protected]
npm WARN node_modules/react
npm WARN react@"0.0.0-experimental-035a41c4e-20230704" from the root project
npm WARN 1 more (react-dom)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer react@"^16.13.1 || ^17.0.2 || ^18.1.0" from @gisatcz/[email protected]
npm WARN node_modules/@gisatcz/cross-package-react-context
npm WARN @gisatcz/cross-package-react-context@"^0.2.0" from @tanstack/[email protected]
npm WARN node_modules/@tanstack/react-start
npm WARN 1 more (@tanstack/router)
npm WARN
npm WARN Conflicting peer dependency: [email protected]
npm WARN node_modules/react
npm WARN peer react@"^16.13.1 || ^17.0.2 || ^18.1.0" from @gisatcz/[email protected]
npm WARN node_modules/@gisatcz/cross-package-react-context
npm WARN @gisatcz/cross-package-react-context@"^0.2.0" from @tanstack/[email protected]
npm WARN node_modules/@tanstack/react-start
npm WARN 1 more (@tanstack/router)
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: @tanstack/[email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR! react@"0.0.0-experimental-035a41c4e-20230704" from the root project
npm ERR! peer react@"0.0.0-experimental-035a41c4e-20230704" from [email protected]
npm ERR! node_modules/react-dom
npm ERR! react-dom@"0.0.0-experimental-035a41c4e-20230704" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@">=16" from @tanstack/[email protected]
npm ERR! node_modules/@tanstack/react-loaders
npm ERR! @tanstack/react-loaders@"0.0.1-beta.109" from the root project
npm ERR! @tanstack/react-loaders@"0.0.1-beta.109" from @tanstack/[email protected]
npm ERR! node_modules/@tanstack/react-start
npm ERR! @tanstack/react-start@"0.0.1-beta.111" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: [email protected]
npm ERR! node_modules/react
npm ERR! peer react@">=16" from @tanstack/[email protected]
npm ERR! node_modules/@tanstack/react-loaders
npm ERR! @tanstack/react-loaders@"0.0.1-beta.109" from the root project
npm ERR! @tanstack/react-loaders@"0.0.1-beta.109" from @tanstack/[email protected]
npm ERR! node_modules/@tanstack/react-start
npm ERR! @tanstack/react-start@"0.0.1-beta.111" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR!
npm ERR! For a full report see:
npm ERR! /home/.npm/_logs/2024-01-10T14_33_28_197Z-eresolve-report.txt

npm ERR! A complete log of this run can be found in:
npm ERR! /home/.npm/_logs/2024-01-10T14_33_28_197Z-debug-0.log

~/projects/kkvipxjky.github 2s
❯ npm install --legacy-peer-deps && npm run dev

added 650 packages in 6s

123 packages are looking for funding
run npm fund for details

dev
vinxi dev

vinxi 0.1.1
vinxi starting dev server

and then nothing displays in the browser view. This is on macOS with Firefox 115.6.0esr (64-bit).

startup / dispose hooks?

Hello,
I like to initialize a db connection on startup and also close this connection when the dev server reloads. Is there a way to hook into this? Thought of import.meta.hot, but that does not work. Also I couldn't find a Signal to listen to like process.on('SIGTERM'...

thanks in advance

Acorn crashed on TS types

Hi,

I just tried Start beta with island support. I got an error during the build process:

Acorn crashed with this error:

vite v4.5.0 building SSR bundle for production...
✓ 32 modules transformed.
✓ built in 482ms
[vite-server-references] Unexpected token (104:83)
file: /Users/jchatard/Documents/xxx/src/lib/fetcher.ts:104:83

 ERROR  Unexpected token (104:83)                                                                                                                     09:15:35

  at pp$4.raise (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:3571:15)
  at p.raiseCommonCheck (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:101468)
  at p.raise (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:101622)
  at pp$9.unexpected (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:772:10)
  at pp$9.expect (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:766:28)
  at p.parseExprList (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:92278)
  at p.parseSubscript (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:94920)
  at pp$5.parseSubscripts (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2734:26)
  at pp$5.parseExprSubscripts (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2718:23)
  at pp$5.parseMaybeUnary (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2681:19)
  at pp$5.parseExprOps (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2608:21)
  at p.parseMaybeConditional (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:75991)
  at p.parseMaybeAssignOrigin (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:83453)
  at p.parseMaybeAssign (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:84543)
  at p.parseExprList (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:92499)
  at p.parseSubscript (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:94920)
  at pp$5.parseSubscripts (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2734:26)
  at pp$5.parseExprSubscripts (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2718:23)
  at pp$5.parseMaybeUnary (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2681:19)
  at pp$5.parseExprOps (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:2608:21)
  at p.parseMaybeConditional (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:75991)
  at p.parseMaybeAssignOrigin (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:83453)
  at p.parseMaybeAssign (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:84543)
  at pp$8.parseVar (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:1321:26)
  at p.parseVarStatement (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:73986)
  at pp$8.parseStatement (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:927:19)
  at p.parseStatement (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:74981)
  at p.parseExportDeclaration (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:77126)
  at p.parseExport (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:70559)
  at pp$8.parseStatement (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:948:76)
  at p.parseStatement (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:74981)
  at pp$8.parseTopLevel (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:829:23)
  at e.parse (node_modules/.pnpm/[email protected]/node_modules/acorn/dist/acorn.js:601:17)
  at e.parse (node_modules/.pnpm/[email protected][email protected]/node_modules/acorn-typescript/lib/index.js:1:99339)
  at parseLoose (node_modules/.pnpm/@[email protected][email protected]/node_modules/@vinxi/plugin-directives/parse.js:14:17)
  at Object.transform (node_modules/.pnpm/@[email protected][email protected]/node_modules/@vinxi/plugin-directives/transform.js:595:42)
  at Object.transform (node_modules/.pnpm/@[email protected][email protected]/node_modules/@vinxi/plugin-directives/plugin.js:49:34)



 ERROR  Unexpected token (104:83)                                                                                                                     09:15:35

 ELIFECYCLE  Command failed with exit code 1.

My code in src/lib/fetcher.ts was:

//... Note the return type 
export const getSettings = cache(async (): Promise<Settings> => {
  return getDataAtPath("settings");
}, "settings");

export const getMenuMain = cache(async (): Promise<MenuItem[]> => {
  return getDataAtPath("menu/main");
}, "menu/main");

export const getMenuFooter = cache(async (): Promise<MenuItem[]> => {
  return getDataAtPath("menu/footer");
}, "menu/footer");

When I remove return types like this:

export const getSettings = cache(async () => {
  return getDataAtPath("settings");
}, "settings");

export const getMenuMain = cache(async () => {
  return getDataAtPath("menu/main");
}, "menu/main");

export const getMenuFooter = cache(async () => {
  return getDataAtPath("menu/footer");
}, "menu/footer");

It works!

PS: thanks Nikhil for your amazing work on Vinxi and Solid :-)

dev-server on https

I'm porting solid-start application from 0.3 to 0.4. Previously, I could specify this in vite.config and dev-server started to work over https, which is really useful for my scenarios.

{
  server: {
    https: {
      cert: 'file.pem',
      key: 'file-key.pem'
    }
  }
}

I don't need this for production, which uses reverse-proxies in my case. But for dev-server this is very important.

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.