DEV Community

Cover image for A First Look at SolidStart
ajcwebdev
ajcwebdev

Posted on • Updated on • Originally published at ajcwebdev.com

A First Look at SolidStart

Outline

All of this project's code can be found in the First Look monorepo on my GitHub.

Introduction

On November 9, 2022, Ryan Carniato published Introducing SolidStart: The SolidJS Framework to announce the beta launch of SolidStart, the eagerly awaited metaframework for SolidJS. SolidStart provides a first-party project starter and metaframework for SolidJS. It prescribes a recommended way to organize, architect, and deploy SolidJS applications.

Vite is included for the build tool along with extra Solid packages for common functionality and a CLI for generating templated projects. These packages enable features such as routing, MetaTags, different rendering modes, TypeScript support, and deployment adapters. In addition to Node and static hosting, adapters currently exist for the following platforms:

A History of SolidJS and How it Compares to React

Before diving into SolidStart, it's worth taking a moment to outline the history and motivation behind the creation of Solid. Branded as "a reactive JavaScript library for building user interfaces," Ryan open sourced the framework on April 24, 2018. It was designed as a spiritual successor to the reactive programming model exemplified by KnockoutJS.

React wasn’t the first JavaScript “Just a Render Library”. I attribute that honor to a much older library, KnockoutJS. Knockout didn’t have components but identified an application was built from 3 parts, Model, ViewModel, and View, and only cared about how you organized the latter. The ViewModel was a revolutionary concept.

ViewModels are instances much like components. But what set Knockout apart was ViewModels could be anything you wanted; an object, a function, a class. There were no lifecycle functions. You could bring your own models and organize your application as you saw fit. Without best practices it could be a complete mess.

But it was truly “Just a Render Library.” Those boundaries haven’t changed in over a decade... As Controllers transformed to Routers, Models to Stores, and ViewModels/Views got wrapped together as Components, the anatomy of a Component (even in a smaller library like React) is still 3 main parts:

  • Container
  • Change (Local State) Manager
  • Renderer

Ryan Carniato - B.Y.O.F. Writing a JS Framework in 2018 (November 10, 2018)

As the 2010s progressed, Ryan believed the JavaScript world had moved on from using composable reactive primitives in favor of class components and lifecycle methods. Dissatisfied with this direction, Ryan aimed for Solid to be a more modern reactive framework inspired by Knockout but with features informed by newer component frameworks like Angular, React, and Vue.

Shortly after the framework's release, React introduced hooks. Their debut in React Today and Tomorrow and 90% Cleaner React With Hooks, October 26, 2018 became a pivotal moment for Solid. React hooks are functions that can access React state and lifecycle methods from functional components. These functions can be composed into more complex UIs much like Solid.

Within a few years, the majority of React developers would be developing with composable, functional patterns. This ensured that React developers would find Solid easily comprehensible. But despite the surface level similarities between Solid and React's syntax, Solid has a few key advantages over React due to its underlying implementation.

Solid removes the need for some of React's more complex hooks that patch over the leaky abstraction underlying React. useCallback exists to give React developers a mechanism for preventing rerenders. But in Solid, components only mount once and don't rerender so there is no need for an equivalent hook.

SolidJS Benchmark Performance

Solid is also one of the most performant JavaScript libraries. This is evidenced by the results of the JS Framework Benchmark. A large, randomized table of entries is created and modified. Rendering duration is measured along with how long various operations take to complete (lower scores are better).

While admittedly a contrived example, the benchmark allows factoring multiple measurements into a single geometric mean representing comparative performance between frameworks. For a combination of all types of read and write operations, Solid ranks just below vanilla JavaScript:

Framework Version Mean
Vanilla JS N/A 1.00
Solid 1.5.4 1.10
Lit-html 1.1.0 1.19
Vue 3.2.37 1.25
Svelte 3.50.1 1.30
Preact 10.7.3 1.43
Angular 13.0.0 1.58
Marko 4.12.3 1.70
React 18.2.0 1.73

Solid ties vanilla JS and ranks just below Svelte on lighthouse startup metrics:

Framework Version Mean
Svelte 3.50.1 1.03
Solid 1.5.4 1.04
Vanilla JS N/A 1.04
Preact 10.7.3 1.06
Lit-html 1.1.0 1.07
Marko 4.12.3 1.18
Vue 3.2.37 1.27
React 18.2.0 1.69
Angular 13.0.0 1.77

SolidStart Motivations

SolidStart takes influence from other JavaScript metaframeworks including Next.js, Nuxt.js, and SvelteKit by introducing multiple build modes, routing conventions, opinionated project structures, and pre-configured deployment adapters. The framework can produce sites or applications that employ either:

In the future, you'll also be able to choose:

Create Client Rendered Solid Project

mkdir ajcwebdev-solidstart
cd ajcwebdev-solidstart
pnpm init
pnpm add solid-js @solidjs/meta @solidjs/router solid-start
pnpm add -D solid-start-node vite-plugin-solid vite undici typescript
Enter fullscreen mode Exit fullscreen mode

Add vite scripts to package.json and set type to module.

{
  "name": "ajcwebdev-solidstart",
  "version": "1.0.0",
  "description": "An example SolidStart application deployed on Netlify, Vercel, and Cloudflare Pages",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "keywords": [ "SolidJS", "SolidStart", "Netlify", "Vercel", "Cloudflare" ],
  "author": "Anthony Campolo",
  "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode

Create a .gitignore file.

echo 'node_modules\n.env\n.DS_Store\ndist\n.solid\nnetlify\n.netlify\n.vercel' > .gitignore
Enter fullscreen mode Exit fullscreen mode

There's only a handful of files needed for a working Solid project. These include a configuration file for Vite (vite.config.ts), an entry point for our JavaScript application (src/root.tsx), and an entry point for our HTML page (index.html).

Run the following commands:

mkdir src
echo > tsconfig.json   # TypeScript Configuration
echo > vite.config.ts  # Vite Configuration
echo > index.html      # HTML entry point where JavaScript app loads
echo > src/root.css    # CSS stylesheet
echo > src/root.tsx    # Defines the document the app renders
Enter fullscreen mode Exit fullscreen mode

In addition to the required files we also created optional files for CSS styling and TypeScript configuration. Later in the tutorial when we migrate this project to SolidStart, we'll remove the HTML file and replace it with two files, entry-server.tsx and entry-client.tsx.

TypeScript and Vite Project Configuration

Copy/paste this impenetrable hunk of gibberish into your tsconfig.json and say a prayer to Microsoft.

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "strict": true,
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "jsxImportSource": "solid-js",
    "jsx": "preserve",
    "types": ["vite/client"],
    "baseUrl": "./",
    "paths": {
      "~/*": ["./src/*"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The vite.config.ts file is where we'll add the Solid Plugin to define our Vite Configuration. Import solidPlugin from vite-plugin-solid and add it to the plugins array inside Vite's defineConfig helper.

// vite.config.ts

import solidPlugin from "vite-plugin-solid"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [solidPlugin()]
})
Enter fullscreen mode Exit fullscreen mode

HTML Entry, CSS Styling, and Render Function

The root Solid component will be imported as an ESM module from /src/root.tsx and set to the src attribute.

<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="An example SolidJS single-page application." />
    <title>A First Look at SolidStart</title>
  </head>

  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script src="/src/root.tsx" type="module"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Include the following CSS styles in src/root.css.

/* src/root.css */

body {
  background-color: #282c34;
  color: white;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  margin: 0;
  text-align: center;
}

header {
  font-size: calc(10px + 2vmin);
  margin: 1rem;
}

a {
  color: #b318f0;
}
Enter fullscreen mode Exit fullscreen mode

To mount Solid and automatically create a reactive root, import render from solid-js/web and pass in two arguments, a top-level component function and an element to mount on:

  • The first argument returns the root component and must be passed a function.
  • The mounting container is passed for the second argument and wired up to the root div.
// src/root.tsx

/* @refresh reload */
import { render } from "solid-js/web"
import "./root.css"

function App() {
  return (
    <>
      <header>
        <h1>A First Look at SolidStart</h1>
        <a href="https://github.com/solidjs/solid">Learn Solid</a>
      </header>
      <footer>
        <span>
          Visit <a href="https://ajcwebdev.com">ajcwebdev.com</a> for more tutorials
        </span>
      </footer>
    </>
  )
}

render(
  () => <App />, document.getElementById('root') as HTMLElement
)
Enter fullscreen mode Exit fullscreen mode

Start Development Server

pnpm dev # or npm run dev | yarn dev
Enter fullscreen mode Exit fullscreen mode

Open localhost:5173 to view the running application in your browser. The page will reload if you make edits.

01 - Solid homepage with styling on localhost 5173

At this point, we could build and deploy a dist folder to any static host provider. Run pnpm build and pnpm serve to test serving your bundle on localhost:4173. Instead of deploying this project, we'll continue to the next section and begin modifying our project to make it work with SolidStart.

Migrate Project to SolidStart

First, delete your existing HTML file and create a routes directory inside src.

rm -rf index.html
mkdir src/routes
echo > src/entry-server.tsx # Server entry point
echo > src/entry-client.tsx # Browser entry point
echo > src/routes/index.tsx # Home route
Enter fullscreen mode Exit fullscreen mode

SolidStart Scripts and Vite Configuration

Replace the Vite scripts with the following SolidStart scripts.

{
  "scripts": {
    "dev": "solid-start dev",
    "build": "solid-start build",
    "start": "solid-start start"
  },
}
Enter fullscreen mode Exit fullscreen mode

Remove solidPlugin from vite-plugin-solid and replace it with solid from solid-start/vite.

// vite.config.ts

import solid from "solid-start/vite"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [solid()]
})
Enter fullscreen mode Exit fullscreen mode

