Releases: solidjs/solid-start
@solidjs/[email protected]
Patch Changes
- #1888: Add back support for generators in server functions
@solidjs/[email protected]
@solidjs/[email protected]
v1.1.1 - Constantly Exported
Patch Changes
- efd762e: Bump tanstack server functions plugin
This fixesexport const
in top-level"use server"
files.
The bundler warning for top-level"use server"
is still there, but still code-removal works.
v1.1.0 - Gear 5
At last our first post 1.0 minor release!!
It took us some time but it is an important one. It includes the update to Vite 6 along with tons of bug fixes around Server functions. But the most important thing is over this time we've doubled down to make sure that we have a proper team supporting this project. This includes setting up the people and infrastructure for SolidStart to work independently from the core project. So we are cranking stuff up to Gear 5 to improve our release cadence and overall responsiveness.
We've been working very closely with @tannerlinsley and the Tanstack Start team in ushering the future of Metaframeworks and I'd almost call it one shared team at this point. That's the direction things are heading. These are more than sister projects but part of a unified picture for the future. More details of that will be revealed as the is collaboration continues.
Huge thanks to the SolidStart team for making this all possible: @birkskyum, @atilafassina, @katywings, @brenelz. PRs from @christhornham, @AirBorne04, @edivados, @loetjvr. As well as continued support from core team members @lxsmnsyc and @nksaraf.
Enjoy!
@ryansolid
Minor Changes
- 4ec5d9b: - Added "OPTIONS" to the HTTP_METHODS array in packages/start/config/fs-router.js.
I made this change so developers can handle preflight OPTIONS requests when using SolidStart as a public facing REST API.
Existing users will not have to change their code. This change only adds an additional feature. - b434665: Vite 6 support
- 600c115: move the RequestEventLocals definition into the App namespace for easier end user retyping
Patch Changes
-
00c6d33: update vinxi to 0.5.3
-
df32b0d: Await internal
sendWebResponse
calls for middlewares that return responses. -
cda037b: Return
404
when server-function is not found -
a97093f: Move
getServerFunctionMeta
from@solidjs/start/server
to@solidjs/start
to fix circular import issues.The old export at
@solidjs/start/server
still exists, but is deprecated and will be removed in a future release. -
5a166a4: Adopt tanstack server functions plugin
The Shape of Frameworks to Come
What can I say we made it! Over 3 years of effort here and we have a major release. When we started this journey we only vaguely had an outcome in mind. In the process we managed to yet again be a driving source for innovation in the ecosystem. I'm very proud of every single person involved in this release, from development to docs. As the title suggests. We(the community) are just getting started.
I would love to see a future where people build more opinionated frameworks on top of what we've done here. People carry the DX torch to the finish line. This will not be the last JS Framework, or even the last SolidJS framework. Change is inevitable. Be that change.
The full release announcement is here: https://www.solidjs.com/blog/solid-start-the-shape-frameworks-to-come
v1.0 RC - Clown Town
When we released SolidStart Beta it was a celebration of all the libraries and frameworks that inspired us. There have been so many other frameworks exploring this space alongside us. We have learned so much from them. A year and a half later, I'd like to think that in turn we've influenced them as well.
This release is dedicated to all those who have contributed to getting us here. Everyone who tested builds, reported issues, made PRs (even the ones we didn't merge). We wouldn't have made it to this point without all of them. This release is for them so that the next can be for all of you. We've reached a release candidate for 1.0!
We've learned a lot along the way. The name of this release is a throwback to an early moment in the project's history that had a profound and important impact on how we operate. While I don't wish to rehash, I will say it changed the way we looked at our work in open source and challenged each of us to decide what it meant for us publically and personally.
So today with our goals in sight, we lay this one to rest, and thank everyone who has ever contributed to the project. Not everyone who started on this road with us is still with us. That is the life of volunteering and open source. But you have our (and my) thanks:
@nksaraf, @nsarafpure, @lxsmnsyc, @birkskyum, @ghalle, @edivados, @Jutanium, @davedbase, @femincan, @btakita, @OrJDev, @boehs, @lightyaer, @G3root, @caseybaggz, @Brendonovich, @fezproof, @atk, @arbassett, @fictitious, @benbender, @mhyfritz, @emdede, @frenzzy, @Zachiah, @utkukaratas, @marvin-j97, @pawelblaszczyk5, @katywings, @harshmangalam, @jzohdi, @IvanLisz, @rrosas1198, @doeixd, @orenelbaum, @AlexErrant, @ch99q, @devinrhode2, @knpwrs, @timotius02, @m4rvr, @paularmstrong, @ryanseipp, @rturnq, @skreutzberger, @leaysgur, @samualtnorman, @pan93412, @uncenter, @sapphi-red, @indeyets, @u1in, @AirBorne04, @ajcwebdev, @alexandre-mb-airweb, @rvlzzr, @arnvgh, @brenelz, @fabian-hiller, @feynmanliang, @iainsimmons, @jceb, @leoj3n, @jorroll, @jchatard, @obask, @LiQuidProQuo, @ryoid, @rpivo, @samcfinan, @SirSerje, @simbas, @yume-chan, @soorria, @xstevenyung, @Tanner-Scadden, @painotpi, @Tommypop2, @ticianomorvan, @Nimaear, @russelgal, @ricardo-devis-agullo, @quentindutot, @dertieran, @petebacondarwin, @phouverneyuff, @patdx, @oscartbeaumont, @itsyoboieltr, @nas5w, @TooTallNate, @NathanHuisman, @Maxobat, @33KK, @dayvster, @zimonitrome, @xbmlz, @wimbarelds, @webfolderio, @vaishnav-mk, @stereobooster, @spicyzboss, @shivanshubisht, @nullableVoidPtr, @nirtamir2, @muslax, @markdalgleish, @guyo13, @gunnnnii, @ddPn08, @DaveMadden, @eryue0220, @bherbruck, @aronmal, @yonran, @yoavbls, @stickyburn, @progamesigner, @Wilaz, @vladrose, @viniciuspjardim, @TimWillebrands, @cstrnt, @thdxr, @davycoe, @danieltroger, @thetarnav, @clabinger, @colinhacks, @colbyfayock, @chrisbirster, @chobe, @charkour, @CWSpear, @seeplusplus, @burhanuday, @benmccann, @gBasil, @baristikir, @amorriscode, @afjlambert, @yurisich, @ammarriq, @ahkhanjani, @MASTERAMARJEET, @AlexMercedCoder, @albertoforni, @acerempel, @afonsojramos, @AdvTechnoKing, @adipascu, @luca-rath, @lawrencecchen, @Lalit3716, @K-Sato1995, @juliusmarminge, @jpmaga, @jhdcruz, @jgibo, @JoosepAlviste, @jtag05, @jqhr, @JesusP2, @BigDog1400, @ikapo, @xania, @iainmerrick, @golamrabbiazad, @garrett-hopper, @pureliani, @gabrielmfern, @fwang, @FoxtrotPerry, @Feel-ix-343, @erikrahm, @emilbonnek, @ehsanonline, @dudusotero, @MrFoxPro, @superbull, @BierDav, @haseeb5555, @XiNiHa, @AlbertSabate, @lukaprsina, @dev-rb, @Chojecki, @Vexcited, @paoloricciuti, @nexxeln, @sakhnyuk, @cohenerickson, @kkharji, @alxarch, @LukeSheard, @modderme123, @vsbyvi, @amitdahan, @quantuminformation, @fabien0102, @Budmin, @opudalo, @Bersaelor, @shorkyw, @blackvibe, @petercorrea, @HatulaPro, @rtritto, @huijiewei, @murphye, @sashoism, and anyone else we may have missed.
We'd also like to thank those that have invested financially with us as you are a big part of making this release happen. Especially Netlify, Google Chrome, JetBrains, Builder.io, Northlabs, Stytch, Breek, Monogram, csel.co.nk, divRIOTS, Vercel, Bumi, Clearspend, OSLabs and 402.
There are still a few more things to get in line for the 1.0 release. We are still expecting some bugs, and the official SolidJS docs for SolidStart are still under construction. But we are well on our way. I look forward to pushing this across the finish line in the coming weeks.
Thank you for your support and encouragement.
@ryansolid and Solid Core Team
v0.7.0 - Calm Before the Storm
This is a smaller release that doesn't fundamentally change anything you are already doing in Solid Start but it needed to happen since there were some circular dependency issues and I used this as an opportunity to cleanup some of the config. So this release is very much a precursor to us getting to 1.0 RC candidates. If you have been watching the repo the issue count is down to the lowest it has ever been (even after I went issue bankrupt with Beta 1). We've been slowly getting key enhancements in and fixing bugs. There are a couple things outstanding like the ultimate decision on Base Path and some weird cache issues during HMR but the general behavior is coming together nicely.
Changes
FileRoutes have moved
Honestly I should have done this ages ago but we just keep getting weird circular deps issues due to them. Now they are their own export. This means changing your entry point import to:
import { FileRoutes } from "@solidjs/start/router";
But this should address a lot of the weirdness there.
Support for breaking out of nested routes
Sometimes you don't want to nest routes. Now you can represent paths with "." to avoid matching with parents. For example if you had users listing page under "/users" and you wanted the details to be under "/user/:id" but they don't share a layout or data fetching. Now you can name your files.
users.tsx
users.[id].tsx
And they won't try to nest. These can also each be their own nested routes as well by using "." notation on folders. Thanks to Remix V1 router for the inspiration, and Vinxi for making this implementable in about 30 seconds.
UPDATE: The above API was replaced with a simpler mechanism we already have. You can use (name)
to differentiate paths. The text between the paranthesis is not included on the path but it prevents nested matching.
users(list).tsx
users/
- [id].tsx
getServerFunctionMeta
This is a specific helper but it is useful sometimes to get the underlying information about your running server function. You can do that now by calling this method. So far it only returns an id
but it can help give you a stable reference across different environments this way. Thanks @katywings for making this happen.
import { getServerFunctionMeta } from "@solidjs/start/server";
// or some in-memory db
const appCache: any = globalThis;
const counter = async () => {
"use server";
const { id } = getServerFunctionMeta()!;
const key = `counter_${id}`;
appCache[key] = appCache[key] ?? 0;
appCache[key]++;
return appCache[key] as number;
};
Dropped Direct Interop with Solid's Request Event and H3
This is mostly unnecessary with our response wrapper and ALS. And was causing extra complication that was unnecessary. If you want to use Vinxi HTTP helpers or H3 utilities directly just use the .nativeEvent
property on our Request Event.
Conclusion
There are another half a dozen smaller changes so see the changelog for more details. But things are getting closer. Thank you everyone who is participating in the beta and reporting issues. We appreciate your patience and look forward to your continued participation.
v0.6.0 - Take Flight
Listening carefully to the feedback and reflecting on the second month of beta 2 we have prepared this release which improves on a lot of the usability around Start itself. This is less about features and more about stabilization but I'm excited that one of the coolest features we've showed off in a while was developed in the process: Single Flight Mutations.
Single Flight Mutations
This feature is really a combined Start + Solid Router feature but it showcases off the power of server function protocol. Inspired by React Server Component's ability to send back the next page in the same request with their server actions, we have added the ability to instead send back the data for the next page(or refresh of the same page's data). And not just send it back in a blocking way but to stream it back as it is available.
So you can picture the classic listing page + details page setup. You can in an action update a details page and have it redirect back to the listings page. We can now do that in one request. The item will be saved and return a redirect, at which point it starts sending back the request however the body will contain the data for the next page streamed as it completes. Suspense will allow the browser to start redirecting before all the data has returned and each cache
function resolve as its data comes in.
Try the Notes and TodoMVC examples to see this in action.
The best part is this requires no new API. No required code change on your part. Can still use all the features like optimistic updates etc... And it supports granular revalidation. While by default we will revalidate all the data on the next page, you can still use our revalidate options in our router helpers (reload
, redirect
, json
) select only certain cache keys and we will honor that. We diff the knowledge of which cache keys are already available on the page so that while we won't fetch any data that isn't in the keys from existing cache, we will still fetch new data for the new page sections (if it is a redirect).
This works with SSR on or off so it is available to any project that supports Server functions.
Vite 5
v0.6.0 adds support for Vite 5. I admit this took us a while but we were working on a whole new build system with Vinxi. @nksaraf has done amazing work here and continues to push the envelope. Also thanks to @birkskyum for getting this rolling and testing the integration until it was ready to go.
We look forward to an even quicker dev experience and all the other goodies that come with the update.
vite.config
-> app.config
A lot of people expressed confusion over the difference in options and settings and we decided you were right. In so we have stopped using vite.config.ts
and instead opt for an app.config.ts
. We have also updated the settings to be clearer. SolidStart's own settings are now top level and you will find the vite
settings under a vite
property. This allows more flexibility as Vite can be configured now per Vinxi router.
import { defineConfig } from "@solidjs/start/config";
export default defineConfig({
ssr: false,
server: {
preset: "netlify"
},
vite(options) {
if (options.router === "server") ....
return { plugins: [] }
}
});
We've added the ability to disable the dev overlay in dev
so you can see the errors the way your users would in prod. We've also moved the ssr
mode settings from the config to the runtime to handle more dynamic needs.
Handler Config as a Function
We've expanded the capability of handler config so that we can do my dynamic things at runtime. Things like switch between render modes. This way we can turn off streaming for bots etc.. Or applying a nonce
based on the middleware configuration.
import { createHandler, StartServer } from "@solidjs/start/server";
export default createHandler(() => (
<StartServer document={/*...*/} />
), (event) => {
return { nonce: event.locals.nonce, mode: event.locals.isBot ? "async" : "stream"}
};
A Long and Steady Road
We've been at this for a while but things are consolidating nicely. We are now feature complete for SolidStart 1.0 so it is time to fix bugs and get docs going. If we based on the feedback of these recent changes I hope to have an RC out in the coming weeks. Thank you all for your patience and your support.
Best,
@ryansolid
v0.5.0 - Async Local Storage ...Everywhere
This release is a bunch of organizational shifts from our learnings after running Solid Start Beta 2 for the first month (see: #1279). These are all minor changes but we hope they will smooth out the dev experience significantly. This release is largely possible due to the heroic efforts of @nksaraf and the multitudes of updates/fixes @lxsmnsyc has been making behind the scenes.
RequestEvent improvements
Main update is we've changed how we look at the main event object. Before we were mashing everything on top of H3 which wasn't always the best. We couldn't just adopt H3's Event because we have conventions in the Solid ecosystem and it was a bit awkward trying to figure out how to best interact with both systems in place.
Main change here is that instead of merging, the underlying H3Event is now available at event.nativeEvent
. But having to pump that through helpers all the time would be a bit clunky so we have a couple new mechanism to make it easier to use.
Stubbing out the Response
If you are doing simple operations like updating the headers or status of the response you can do that now directly off our event the same way you can with request:
import { getRequestEvent } from "solid-js/web";
const event = getRequestEvent();
console.log(event.request.url);
event.response.headers.set("x-foo", "bar");
console.log(event.response.status);
event.response.status = 201;
This response object proxies the H3 methods which has the nice benefit of being able to use it easier in isomorphic settings without worrying about imports and bundling. Components like <HttpStatus>
and <HttpHeader>
are built using this primitive.
Async Local Storage Everywhere
HTTP helpers are now available at vinxi/http
. Previously we were re-exporting these but we don't want to own this piece. Currently there is a light wrapper around H3 done here. But it means that the provided helpers are usable now directly without passing the H3Event in.
import { useSession } from "vinxi/http";
async function someServerFunction() {
"use server";
const session = await useSession({ password: process.env.SESSION_SECRET});
doSomethingWith(session.data.userId);
}
You can still pass in the H3Event if you want as the first argument, and these Vinxi wrappers also support passing in Solid's RequestEvent as well but between these 2 APIs you probably won't be interfacing with the H3Event much directly in application code.
Typing Locals
SolidStart uses event.locals
to pass around local context to be used as you see fit. Before this was just a record but now you can add specific types to it as well:
declare module "@solidjs/start/server" {
interface RequestEventLocals {
myNumber: number;
someString: string;
}
}
Server Function Improvements
HTTP-Cacheable Server Functions
Technically this came out in 0.4.11 but will announce it here. Solid Start now supports GET
server functions. This is important because it means they can be cached with HTTP cache. And that the arguments to the function will be serialized into the URL.
// example with streaming promise and a 60 second cache life
import { json } from "@solidjs/router";
import { GET } from "@solidjs/start";
const hello = GET(async (name: string) => {
"use server";
return json(
{ hello: new Promise<string>(r => setTimeout(() => r(name), 1000)) },
{ headers: { "cache-control": "max-age=60" } }
);
});
Note that cache
from @solidjs/router
will automatically opt into GET.
Return Responses as well as throw them
There were several comments about ergonomic issues of only supporting throwing of Response objects in server functions. Mostly it was about TypeScript. However, now that we need to support json
helper for adding headers for GET
instead of the typical redirect
or reload
cases of Actions we also support returning Responses.
@solidjs/router
's redirect
, reload
, and json
helpers will all return responses but from a type perspective will not impact your server function. For instance json
above will see that hello
function returns a Promise<{ hello: Promise<string> }>
. And redirect
and reload
return never
meaning getUser
below can only ever return Promise<User>
.
export async function getUser() {
const session = await getSession();
const userId = session.data.userId;
if (userId === undefined) return redirect("/login");
try {
const user: User = await db.user.findUnique({ where: { id: userId } });
// throwing here could have been a bit awkward.
if (!user) return redirect("/login");
return user;
} catch {
// do stuff
throw redirect("/login");
}
}
API Routes Refined
A decent amount of feedback in Beta 2 has been around the FS routing system with API routes. One of the consequences of being Router agnostic is that the API routes needed to be processed separately. In our case it means API routes are always matched before Page routes. With the desire to be able to break them out in the future to be deployable in different places this decision makes a lot of sense. But we had a lot of duplication between router logic and API routes, that didn't really optimize for them.
In 0.5.0 API route logic has been pulled out and they are now being matched and processed by unjs radix3. While ultimately we decided to still have them in the same folder structure for maximum flexibility and visibility, we'd recommend keeping them separate on paths to make it more clear. While you can technically have a GET
method and a default export for a Page component at the same URL if you really want to, you would have to use Accept
headers to early return from the API route without a value. And know it will go through the API route first and then Page route.
Other updates
Moved createHandler back into @solidjs/start/server
and middleware to @solidjs/start/middleware
While it was only a recent change to move createHandler
out it was not the right decision. Circular bundling issues are better resolved by moving the server utilities to a different package (vinxi/http
) and having middleware in its own entry. So you entry-server.tsx
returns to:
import { createHandler, StartServer } from "@solidjs/start/server";
export default createHandler(() => (
<StartServer
document={({ assets, children, scripts }) => (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
)}
/>
));
And your middleware.ts might look like:
import { createMiddleware } from "@solidjs/start/middleware";
export default createMiddleware({
onRequest: [
event => {
console.log("REQUEST", event.request.url);
}
]
});
Replacing Solid Start's CLI
create-solid
in this repo hasn't built properly for almost 8 months now and was slowly falling apart. I was manually editing the bin file on my one computer with a working build. I have removed it from the repo. You can continue to use the currnet version until the new version is published under the same npm init solid
command. We will be replacing it with https://github.com/solidjs-community/solid-cli built by our community in Rust. It's faster, better organized, and more featured thanks to the amazing work of @Tommypop2 and @dev-rb. So it will be where CLI work will continue to improve instead of in this repo.
Support for Solid's renderToString
Since the release of Beta 2 we have been focusing on streaming as the default. But you could always opt into wait for all data loading with the ssr: "async"
. With 0.5.x we have also added back support for ssr: "sync"
which uses renderToString
. This mode synchronously renders on the server until it hits a Suspense boundary and then fetches and renders the rest in the browser. While generally less performant than streaming, it may be a good option for those just moving to SSR.
Continuing towards 1.0
We think these quality of life improvements will made development a lot more streamlined and help you all better build the applications you are looking to make. I'm excited to work through the next couple features as approach RC of 1.0.