Solid UI Library

用于构建用户界面的声明式、高效和灵活的 JavaScript 库。「A declarative, efficient, and flexible JavaScript library for building user interfaces.」

Github stars Tracking Chart

Solid

Solid 是一个用于创建用户界面的声明性 JavaScript 库。它不使用虚拟 DOM。相反,它选择将其模板编译成真正的 DOM 节点,并用细粒度的反应中包装更新。这样,当您的状态更新时,只会运行依赖于它的代码。

主要特性

  • 带有细粒度更新的真实 DOM(没有虚拟 DOM!没有脏检查摘要循环!)。
  • 声明性数据
    • 没有隐藏规则的简单可组合原语。
    • 不需要生命周期方法或专门配置对象的功能组件。
    • 渲染一次心智模型。
  • 快!与优化后的令人痛苦的命令式普通 DOM 代码相比,性能几乎没有区别。 请参见 JS 框架基准测试
  • 小!小! 完全树状结构的 Solid 的编译器将只包含您使用的部分库。
  • 支持并基于 TypeScript 构建。
  • 支持现代特性,如 JSX、Fragments、Context、Portals、Suspense、流式 SSR、渐进式水合、错误边界和并发呈现。
  • Webcomponent 友好,可以编写自定义元素
    • 跨自定义元素的上下文 API
    • 隐式事件委托与 Shadow DOM 重定向
    • Shadow DOM 门户
  • 透明调试:一个 <div> 只是一个 div。

关于 Solid 你应该知道的 5 件事

要点

import { render } from "solid-js/web";
const HelloMessage = props => <div>Hello {props.name}</div>;
render(() => <HelloMessage name="Taylor" />, document.getElementById("hello-example"));

一个简单组件只是一个接受属性的函数。Solid 使用一个渲染函数来创建您的应用程序的反应式挂载点。

JSX 然后被编译成有效的真实 DOM 表达式:

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")
);

_el$ 是一个真正的 div 元素,而 props.name,在本例中是 Taylor,被附加到它的子节点上。请注意,props.name 被包裹在一个函数中。这是因为这是这个组件中唯一会再次执行的部分。即使从外部更新名称,也只有那一个表达式会被重新评估。编译器优化初始渲染,运行时优化更新。这是两全其美的事情。

想看看 Solid 生成的代码。

在线试用

入门

npm init solid <project-type> <project-name>在 npm 6+ 中可用。

你可以通过运行以下命令来开始使用一个简单的 CLI 应用程序。

> npm init solid app my-app

或者是 TypeScript 的启动器。

> npm init solid app-ts my-app

或者您也可以在您自己的项目中安装依赖项。要在 JSX 中使用 Solid (推荐),请运行以下命令。

> npm install solid-js babel-preset-solid

最简单的设置方法是将 babel-preset-solid 添加到您的 .babelrc,或 webpack 的 babel config,或 rollup。

"presets": ["solid"]

看看 @aftzl 的这两篇介绍性文章:了解 Solid:反应性基础
了解 Solid:JSX

文档

资源

没有编译?

不喜欢 JSX?不介意手动封装表达式,性能更差,包大小更大?或者,在非编译环境中,可以使用带标记的模板文本或超脚本。

您可以使用 SkyPack 直接从浏览器运行它们:

<html>
  <body>
    <script type="module">
      import { createSignal, onCleanup } from "https://cdn.skypack.dev/solid-js";
      import { render } from "https://cdn.skypack.dev/solid-js/web";
      import html from "https://cdn.skypack.dev/solid-js/html";
      const App = () => {
        const [count, setCount] = createSignal(0),
          timer = setInterval(() => setCount(count() + 1), 1000);
        onCleanup(() => clearInterval(timer));
        return html`<div>${count}</div>`;
      };
      render(App, document.body);
    </script>
  </body>
</html>

请记住,你仍然需要相应的 DOM 表达式库来使用 TypeScript。标记模板字面值 Lit DOM Expressions 或 HyperScript 与 Hyper DOM Expressions。

浏览器支持

最近 2 个版本的现代常青浏览器和 Node LTS。

社区

有什么问题或点子的话来 Discord 和我们聊聊吧。

开放式集体

捐款支持我们,帮助我们继续我们的活动。[贡献]

赞助商

成为赞助商,在我们的 GitHub 自述中获取您的徽标,并提供指向您站点的链接。[成为赞助商]

状态

Solid 在其 v1.0.0 版本中大部分功能都已完成。下一个版本将主要是在稳定的道路上进行 bug 修复和 API 调整。


(The first version translated by vz on 2020.12.05)

Main metrics