Index Route, Root, and Entry Points

Copy the App component from src/root.tsx and include it in src/routes/index.tsx with export default.

// src/routes/index.tsx

export default function App() {
  return (
    <>
      <header>
        <h1>A First Look at SolidStart</h1>
        <a href="https://github.com/solidjs/solid">Learn Solid</a>
      </header>
      <footer>
        <span>
          Visit <a href="https://ajcwebdev.com">ajcwebdev.com</a> for more tutorials
        </span>
      </footer>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

root.tsx is the point where your code runs on both the server and client. It exports a Root component that is shared on the server and browser as an isomorphic entry point to your application. Since SolidStart is designed for file-system routing, routes are defined via a folder structure under the /routes folder. You can pass them into the <Routes> component with the <FileRoutes> component.

This collects routes from the file-system in the /routes folder to be inserted into a parent <Routes> component. Since <FileRoutes> returns a route configuration, it must be placed directly between <Routes>, typically in the root.tsx file. <Routes> is a special Switch component that renders the correct <Route> child based on the users' location, and switches between them as the user navigates.

// src/root.tsx

// @refresh reload
import { Suspense } from "solid-js"
import { Body, ErrorBoundary, FileRoutes, Head, Html, Meta, Routes, Scripts, Title } from "solid-start"
import "./root.css"

export default function Root() {
  return (
    <Html lang="en">
      <Head>
        <Title>A First Look at SolidStart</Title>
        <Meta charset="utf-8" />
        <Meta name="viewport" content="width=device-width, initial-scale=1" />
        <Meta name="description" content="An example SolidStart application deployed on Netlify, Vercel, and Cloudflare Pages." />
      </Head>
      <Body>
        <ErrorBoundary>
          <Suspense fallback={<div>Loading...</div>}>
            <Routes>
              <FileRoutes />
            </Routes>
          </Suspense>
        </ErrorBoundary>
        <Scripts />
      </Body>
    </Html>
  )
}
Enter fullscreen mode Exit fullscreen mode

entry-client.tsx starts the application in the browser by passing <StartClient> to a mount function. mount is an alias over Solid's hydrate and render methods. It ensures that the client always starts up properly whether you are using SolidStart for client-only rendering or server-side rendering.

// src/entry-client.tsx

import { mount, StartClient } from "solid-start/entry-client"

mount(() => <StartClient />, document)
Enter fullscreen mode Exit fullscreen mode

entry-server.tsx starts the application on the server by passing <StartServer> to a render function called renderAsync. createHandler enables a mechanism for introducing middleware into server rendering. <StartServer> wraps the application root and includes Context providers for Routing and MetaData. It takes the Event object originating from the underlying runtime and includes information such as the request, responseHeaders and status codes.

// src/entry-server.tsx

import { StartServer, createHandler, renderAsync } from "solid-start/entry-server"

export default createHandler(
  renderAsync((event) => <StartServer event={event} />)
)
Enter fullscreen mode Exit fullscreen mode

While this example uses renderAsync, there are three different render functions provided by SolidStart. Each wraps Solid's rendering method and returns a unique output:

  • renderSync calls renderToString to synchronously respond immediately and render the application to a string.
  • renderAsync calls renderToStringAsync to asynchronously respond when the page has fully been loaded and render the application to a promise.
  • renderStream calls renderToStream to asynchronously respond as soon as it can and render the application to a ReadableStream.

Check that everything still displays as expected.

pnpm dev
Enter fullscreen mode Exit fullscreen mode

Open localhost:3000.

Components and Reactive Primitives

Since this is a tutorial about a frontend framework it will be considered illegitimate until we build a counter. Create a components directory and then a file called Counter.tsx inside of it.

mkdir src/components
echo > src/components/Counter.tsx
Enter fullscreen mode Exit fullscreen mode

There are two foundational building blocks at the core of Solid's fine grained reactivity that will enable us to craft this magnificent counter into existence:

  • Components contain stateless DOM elements within functions that accept props and return JSX elements.
  • Reactive Primitives including Signals, Effects, and Memos track and broadcast the changing values that represent the state of the components over time.

In this component we'll create a signal to track the changing value of the counter and an effect to modify the value with button clicks.

Create Signal

Signals contain values that change over time. They are tracked by the framework and update automatically by broadcasting to the rest of the interface. Use createSignal to initialize a value of 0 and set it to count. Increment the counter once every second by passing a setCount(count() + 1) function to a setInterval() method that executes every 1000 milliseconds.

// src/components/Counter.tsx

import { createSignal } from "solid-js"

export default function Counter() {
  const [count, setCount] = createSignal(0)

  setInterval(() => setCount(count() + 1), 1000)

  return (
    <>The count is now: {count()}</>
  )
}
Enter fullscreen mode Exit fullscreen mode

Inside src/routes/index.tsx, import Counter from ../components/Counter. Return a <Counter /> component in the return function of the App component.

// src/routes/index.tsx

import Counter from "../components/Counter"

export default function App() {
  return (
    <>
      <header>
        <h1>A First Look at SolidStart</h1>
        <a href="https://github.com/solidjs/solid">Learn Solid</a>
      </header>
      <main>
        <Counter />
      </main>
      <footer>
        <span>
          Visit <a href="https://ajcwebdev.com">ajcwebdev.com</a> for more tutorials
        </span>
      </footer>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

02 - Homepage with counter

Create Effect

An Effect is an example of an observer that runs a side effect depending on a signal. createEffect creates a new computation (for example to modify the DOM manually) and runs the given function in a tracking scope.

// src/components/Counter.tsx

import { createSignal, createEffect } from "solid-js"

export default function Counter() {
  const [count, setCount] = createSignal(0)

  createEffect(() => count())

  return (
    <>
      <button onClick={() => setCount(count() + 1)}>
        Click Me
      </button>
      <div>The count is now: {count()}</div>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

This automatically tracks the dependencies and reruns the function whenever the dependencies update.

03 - Create effect button

Create Route Data

Create a new file called students.tsx inside the src/routes directory. This will contain a third party API call to return a list of Harry Potter characters.

echo > src/routes/students.tsx
Enter fullscreen mode Exit fullscreen mode

createRouteData is a wrapper over createResource for handling async data fetching and refetching. With SolidStart's file system routing, components defined under /routes can utilize a routeData function which executes when navigation to that component begins. This hook returns the JSON parsed data from the loader function. We'll use the Fetch API to query Harry Potter information on Deno Deploy.

// src/routes/students.tsx

import { useRouteData, createRouteData } from "solid-start"

type Student = { name: string; }

export function routeData() {
  return createRouteData(async () => {
    const response = await fetch("https://hogwarts.deno.dev/students")
    return (await response.json()) as Student[]
  })
}

export default function Page() { }
Enter fullscreen mode Exit fullscreen mode

This routeData function can be thought of like a "loader" function (what a brilliant idea, amazing no one thought of it before) which includes a useRouteData hook to access the returned data.

// src/routes/students.tsx

import { useRouteData, createRouteData } from "solid-start"

type Student = { name: string; }

export function routeData() {
  return createRouteData(async () => {
    const response = await fetch("https://hogwarts.deno.dev/students")
    return (await response.json()) as Student[]
  })
}

export default function Page() {
  const students = useRouteData<typeof routeData>()

  return (
    <>
      <header>
        <h1>Students</h1>
      </header>
      <main>
        <code>{JSON.stringify(students(), null, 2)}</code>
      </main>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

useRouteData can use whatever data is returned from the routeData loader function.

04 - Return student data to page as raw JSON

The <For> component loops over an array of objects. The <For> component has only one prop, each, which is passed an array to loop over with a callback similar to JavaScript's map callback.

// src/routes/students.tsx

import { useRouteData, createRouteData } from "solid-start"
import { For } from "solid-js"

type Student = { name: string; }

export function routeData() {
  return createRouteData(async () => {
    const response = await fetch("https://hogwarts.deno.dev/students")
    return (await response.json()) as Student[]
  })
}

export default function Page() {
  const students = useRouteData<typeof routeData>()

  return (
    <>
      <header>
        <h1>Students</h1>
      </header>
      <main>
        <For each={students()}>
          {student => <li>{student.name}</li>}
        </For>
      </main>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

05 - Loop over json response and display data with for component

API Routes

API routes are similar to other routes except instead of exporting a default Solid component with a routeData function, they export functions that are named after the HTTP methods they handle such as GET or POST.

mkdir src/routes/api
echo > src/routes/api/index.ts
Enter fullscreen mode Exit fullscreen mode

json is a helper function to send JSON HTTP responses. Return a JSON object with the key set to hello and the value set to world.

// src/routes/api/index.ts

import { json } from "solid-start"

export function GET() {
  return json(
    { hello: "world" }
  )
}
Enter fullscreen mode Exit fullscreen mode

Open 127.0.0.1:3000/api or make a request with cURL.

curl http://127.0.0.1:3000/api
Enter fullscreen mode Exit fullscreen mode
{"hello":"world"}
Enter fullscreen mode Exit fullscreen mode

Deployment Adapters

Here is the directory and file structure for the final project before including any files related to deployment:

.
├── src
│   ├── components
│   │   └── Counter.tsx
│   ├── routes
│   │   ├── api
│   │   │   └── index.ts
│   │   ├── index.tsx
│   │   └── students.tsx
│   ├── entry-client.tsx
│   ├── entry-server.tsx
│   ├── root.css
│   └── root.tsx
├── package.json
├── tsconfig.json
└── vite.config.ts
Enter fullscreen mode Exit fullscreen mode

Push your project to a GitHub repository.

git init
git add .
git commit -m "mr solid"
gh repo create ajcwebdev-solidstart \
  --description="An example SolidJS application deployed on Netlify, Vercel, and Cloudflare Pages." \
  --remote=upstream \
  --source=. \
  --public \
  --push
Enter fullscreen mode Exit fullscreen mode

If you only want to use a single deployment platform, select one of the next three options and push the changes to the main branch. I will deploy the project to all three by creating a different branch for each and specifying the correct branch on the deployment platform.

Deploy to Netlify

Import the netlify adapter from solid-start-netlify.

// vite.config.ts

// @ts-ignore
import netlify from "solid-start-netlify"
import solid from "solid-start/vite"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [solid({
    adapter: netlify({ edge: true })
  })]
})
Enter fullscreen mode Exit fullscreen mode

Install solid-start-netlify and the Netlify CLI.

pnpm add -D solid-start-netlify netlify-cli @types/node
Enter fullscreen mode Exit fullscreen mode

Create a netlify.toml file for the build instructions.

echo > netlify.toml
Enter fullscreen mode Exit fullscreen mode

Set the command to pnpm build and the publish directory to netlify.

# netlify.toml

[build]
  command = "pnpm build"
  publish = "netlify"
Enter fullscreen mode Exit fullscreen mode

Connect the repository to your Netlify account through the Netlify dashboard or use the following commands with the Netlify CLI.

pnpm ntl login
pnpm ntl init
Enter fullscreen mode Exit fullscreen mode

The build commands will be automatically entered from the netlify.toml file.

pnpm ntl deploy --prod --build
Enter fullscreen mode Exit fullscreen mode

Open ajcwebdev-solidstart.netlify.app to see a running example.

Deploy to Vercel

Install solid-start-vercel and the Vercel CLI.

pnpm add -D solid-start-vercel vercel
Enter fullscreen mode Exit fullscreen mode

Import the vercel adapter from solid-start-vercel.

// vite.config.ts

// @ts-ignore
import vercel from "solid-start-vercel"
import solid from "solid-start/vite"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [solid({
    adapter: vercel({ edge: true })
  })]
})
Enter fullscreen mode Exit fullscreen mode

Deploy the project with the Vercel CLI.

pnpm vercel --yes --prod
Enter fullscreen mode Exit fullscreen mode

Open ajcwebdev-solidstart.vercel.app.

Deploy to Cloudflare

SolidStart includes two adapters for Cloudflare, one for Cloudflare Workers and another for Cloudflare Pages. It's important to note that the Cloudflare Pages adapter is also using Workers through Pages Functions. Install solid-start-cloudflare-pages and the wrangler CLI.

pnpm add -D solid-start-cloudflare-pages wrangler
Enter fullscreen mode Exit fullscreen mode

Import the cloudflare adapter from solid-start-cloudflare-pages.

// vite.config.ts

// @ts-ignore
import cloudflare from "solid-start-cloudflare-pages"
import solid from "solid-start/vite"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [solid({
    adapter: cloudflare({})
  })],
})
Enter fullscreen mode Exit fullscreen mode

Build the project's assets and run a local Worker emulation on localhost:8788 with wrangler pages dev.

pnpm wrangler login
pnpm build
pnpm wrangler pages dev ./dist/public
Enter fullscreen mode Exit fullscreen mode

Create a project with wrangler pages project create and deploy the project with wrangler pages publish.

pnpm wrangler pages project create ajcwebdev-solidstart \
  --production-branch production
pnpm wrangler pages publish dist/public \
  --project-name=ajcwebdev-solidstart \
  --branch=production
Enter fullscreen mode Exit fullscreen mode

Open ajcwebdev-solidstart.pages.dev.

Top comments (21)

Collapse
 
peerreynders profile image
peerreynders

In case anybody is wondering, the routeData(args: RouteDataArgs) (RouteDataFuncArgs in solid-router) is passed an argument containing the routing information.

SolidStart: Fetching data with a key

Collapse
 
ajcwebdev profile image
ajcwebdev

Thank you for the reference, this part of Solid Start in particular is just straight up magic to me right now 🪄.

Collapse
 
peerreynders profile image
peerreynders

Most of the information is with solid-router.

The file routes handle the route configuration implicitly which is where the magic comes from.

solid-router data functions are the equivalent to SolidStart's routeData() function.

The route data function is passed the routing information so that it can obtain any additional information that is needed for the page (component). The page obtains the information that was prepared by the route data function via the useRouteData function.

It took me some time to figure out this situation:

src/routes/users.tsx
src/routes/users/index.tsx
Enter fullscreen mode Exit fullscreen mode

src/routes/users/index.tsx defines the content for the /users route but src/routes/users.tsx defines the layout that will be used for that content and the content is projected via the <Outlet> component. (Nested Routes).

Note that src/routes/users.tsx itself is projected via the <FileRoutes> component in root.tsx.

However given:

src/root.tsx
src/routes/index.tsx
Enter fullscreen mode Exit fullscreen mode

root.tsx acts as the layout for the / route and the content is projected via the <FileRoutes> component.

Collapse
 
peerreynders profile image
peerreynders

If you are interested some examples can be found in here:

GitHub logo peerreynders / solid-start-notes-basic

Basic client rendered notes app using SolidStart beta

SolidStart Notes (basic)

Overview

First exploration of SolidStart (beta 0.2.6). The app is a port of the December 2020 React Server Components Demo (LICENSE; no pg fork) but here it's just a basic client side routing implementation. It doesn't use a database but just holds the notes in server memory synchronized to the notes-db.json file. This app is not intended to be deployed but simply serves as an experimental platform.

The longer term goal is to eventually leverage island routing to maximum effect once it's more stable and documented (nksaraf already demonstrated that capability (live demo) with a non-standard branch of SolidStart).

$ npm i
added 359 packages, and audited 360 packages in 3s

37 packages are looking for funding
  run `npm fund` for details
Enter fullscreen mode Exit fullscreen mode
Collapse
 
thetarnav profile image
Damian Tarnawski

a first deep long stare at solidstart* (thank you :))

Collapse
 
ajcwebdev profile image
ajcwebdev

Thank you 🙏, I try to be thorough.

Collapse
 
coskuntekin profile image
coskuntekin

yet another JavaScript framework with compare table, yaaay!

Collapse
 
ajcwebdev profile image
ajcwebdev

Ha, if there's not a table is it even a real benchmark?

Collapse
 
aneshodza profile image
anes

Love to see that I'm not the only one that has an interest in solid start! Nice article :)

Collapse
 
ajcwebdev profile image
ajcwebdev

Yeah I've been watching Solid closely for at least a year and was patiently awaiting the release of Solid Start. The community is really starting to pick up steam.

Collapse
 
arifpateldubaiprestonuk profile image
Arif Patel Dubai Preston UK

Thank You! For This Type Of Nice articles :)

Collapse
 
ajcwebdev profile image
ajcwebdev

Thanks for reading!

Collapse
 
nexxeln profile image
Shoubhit Dash

Very nice article! The Form stuff is super cool tooo maybe you should add a bit about it in the post

Collapse
 
ajcwebdev profile image
ajcwebdev

Yeah I always struggle with deciding how much to include before an article just becomes totally ridiculous in length. I'm thinking I'll have a follow up article that will include both tRPC and forms/mutations.

Collapse
 
peerreynders profile image
peerreynders • Edited

I think the already included createServerData$, createServerAction$ and API Routes delay the need to reach for solutions like tRPC.

Not to mention islands + islandsrouter that can provide "server-component-like" functionality (experimental source, demo).

Thread Thread
 
ajcwebdev profile image
ajcwebdev

Interesting, will those provide end-to-end typesafety?

Thread Thread
 
peerreynders profile image
peerreynders

I was getting the impression that the TS settings are still pretty loose right now as SolidStart is still in beta.

But IIRC from the Theo stream the intention is to make it typesafe (can't be sure though).

Thread Thread
 
ajcwebdev profile image
ajcwebdev

Cool cool, thanks for the insights! Honestly, my desire to integrate tRPC has less to do with any actual technical reasons and more to do with following along with my tried-and-true Hype Based Development strategy 😆.

Thread Thread
 
peerreynders profile image
peerreynders

Right, which is why it's included in the SolidStart docs.

However, in my view tRPC is a solution that largely fits the React/Next.js space or perhaps between node applications and only really makes sense when the same team is in charge of both ends anyway (background: A Brief History of Distributed Programming: RPC; also in the long term React Server Components (once fully supported) may lessen the need for tRPC).

But SolidStart already has baked in solutions for server/client communication that should fit most use cases.

tRPC would likely only come into play if the server already existed prior to using SolidStart and if islandsrouter is used that interaction could move to the server anyway as the client may only need HTML updates.

Collapse
 
leob profile image
leob

React performance pretty atrocious in these 2 tests, especially compared to Vue, while React makes you work harder (makes you jump through a lot of hoops with useMemo and whatnot, putting the burden on the programmer to manually optimize re-renders) ... Vue takes care of more stuff for you, with a smaller bundle size!

The only thing that React has going for it is that it's dominant in the marketplace, the proverbial 900 pound gorilla, but it's not the smartest ape in the family :-P

Collapse
 
ajcwebdev profile image
ajcwebdev

Not sure how you came away from this article thinking that Vue is the solution to React's performance problems (instead of maybe, I dunno, Solid) but I commend your ability to arrive at whatever conclusion you want.