Solid is a declarative JavaScript library for creating user interfaces. It does not use a Virtual DOM. Instead it opts to compile its templates down to real DOM nodes and wrap updates in fine grained reactions. This way when your state updates only the code that depends on it runs.
This branch is PoC of of Trusted Types integration into solid.js library. From my testing, no direct changes to solid.js
code needs to be performed - however there needs to be a change in the JSX preprocessing code. This code is included in
a dependency called dom-expressions
. The integration code can be found in
https://github.com/Siegrift/dom-expressions/tree/trusted-types.
I had some problem using a custom build of dom-expression
library, so I ended up replacing the necessary files inside
node modules directly. This is a fragile setup, but it's good enough for this PoC. To correctly build the Trusted Types
compliant version of solid.js, follow these steps:
- Clone this (
solid
) repository
git clone --branch trusted-types https://github.com/Siegrift/solid/
- Clone
dom-expressions
alongside this project
git clone --branch trusted-types https://github.com/Siegrift/dom-expressions
The two projects should be alongside each other:
# tree -L 1 .
├── solid
├── dom-expressions
...
- Download dependencies and build the
dom-expressions
project:
cd dom-expressions
npm install && npm run build
This will build the dom-expressions
project and prepare it for use inside solid
library.
- From this (
solid
) repository run:
npm install
- The library is ready to be built (using
yarn build
) and used in solid applications
Solid transforms the JSX into code chunks using HTML templates which are then directly updated in the DOM when
necessary. These templates are populated via innerHTML
property which sets the content of the template based on the
JSX expression. This JSX transformation is performed by babel at compile time. This by definition means that no
dangerous (attacker controlled values) can be passed to the template. For this reason it is safe to allow all templates
created by JSX transformation, which we do so using a Trusted Types policy called solid-dom-expressions
.
Note that the updates of the JSX or dynamic JSX values are handled via updates, for which standard Trusted Types rules apply.
- Real DOM with fine-grained updates (No Virtual DOM! No Dirty Checking Digest Loop!).
- Declarative data
- Simple composable primitives without the hidden rules.
- Function Components with no need for lifecycle methods or specialized configuration objects.
- Render once mental model.
- Fast!
- Almost indistinguishable performance vs optimized painfully imperative vanilla DOM code. See Solid on JS Framework Benchmark.
- Fastest at Server Rendering in the Isomorphic UI Benchmarks
- Small! Completely tree-shakeable Solid's compiler will only include parts of the library you use.
- Supports and is built on TypeScript.
- Supports modern features like JSX, Fragments, Context, Portals, Suspense, Streaming SSR, Progressive Hydration, Error Boundaries and Concurrent Rendering.
- Works in serverless environments including AWS Lambda and Cloudflare Workers.
- Webcomponent friendly and can author Custom Elements
- Context API that spans Custom Elements
- Implicit event delegation with Shadow DOM Retargeting
- Shadow DOM Portals
- Transparent debugging: a
<div>
is just a div.
Learn more on the Solid Website and come chat with us on our Discord
import { render } from "solid-js/web";
const HelloMessage = props => <div>Hello {props.name}</div>;
render(() => <HelloMessage name="Taylor" />, document.getElementById("hello-example"));
A Simple Component is just a function that accepts properties. Solid uses a render
function to create the reactive mount point of your application.
The JSX is then compiled down to efficient real DOM expressions:
import { render, template, insert, createComponent } from "solid-js/web";
const _tmpl$ = template(`<div>Hello </div>`);
const HelloMessage = props => {
const _el$ = _tmpl$.cloneNode(true);
insert(_el$, () => props.name);
return _el$;
};
render(
() => createComponent(HelloMessage, { name: "Taylor" }),
document.getElementById("hello-example")
);
That _el$
is a real div element and props.name
, Taylor
in this case, is appended to its child nodes. Notice that props.name
is wrapped in a function. That is because that is the only part of this component that will ever execute again. Even if a name is updated from the outside only that one expression will be re-evaluated. The compiler optimizes initial render and the runtime optimizes updates. It's the best of both worlds.
Want to see what code Solid generates:
You can get started with a simple app by running the following in your terminal:
> npx degit solidjs/templates/js my-app
> cd my-app
> npm i # or yarn or pnpm
> npm run dev # or yarn or pnpm
Or for TypeScript:
> npx degit solidjs/templates/ts my-app
> cd my-app
> npm i # or yarn or pnpm
> npm run dev # or yarn or pnpm
This will create a minimal client-rendered application powered by Vite.
Or you can install the dependencies in your own project. To use Solid with JSX (recommended) run:
> npm install solid-js babel-preset-solid
The easiest way to get setup is add babel-preset-solid
to your .babelrc, or babel config for webpack, or rollup:
"presets": ["solid"]
For TypeScript remember to set your TSConfig to handle Solid's JSX by:
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js",
}
Check out the Documentation website.
The last 2 versions of modern evergreen browsers and Node LTS.
Come chat with us on Discord
Support us with a donation and help us continue our activities. [Contribute]
Become a sponsor and get your logo on our README on GitHub with a link to your site. [Become a sponsor]