Overview
Name With Ownersolidjs/solid
Primary LanguageTypeScript
Program languageJavaScript (Language Count: 3)
PlatformLinux, Mac, Web browsers, Windows
License:MIT License
所有者活动
Created At2018-04-24 16:36:27
Pushed At2025-04-11 15:15:11
Last Commit At
Release Count340
Last Release Namev1.9.5 (Posted on 2025-02-21 11:35:27)
First Release Namev0.4.2 (Posted on )
用户参与
Stargazers Count33.4k
Watchers Count212
Fork Count1k
Commits Count1.8k
Has Issues Enabled
Issues Count1069
Issue Open Count108
Pull Requests Count373
Pull Requests Open Count21
Pull Requests Close Count85
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

     The Deceptively Simple User Interface Library

Build Status
Coverage Status
NPM Version

Gitter
Subreddit subscribers

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 computations. This way when your state updates only the code that depends on it runs.

Key Features

  • 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.
  • Supports modern features like JSX, Fragments, Context, Portals, Suspense, SSR, Error Boundaries and Asynchronous Rendering.
  • Built on TypeScript.
  • Webcomponent friendly
    • Implicit event delegation with Shadow DOM Retargeting
    • Shadow DOM Portals
  • Transparent debugging: a <div> is just a div.

The Gist

import { render } from "solid-js/dom";

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/dom";

const _tmpl$ = template(`<div>Hello </div>`);

const HelloMessage = props => {
  const _el$ = _tmpl$.cloneNode(true);
  insert(_el$, () => props.name, null);
  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 it's 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.

Installation

You can get started with a simple app with the CLI with by running:

> npm init solid app my-app

Use app-ts for a TypeScript starter.

npm init solid <project-type> <project-name> is available with npm 6+.

Or you can install the dependencies in your own project. To use Solid with JSX (recommended) run:

> npm install solid-js babel-preset-solid

Solid State

Solid's data management is built off a set of flexible reactive primitives. Similar to React Hooks except instead of whitelisting change for an owning Component they independentally are soley responsible for all the updates.

Solid's State primitive is arguably its most powerful and distinctive one. Through the use of proxies and explicit setters it gives the control of an immutable interface and the performance of a mutable one. The setters support a variety of forms, but to get started set and update state with an object.

import { createState, onCleanup } from "solid-js";

const CountingComponent = () => {
  const [state, setState] = createState({ counter: 0 });

  const interval = setInterval(
    () => setState({ counter: state.counter + 1 }),
    1000
  );

  onCleanup(() => clearInterval(interval));

  return <div>{state.counter}</div>;
};

Where the magic happens is with computations(effects and memos) which automatically track dependencies.

const [state, setState] = createState({ user: { firstName: "Jake", lastName: "Smith" }})

createEffect(() =>
  setState({
    displayName: `${state.user.firstName} ${state.user.lastName}`
  })
);

console.log(state.displayName); // Jake Smith
setState('user', {firstName: "Jacob" });
console.log(state.displayName); // Jacob Smith

Whenever any dependency changes the State value will update immediately. Each setState statement will notify subscribers synchronously with all changes applied. This means you can depend on the value being set on the next line.

Solid State also exposes a reconcile method used with setState that does deep diffing to allow for automatic efficient interopt with immutable store technologies like Redux, Apollo(GraphQL), or RxJS.

const unsubscribe = store.subscribe(({ todos }) => (
  setState('todos', reconcile(todos)));
);
onCleanup(() => unsubscribe());

Solid Rendering

Solid's rendering is done by the DOM Expressions library. This library provides a generic optimized runtime for fine grained libraries like Solid with the opportunity to use a number of different Rendering APIs. The best option is to use JSX pre-compilation with Babel Plugin JSX DOM Expressions to give the smallest code size, cleanest syntax, and most performant code. The compiler converts JSX to native DOM element instructions and wraps dynamic expressions in reactive computations.

The easiest way to get setup is add babel-preset-solid to your .babelrc, or babel config for webpack, or rollup:

"presets": ["solid"]

Remember even though the syntax is almost identical, there are significant differences between how Solid's JSX works and a library like React. Refer to JSX Rendering for more information.

Alternatively in non-compiled environments you can use Tagged Template Literals Lit DOM Expressions or even HyperScript with Hyper DOM Expressions.

For convenience Solid exports interfaces to runtimes for these as:

import h from "solid-js/h";
import html from "solid-js/html";

Remember you still need to install the library separately for these to work.

Documentation

Examples

Articles

Status

Solid is mostly feature complete for its v1.0.0 release. The next releases will be mostly bug fixes API tweaks on the road to stability.