A declarative, efficient, and flexible JavaScript library for building user interfaces.

Overview

Solid

Build Status Coverage Status NPM Version Discord 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 reactions. 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.
  • 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.
  • 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.

Top 5 Things You Should Know about Solid

The Gist

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:

Try it Online

Getting Started

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

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

> npm init solid app my-app

Or for a TypeScript starter:

> npm init solid app-ts my-app

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",
}

Documentation

Resources

No Compilation?

Dislike JSX? Don't mind doing manual work to wrap expressions, worse performance, and having larger bundle sizes? Alternatively in non-compiled environments you can use Tagged Template Literals or HyperScript.

You can run them straight from the browser using 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>

Remember you still need the corresponding DOM Expressions library for these to work with TypeScript. Tagged Template Literals Lit DOM Expressions or HyperScript with Hyper DOM Expressions.

Browser Support

The last 2 versions of modern evergreen browsers and Node LTS.

Testing Powered By SauceLabs

Community

Come chat with us on Discord

Contributors

Open Collective

Support us with a donation and help us continue our activities. [Contribute]

Sponsors

Become a sponsor and get your logo on our README on GitHub with a link to your site. [Become a sponsor]

Status

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

Comments
  • Help Me Understand Documentation Holes

    Help Me Understand Documentation Holes

    I really would appreciate feedback here. It is so hard for me to see it since I've been so close to this for so long and I've developed apps in this manner for 10 years. I'm going to be the worst person to write the documentation since it is all so second nature for me. Yet, I am most likely going to be the person writing the documentation since I understand how everything works so well.

    So can you please comment on anythings you found confusing about Solid as you've been trying it out, using it in your demo projects, integrating it with 3rd party libraries. And if you did find a solution can you comment on what you feel would have been the easiest way to describe it to you. Even if it takes me some time to compile all of this I think it would also highlight some early gotcha's for people trying the library.

    I know I need to do a lot better here but this is a bit of a blindspot for me. Thank you.

    help wanted good first issue documentation 
    opened by ryansolid 116
  • SSR Specification

    SSR Specification

    I've had many people ask me about SSR. In fact, it's probably the most requested feature. So far I've made it mechanically possible to do rehydration in the client for non-asynchronous rendered cases. Using JSDOM or similar we can run Solid on the server to generate fake DOM nodes that can be stringified.

    I don't know enough about the topic of SSR and Isomorphic Libraries to know beyond that how they are expected to work. Nor am I the best suited to spearhead this as I have no reason, outside of requests, to look into this. It's just not an area where I do work. I've been working hard to improve clientside performance to a point that TTI speed and Service worker caching makes the whole thing mute for high-performance Web Apps and PWAs. But I know there are other use cases out there, and that the research especially being done with React and Next.js is impressive. But I'm much more incentivized to show far we can optimize SPAs.

    Currently, I am not really clear even what the essential building blocks are. Routing obviously comes to mind. But I'm unclear on isomorphic patterns there. How are lifecycles and asynchronous requests handled? Lazy loaded components? How do things differ between static site generation and otherwise? What sort of tooling is useful? If anyone has experience in these areas it would be invaluable.

    I realize people are looking for libraries and frameworks for opinions here, but I haven't formed them. I will work with anyone interested to make Solid be able to handle the mechanicals. Unless others help take it on though I don't see SSR progressing in the next 6 months. I have a lot of other work to get done to make Solid better.

    What can I do to Help?

    Join the conversation. I'm free to chat at length about this on gitter. Post in this thread what you'd like to see. Or any Solid specific insights you have from your experience with other SSR libraries. If you think you might have answers to any of my questions above please shed some light on the issues.

    Thank you.

    enhancement help wanted 
    opened by ryansolid 45
  • Revised Component types (children, ref)

    Revised Component types (children, ref)

    Based on recent discussion on #typescript. This change summary is longer than the diff. πŸ™‚

    • Rename past Component type to ~~ComponentWithChildren~~ ParentComponent.

      • Motivation: Most components don't actually support children. This causes a type error upon accidental passing of children / forces you to think about which components support children.
      • Also, many users on #help/#typescript have asked for how to type such a component.
      • This is a slight breaking change (users may need to change some instances of Component type to ParentComponent to avoid type errors) so should probably wait for Solid 1.4.
    • Two-parameter FlowComponent requires children and makes it easy to give a custom type for children, as in many flow control components.

    • New Component type does not have automatic children property (like React's preferred VoidFunctionalComponent), offering another natural way to type props.children:

      Component<{children: JSX.Element}>
      
    • New VoidComponent forces not having children prop, to make it extra clear how to type this.

    • ParentProps, FlowProps, and VoidProps type helpers for the props argument to ParentComponent, FlowComponent, and VoidComponent.

    • Sadly none of these are great when you need to parameterize by a generic type, but still good starting points for people typing simple components.

    • ~~props argument in both Component and ComponentWithChildren automatically cast to readonly (shallow one level only), to avoid accidental assignment to props.foo (usually a getter) while still allowing passing mutables in props.~~ Removed; see below.

      • ~~Add Props<T> helper for this transformation.~~
      • Inspired by this React plan.
    • Add @LXSMNSYC's Ref<T> type so it's easy to type props.ref:

      Component<{ref: Ref<Element>}>
      

      Fixes #778.

    An alternative would be to leave Component as is, and rename the new Component type to VoidComponent. This would preserve backward compatibility and match React. But see this discussion for good arguments why (in React) VoidComponent is better than straight Component. And React 18 is changing the type of FunctionalComponent to what was VoidFunctionalComponent.

    typescript 
    opened by edemaine 39
  • Update Logo/Theme

    Update Logo/Theme

    I am not a visual artist. I used a logo generator. I think at some point in the near future Solid needs to get a real logo. Now I'm not necessarily inviting an open free for all as I don't want to waste anyone's time but I could definitely benefit from some help.

    enhancement help wanted 
    opened by ryansolid 33
  • Updating solid-js and babel-preset-solid to 0.24.0 break my buttons

    Updating solid-js and babel-preset-solid to 0.24.0 break my buttons

    Describe the bug After upgrading the places I used onClick are broken.

    The examples: https://github.com/steelbrain/linter-ui-default/blob/2b2f2ca1ed449d4ec8e0f076020aec2831388ce8/lib/tooltip/message.tsx#L101

          <div className={`linter-excerpt ${message.severity}`}>
            {
              // fold butotn if has message description
              message.description && (
                <a href="#" onClick={async () => await toggleDescription()}>
                  <span className={`icon linter-icon icon-${state.descriptionShow ? 'chevron-down' : 'chevron-right'}`} />
                </a>
              )
            }
    	<div>
    

    To Reproduce

    Expected behavior Click should work

    Reproduction This is reproducible inside Atom. I cannot seem to be able to make a separate reproduction outside Atom. https://github.com/steelbrain/linter-ui-default/

    Downgrading Solid completely fixed the issue!

    Additional context

    bug 
    opened by aminya 32
  • Duplicate edges in signal graph

    Duplicate edges in signal graph

    If I understand correctly, when signal value is accessed, it doesn't perform a check when the edge already exists:

    1. Accessing current() value: https://github.com/ryansolid/solid/blob/8fe0c11360387a325d64e040a756585a69f6da63/src/signals.ts#L189-L192
    2. Creating an edge: https://github.com/ryansolid/solid/blob/8fe0c11360387a325d64e040a756585a69f6da63/src/signals.ts#L405-L439

    Without such checks, use cases that involve sorting/filtering in data tables will create insanely huge graphs.

    For example, simple sort() on 5000 items will create ~110000 edges:

    let i = 0;
    
    class Item {
      _a = Math.random();
    
      get a() {
        i++;
        return this._a;
      }
    }
    
    const items = [];
    for (let i = 0; i < 5000; i++) {
      items.push(new Item());
    }
    
    items.sort((a, b) => a.a - b.a);
    console.log(i);
    
    enhancement 
    opened by localvoid 32
  • Help in making a `etch-solid` library

    Help in making a `etch-solid` library

    Plan

    I plan to use solid for Atom projects. However, Atom has its own DOM library called etch, which is used in the core of Atom as well as many of its packages. etch has some limitations, it has an average performance, and forces a certain style of programming. https://github.com/atom/etch

    Implementation

    To make the transition seamless, I want to make a drop-in replacement library that uses solid as its backend but has the same API as etch. Could you help me with this?

    I have made a demo of this etch-solid library: https://codesandbox.io/s/etch-solid-pwonz?file=/src/index.jsx

    Details The documentation of etch gives an overview of the API https://github.com/atom/etch

    These are the source code of the API (initialize, update, destroy): https://github.com/atom/etch/blob/master/lib/component-helpers.js and here the dom function: https://github.com/atom/etch/blob/9b90d6ad88b90b8a273992c540879b915d9967a2/lib/dom.js#L4

    P.S: The other approach is to use meta-programming to transpile etch code to solid code. However, this can be complex, but I am open to that approach too. Something like this babel plugin or this transformer

    Benchmarks

    Details In the benchmarks, etch is behind solid so this can be beneficial in general (~25% improvement). This can enhance the responsiveness of the editor. https://krausest.github.io/js-framework-benchmark/2020/table_chrome_84.0.4147.89.html

    image

    The last dramatic change for improving the performance happened back in 2017 by introducing etch. Now it is the time to replace that with a faster modern framework. Even if we do not use it for text rendering, other parts of the Atom can benefit from it. https://blog.atom.io/2017/06/22/a-new-approach-to-text-rendering.html https://blog.atom.io/2018/01/10/the-state-of-atoms-performance.html

    P.S:

    • I am not sure if this repository is the best place to have this issue. Feel free to transfer it or move the discussion here
    question 
    opened by aminya 31
  • Redefining `batch`, and the concept of a new batched effect

    Redefining `batch`, and the concept of a new batched effect

    Describe the bug

    import { createSignal, batch } from "solid-js";
    
    const [count, setCount] = createSignal(0);
    
    batch(() => {
      console.log('set:', setCount(123));
      console.log('get:', count()); // logs 0 instead of 123
    });
    

    Your Example Website or App

    https://playground.solidjs.com/?hash=-937748346&version=1.3.9

    Steps to Reproduce the Bug or Issue

    See link

    Expected behavior

    Reading and writing signals should be atomic operations.

    Screenshots or Videos

    No response

    Platform

    n/a

    Additional context

    I spent a weekend debugging an issue I thought was in LUME, because I never expected reading a signal after setting it would return an old value. Essentially the write is not atomic.

    The issue in my case also wasn't obvious because the read was far removed (several methods deep) from where the write happens.

    The reason I wanted to use batch was to group the write of a signal with some method calls after it, so that reactivity would be triggered after the write and subsequent method calls.

    question 
    opened by trusktr 30
  • css-in-js options?

    css-in-js options?

    This is a great library and builds on the shortcomings of some big libraries out there. Absolutely prefer DOM library over virtual DOM implementation. Thanks for this great effort. πŸ’―

    I have a couple of questions:

    • Does anyone know of a css-in-js (styled) library that could work with solid out of the box?
    • What is the React.createElement equivalent for solid.js if someone were to write a port of @emotion/styled or something similar?

    Thanks

    question 
    opened by praneybehl 27
  • Boolean attributes

    Boolean attributes

    Questions: How should JSX attributes foo and foo={true} behave for an HTML element, as in <div foo> or <div foo={true}>? Should the behavior differ for components and/or spreads?

    Current behavior in Solid: Assume const Div = (props) => <div {...props}/>

    | JSX | Equivalent HTML | |-----|--------------------| | <div foo> | <div foo=""> | | <div foo=""> | <div foo=""> | | <div foo={true}> | <div foo="true"> | | <div foo="true"> | <div foo="true"> | | <Div foo> | <div foo="true"> β˜† | | <Div foo=""> | <div foo=""> | | <Div foo={true}> | <div foo="true"> | | <Div foo="true"> | <div foo="true"> |

    The β˜† behavior (another consequence of setAttribute's string casting) is particularly counterintuitive, as it differs between HTML elements and component-wrapped elements. (It may also be an SSR discrepancy?) @fabiospampinato's observation of this weirdness is what spawned this exploration (in #templating channel, also with @LXSMNSYC).

    Relevant facts:

    • HTML 5 defines attribute foo to be equivalent to foo=""
    • React defines that foo is equivalent to foo={true}.
    • TypeScript treats foo like foo={true} (attribute should accept Boolean value)
    • React (specifically react-dom) converts JSX attribute foo to HTML equivalent of foo="true" unless foo is on a whitelist of "Boolean" attributes, in which case it converts to foo="". Here's a relevant list; note that there are some Boolean-like attributes which aren't actually Boolean. For example, React "correctly" converts draggable={true} to draggable="true" and "correctly" converts async={true} to async="".

    Desired properties:

    1. foo is always equivalent to foo="" for HTML/SVG elements (as in HTML 5). This is useful for copy/pastability of HTML, which the JSX spec considers important.
    2. foo is equivalent to foo={true} (as in React and TypeScript)
    3. draggable={true} is equivalent to draggable="true"
    4. <div foo> is equivalent to const Div = (props) => <div {...props}/>; <Div foo>

    We can't have all four properties.

    • Properties 1, 2, and 3 contradict each other: 1+2 imply draggable={true} is equivalent to draggable="".
    • React satisfies Properties 2, 3, and 4. It follows Property 1 only for a whitelist of Boolean attributes.
    • Solid satisfies Properties 1 and 2. It satisfies Property 3 for Div but not div. It doesn't satisfy Property 4 because of β˜†.

    Proposal: I really like Property 1, and would propose gaining Property 4 by compiling foo={value} to essentially _el$.setAttribute('foo', value === true ? '' : value), where value is stored in a temporary variable if it's a general expression, with a similar modification to spreads. This would basically flip β˜†, and also change those marked "!":

    | JSX | Equivalent HTML | |-----|--------------------| | <div foo> | <div foo=""> | | <div foo=""> | <div foo=""> | | <div foo={true}> | <div foo=""> ! | | <div foo="true"> | <div foo="true"> | | <Div foo> | <div foo=""> β˜† | | <Div foo=""> | <div foo=""> | | <Div foo={true}> | <div foo=""> ! | | <Div foo="true"> | <div foo="true"> |

    (By contrast, React's approach of an attribute whitelist feels gross...)

    opened by edemaine 24
  • feat(signal): abortable resource

    feat(signal): abortable resource

    As mentioned earlier on Discord, it would be helpful to be able to abort resource fetching (for fetch or anything else you intend to make abortable). A simple way to do so is to introduce an optional third argument to the fetcher that if used creates an AbortController automatically and calls it whenever the resource is fetched anew. This saves developers the hassle of managing the creation of new AbortControllers themselves, as those are not reusable once called.

    opened by atk 24
  • Fill name option of some primitives in dev

    Fill name option of some primitives in dev

    Show, For, children, and other primitives are used frequently so it would be nice to see their internal names instead of autogenerated. Having these names would help in understanding their purpose and behavior.

    image

    vs

    image

    Since the options object doesn't get tree-shaken out of the built application bundle, I included them only in dev, but it's hard to only target one output here without doing any changes to the other ...and avoid duplicating the source code too much.

    opened by thetarnav 1
  • Store setter type signature allows setting readonly properties

    Store setter type signature allows setting readonly properties

    Describe the bug

    While creating a store using a getter property I encountered a runtime error trying to update the store. For example when I define the following store:

    const [ store, setStore ] = createStore({
        get value() { return 'value' },
    });
    
    setStore('value', 'modified');
    

    I would expect a type error on the last line, instead it results in a runtime error: Uncaught TypeError: setting getter-only property "value"

    Your Example Website or App

    https://stackblitz.com/edit/solidjs-templates-9qbvhq?file=src/App.tsx

    Steps to Reproduce the Bug or Issue

    1. Go to the linked stackblitz.
    2. The app will compile
    3. At runtime it will throw an error

    Expected behavior

    As a user, the given code should produce a compile time type-error. Instead you get a runtime error.

    Screenshots or Videos

    No response

    Platform

    • OS: Windows (but affects others)
    • Browser: Firefox (but affects others)
    • Version: 106.0.5

    Additional context

    No response

    help wanted typescript 
    opened by JorrenH 1
  • useContext form population causing Zod form validation to fail

    useContext form population causing Zod form validation to fail

    Describe the bug

    Not sure where to post this but it seems to be an issue with useContext, so I am going to make a bug report here first.

    I am using useContext with a solidjs storage primitive createLocalStorage(). I am then creating a store Provider for a form, and then using the provider's values to pre-populate a form text input.

    I am also using Zod for the validation, which checks whether the form input is empty or not.

    The strange thing is when the field is populated and the submit button is pressed a validation error is thrown stating that the field cannot be empty. If I pass the variable via props instead, everything works as expected.

    Your Example Website or App

    https://codesandbox.io/s/winter-tdd-n45wry?file=/src/main.tsx

    Steps to Reproduce the Bug or Issue

    Click on submit button, you will see form error String must contain at least 1 character(s) Enter something into the input field and then press submit and everything should work as expected.

    Expected behavior

    n/a

    Screenshots or Videos

    No response

    Platform

    latest solidjs latest zod latest storage primitives

    Additional context

    No response

    downstream 
    opened by 0bon 7
  • button click not disabled on within fieldset

    button click not disabled on within fieldset

    Describe the bug

    click not disabled when wrapping button in fieldset

    This is the same issue as #7711 in react

    <fieldset disabled>
      <button onClick={() => alert('clicked')}>
        click me here and <span style={{color: 'red'}}>here</span>
      </button>
    </fieldset>
    

    Your Example Website or App

    https://stackblitz.com/edit/solidjs-templates-jeskz7?file=src/App.tsx

    Steps to Reproduce the Bug or Issue

    Go to the stackblitz Try to click the button both on the gray and red text That'll show that clicking directly on the button doesn't trigger the onClick, while clicking on the child element will.

    Expected behavior

    Clicking on anything within the button should not trigger the onClick handler on the button if the fieldset is set to disabled.

    Screenshots or Videos

    No response

    Platform

    • OS: [e.g. macOS, Windows, Linux]
    • Browser: [e.g. Chrome, Safari, Firefox]
    • Version: [e.g. 91.1]

    Additional context

    https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-disabled

    opened by asmadsen 2
  • mergeProps wrap functional sources in a memo. #1321

    mergeProps wrap functional sources in a memo. #1321

    wrap functional sources, provided to mergeProps() in a memo.

    <div {...functionalSource} />
    

    prevent "over calling" as shown in #1321, sources get evaluated 4 times on mounting alone.

    The memo guards the result of the function, and ensure user provided function is only called once, until a reactive trigger.

    Downsides:

    1. create a memo for every function source (more memory, overhead)
    2. double wrapping: if a source function is already a memo it will be wrapped too. (solid does not provide a way to introspect its primitives, to prevent that)

    fixes: #1321

    opened by LiQuidProQuo 4
Releases(v1.6.0)
  • v1.6.0(Oct 20, 2022)

    For the past months we've been working away at SolidStart and that has led to some incredible exploration into the realm of islands, partial hydration, and hybrid routing. Solid 1.6 backfills that into the core so that other Solid projects can benefit.

    We've also addressed a long-time issue with the proper merging of JSX spreads on native elements. When components don't re-execute dynamic spreads can one of the most complicated pieces to preserve granularity. Overall this is a smaller release but it represents a unique innovation into our vision of the future.

    Special thanks to @nksaraf and @rturnq work to guide exploration in these directions and contributions from @trusktr, @LiQuidProQuo, and @thetarnav

    Highlights

    Official Partial Hydration Support

    Solid has worked for quite some time in partial hydrated ("Islands") frameworks like Astro, Iles, Solitude, etc.. but now we have added core features to support this effort better. These features are mostly designed for meta-framework authors rather than the end user they are exposed through a couple APIs.

    <Hydration /> joins <NoHydration /> as being a way to resume hydration and hydration ids during server rendering. Now we can stop and start hydratable sections. This is important because it opens up a new optimization.

    createResource calls under non-hydrating sections do not serialize. That means that resources that are server only stay on the server. The intention is that hydrating Islands can then serialize their props coming in. Essentially only shipping the JSON for data actually used on the client. Reducing the double data problem significantly.

    The power here is static markup can interleave dynamic components.

    <h1>Server Rendered Header</h1>
    <Island>
      <h2>Server Rendered Sub Header</h2>
      <p>{serverOnlyResource().text}</p>
      <DifferentIsland>
        <p>More server-renderd content</p>
      </DifferentIsland>
    </Island>
    

    Keep in mind Server rendered content like this can only be rendered on the server so maintaining client navigation with this paradigm requires a special router that handles HTML partials.

    Similarly, we want the trees to talk to each other so hydrate calls now have been expanded to accept a parent Owner this will allow Islands to communicate through Contex without shipping the whole tree to the browser.

    <h1>Server Only Rendered Header</h1>
    <ClientProvider>
      <h2>Server Only Rendered Sub Header</h2>
      <ClientIslandThatReadsContext />
    </ClientProvider>
    

    These improvements make it easier to create Partial Hydration solutions on top of Solid, and serve to improve the capabilities of the ones we already have.

    Native Spread Improvements

    Native spreads are something we started at very naively. Simply just iterating an object that has some reactive properties and updating the DOM element. However, this didn't take into consideration two problems.

    First properties on objects can change, they can be added or removed, and more so the object itself can be swapped. Since Solid doesn't re-render it needs to keep a fixed reference to the merged properties. Secondly, these are merged. Properties override others. What this means is we need to consider the element holistically to know that the right things are applied.

    For Components, this was never a problem since they are just function calls. Unfortunately for native elements, this means all those compiler optimizations we do for specific bindings now need to get pulled into this. Which is why we avoided it in the past. But the behavior was too unpredictable.

    In 1.6 we have smartened spread to merge properly using a similar approach to how we process Components.

    // A`class` property in `props` now takes priority even if someSignal() updates.
    // In fact it won't even be subscribed to unless props does not have a `class` property.
    <div class={someSignal()} {...props} />
    

    We've also found new ways to optimize the experience. (See below).

    Other Improvements

    Deproxification

    Working on new Spread behavior we realized that while we can't tell from compilation which spreads can change. We can tell at runtime which are proxies. And in so if we only need to merge things that don't swap, and aren't proxies we can avoid making a Proxy.

    What is great about this is it has a cascading effect. If component props aren't a proxy, then splitProps and mergeProps don't need to create them, and so on. While this requires a little extra code it is a real win.

    We get a lot requests for low-end IoT devices because of Solid's incredible performance. In tests, Solid outperforms many of the Virtual DOM solutions in this space. However, most of them don't support proxies.

    So now if you don't use a Store or swap out the props object:

    // this is fine
    <div {...props} />
    
    // these could swap out the object so they make proxies
    <div {...props.something} />
    // or
    <div {...someSignal()} />
    

    We don't need to introduce any proxy the user didn't create. This makes Solid a viable option for these low-end devices.


    Note on the title

    Castle in the Sky was a landmark film for director Hayao Miyazaki, the first created at their newly formed studio, Studio Ghibli back in 1985. I found the imagery of floating Islands irresistible in the sense with our client-routed Islands it is like pulling them out of the water.

    A "Castle in the Sky" also refers to an idealistic, almost unrealizable goal. I think our isomorphic ambition of where we are taking things in frontend development feels like that sometimes. Attempting to keep aloft balancing the restrictions of the weight of JavaScript, the desire for interactivity, and the polish of experience seamlessly across both platforms immediately brings to mind these floating structures. A Solarpunk-esque return to our roots in server rendering with advanced technology that attempts to make itself invisible.

    So whether that is for you, Laputa, Skyloft, Zeal, Skypiea, Sanctaphrax, or some other, I wish you luck on your journey upwards.

    Best, @ryansolid

    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Aug 26, 2022)

    The last couple of months has been about looking toward the future. With Solid 1.0 clearly in the rearview, we are preparing for the possibility of Solid 2.0. We've started the working group to discuss new ideas and a lot of thought has been going into that future. At the same time, SolidStart, our new full-stack starter is getting closer to its initial reveal we've learned a lot about server rendering that has made it back into the core.

    We're very happy today to release the next version of Solid, thanks primarily to the contributions of @modderme123, @edemaine, @trusktr, @otonashixav, @lxsmnsyc, @LiQuidProQuo, @Drevoed, @nksaraf, @paoloricciuti, and @jorroll.

    Key Highlights

    New Batching Behavior

    Solid 1.4 patched a long-time hole in Solid's behavior. Until that point Stores did not obey batching. However, it shone a light on something that should maybe have been obvious before. Batching behavior that stays in the past is broken for mutable data. Solid only has createMutable and produce but with these sorts of primitives, the sole purpose is that you perform a sequence of actions, and batching this properly defies expectation. You wouldn't expect adding an element to an array and then removing another item to just skip the first operation, but that is proper behavior when values stay in the past.

    const store = createMutable(["a", "b", "c"]);
    
    const move = store.splice(1, 1);
    store.splice(0, 0, ...move);
    
    // solid 1.4
    // ["b", "a", "b", "c"];
    
    // solid 1.5
    // ["b", "a", "c"];
    

    After a bunch of careful thought and auditing, we decided that Solid's batch function should behave the same as how reactivity propagates in the system once a signal is set. As in we just add observers to a queue to run, but if we read from a derived value that is stale it will evaluate eagerly. In so signals will update immediately in a batch now and any derived value will execute on read. The only purpose of batch now is to group writes that begin outside of the reactive system, like in event handlers or async callbacks.

    More Powerful Resources

    Resources continue to get improvements. A common pattern in Islands frameworks like Astro is to fetch the data from the outside and pass it in. In this case, you wouldn't want Solid to do the resource fetching or the serialization on the initial server render, but you still may want to pass it to a resource so it updates on any change. For that to work reactivity needs to run in the browser. The whole thing has been awkward to wire up but no longer.

    ssrLoadFrom field lets you specify where the value comes from during ssr. The default is server which fetches on the server and serializes it for client hydration. But initial will use the initialValue instead and not do any fetching or additional serialization.

    const [user] = createResource(fetchUser, {
      initialValue: globalThis.DATA.user,
      ssrLoadFrom: "initial"
    });
    

    We've improved TypeScript by adding a new state field which covers a more detailed view of the Resource state beyond loading and error. You can now check whether a Resource is "unresolved", "pending", "ready", "refreshing", or "error".

    | state | value resolved | loading | has error | | ---------- | -------------- | ------- | --------- | | unresolved | No | No | No | | pending | No | Yes | No | | ready | Yes | No | No | | refreshing | Yes | Yes | No | | errored | No | No | Yes |

    A widely requested feature has been allowing Resources to be stores. While higher-level APIs are still being determined we now have a way to plugin the internal storage by passing something with the signature of a signal to the new Experimental storage option.

    function createDeepSignal<T>(value: T): Signal<T> {
      const [store, setStore] = createStore({
        value
      });
      return [
        () => store.value,
        (v: T) => {
          const unwrapped = unwrap(store.value);
          typeof v === "function" && (v = v(unwrapped));
          setStore("value", reconcile(v));
          return store.value;
        }
      ] as Signal<T>;
    }
    
    const [resource] = createResource(fetcher, {
      storage: createDeepSignal
    });
    

    Consolidated SSR

    This release marks the end of a several year long effort to merge async and streaming mechanisms. Since pre 1.0 these were separate. Solid's original SSR efforts used reactivity on the server with different compilations. It was easiest to migrate synchronous and streaming rendering and for a time async had a different compilation. We got them on the same compilation 2 years ago but the runtimes were different. Piece by piece things have progressed until finally async rendering is now the same code path as streaming if flushing was deferred until everything has completed.

    This means some things have improved across the board. Async triggered Error Boundaries previously were only ever client rendered (throwing an error across the network), but now if they happen any time before sending to the browser they are server-rendered. onCleanup now runs on the server if a branch changes. Keep in mind this is for render effects and not true side effects as not all rendering cleans up.

    Finally, we've had a chance to do a bunch of SSR rendering performance improvements. Improved raw string rendering by about 8% and replaced our data serializer with an early copy of @DylanPiercey from Marko's upcoming serializer for Marko 6 which boasts performance improvements of up to 6x over devalue which we used previously. Also, we streamlined asset and script insertion.

    Keyed Control Flow

    Solid's <Show> and <Match> control flows were originally re-rendered based on value change rather than truthy-ness changing. This allowed the children to be "keyed" to the value but led to over rendering in common cases. Pre 1.0 it was decided to make these only re-render when statement changed from true to false or vice versa, except for the callback form that was still keyed.

    This worked pretty well except it was not obvious that a callback was keyed. So in 1.5 we are making this behavior explicit. If you want keyed you should specify it via attribute:

    // re-render whenever user changes
    
    // normal
    <Show when={user()} keyed>
      <div>{user().name}</div>
    </Show>
    
    // callback
    <Show when={user()} keyed>
      {user => <div>{user.name}</div>}
    </Show>
    

    However, to not be breaking if a callback is present we will assume it's keyed. We still recommend you start adding these attributes (and TS will fail without them).

    In the future, we will introduce a non-keyed callback form as well so users can benefit from type narrowing in that case as well.

    Other Improvements

    children.toArray

    Children helper now has the ability to be coerced to an array:

    const resolved = children(() => props.children);
    resolved.toArray(); // definitely an array
    

    Better SSR Spreads

    Finally fixed spread merging with non-spread properties during SSR, including the ability to merge children.

    Better Error Handling

    We weren't handling falsey errors previously. Now when Solid receives an error that isn't an Error object or a string it will coerce it into an Unknown Error.

    Migrated the Repo to pnpm and TurboRepo

    Thanks @modderme123 for taking the time to completely modernize our build setup. Making it way easier to contribute and drastically improve build and testing performance.

    NodeNext Support

    TypeScript 4.7 brought a new way to use package exports to resolve Types and with Solid 1.5 we now support this.

    Improved Tagged Template Literals

    Many fixes have been made to Tagged Template literal parsing (special thanks @trusktr) fixing many rough edges.

    Improved CSS Types

    Solid now uses csstype for better typing of the style property.

    in support in Stores

    The in operator is now tracked and auto-wrapped in the JSX.

    Bug fixes

    Many small bug fixes, including:

    • fragment hydration mismatch
    • head/body elements included in templates
    • comparison functions not called with no observers
    • scheduling error in concurrent rendering
    • deletion on createMutable

    As always thanks to everyone involved who contributed, not only to the repos but the countless discussions across Github and Discord. Not everything ended up getting in this round and we had some difficult decisions like reviewing writing symbols to stores, and consistency of boolean attributes. Even if we landed on no change these discussions they served to re-enforce the good patterns we have in Solid today and gave a lot of insight into what we can do in the future.

    Sincerely, @ryansolid

    I apologize for the terrible pun

    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(May 12, 2022)

    This release has been a long time coming. 1.3 brought a ton of new features and a ton of new bugs that have been ironed out in the last couple of months. SolidHack also ran over this time where we got see people pushing the limits of what can be done. We've taken the feedback and applied it to our messaging, documentation, and our roadmap.

    v1.4 addresses some of these allowing people to do more with the features we already have. It may not have as many new toys to play with, but it makes significant improvements to how we use Stores, Resources, and Streaming.

    There also has been an incredible amount of work on TypeScript. So much so that I can't even include all the improvements in this post. Huge thanks goes out to @otonashixav, @trusktr, @edemaine, as well as review by @atk, @high1, and others to help see these landed.

    New Features

    Top Level Arrays in Stores

    Since Stores were first introduced it has always bugged me that the most common case, creating a list, required nesting it under a property to track properly. Thanks to some exploration into proxy traps and iteration we now support top-level arrays. In addition to its other modes, the Store setter will accept an array that allows for common operations.

    const [todos, setTodos] = createStore([
      { id: 1, title: "Thing I have to do", done: false },
      { id: 2, title: "Learn a New Framework", done: false }
    ]);
    
    // set at an index
    setTodos(1, done, true);
    
    // use an array
    setTodos([...todos, { id: 3, title: "New Todo", done: false }])
    
    // iterate over it with <For>
    <For each={todos}>{todo => <Todo todo={todo} />}</For>;
    

    Through this change, we also stopped over execution when listening to specific properties. To support iteration Solid previously would notify the owning object of an array when any index was added/removed or object when a new property was created or a property was deleted.

    The one caveat is downstream optimized control flow that untrack index reads on arrays will now need to track the iterated object explicity. Solid exports a $TRACK symbol used to subscribe to the object and all its properties.

    Resource Deferred Streaming

    Streaming brings a lot of performance benefits but it also comes with the tradeoff we need to respond with the headers before we can send any content. This means we must set the Response headers early if we want to benefit from streaming. While it's always possible to fetch first and delay rendering that slows down everything. Even our async server rendering doesn't block rendering but instead just waits to respond to the end.

    But what if you want to stream but also want to wait on some key data loading so you still have an opportunity to handle the response on the server before sending it to the browser?

    We now have the ability to tell Solid's stream renderer to wait for a resource before flushing the stream. That you can opt-in by setting deferStream option.

    // fetches a user and streams content as soon as possible
    const [user] = createResource(() => params.id, fetchUser);
    
    // fetches a user but only streams content after this resource has loaded
    const [user] = createResource(() => params.id, fetchUser, { deferStream: true });
    

    When this happens the stream and the response will be held allowing the server to process what it needs to before sending the status and streaming back the response. This is also valuable if there is some high-priority content that is worth waiting for before sending the response.

    Stale Resource Reads

    Suspense and Transitions are amazingly powerful features but occasionally you want to opt-out of the consistency and show things out of date because it will show up faster and some of the things you are waiting for are not as high priority. In so you want the Transition to end sooner, but not necessarily stop showing the stale data for part of the screen. It is still preferable to receding back to loading spinner state.

    Solid's Resources now support being able to read the value without triggering Suspense. As long as it has loaded previously latest property won't cause fallback to appear or Transitions to hold. This will always return the latest value regardless of whether it is stale (ie.. a new value is being fetched) and will reactively update. This is super powerful in Transitions as you can use the Resource's own loading state to know if it is stale. Since the Transition will hold while the critical data is loading, the loading state will not be applied to the in view screen until that Transition has ended. If the resource is still loading now you can show that it is stale.

    const [resource] = createResource(source, fetcher)
    
    // read it as usual
    resource();
    
    // read the latest (don't suspend if loaded at least once)
    resource.latest;
    

    Example: https://codesandbox.io/s/solid-stale-resource-y3fy4l

    Combining multiple Custom Renderers

    The Babel plugin now allows configuring multiple custom renderers at the same time. The primary case it is so a developer can still lever Solid's optimized DOM compilation while using their custom renderer. To make this work specify the tags each renderer is reponsible for. It will try to resolve them in order.

    import { HTMLElements, SVGElements } from "solid-js/web";
    let solidConfig = {
      moduleName: "solid-js/web",
      // @ts-ignore
      generate: "dynamic",
      renderers: [
        {
          name: "dom",
          moduleName: "solid-js/web",
          elements: [...HTMLElements, ...SVGElements]
        },
        {
          name: "universal",
          moduleName: "solid-three",
          elements: []
        }
      ]
    };
    

    Credit for this goes to @nksaraf who has been working on weaving Solid's optimal DOM compiler with a custom Three.js compiler.

    Improvements/Fixes

    Synchronous Top Level createEffect

    These were originally deferred to a microtask to resemble how effects are queued under a listener. However it is more correct to run immediately like everything else top level.

    Better Types around Components

    This one took the effort of many resident TypeScript experts, but we've now landed on some better types for components. The biggest change is Component no longer has an opinion on whether it should have children or not. We've added supplementary types ParentComponent and FlowComponent to denote Components that may have children or always have children. And we've added VoidComponent for those which may never have children.

    Sources in createResource are now Memos

    A small change but it was unusual to have refetching trigger a reactive expression outside of a reactive context. Now on refetch it grabs the last source value rather than re-running it.

    Better handling of null and undefined

    Spreads and classes in the JSX now handle these values without writing them as strings or throwing exceptions.

    createMutable batches array methods like push, pop, etc..

    Now these built-ins are batched and more performant. For instance using push or splice will only trigger updates once.

    We've also added modifyMutable that applies modifiers batched to stores created with createMutable.

    modifyMutable(state.data.user, reconcile({ firstName: "Jake", middleName: "R" }));
    

    Better Support for React JSX transform

    We have added support to solid-js/h to support the new React JSX transform. You can use it directly in TypeScript by using:

    {
      "jsx": "react-jsx",
      "jsxImportSource": "solid-js/h"
    }
    

    Keep in mind this has all the consequences of not using the custom transform. It means larger library code, slower performance, and worse ergonomics. If you use this remember to wrap your reactive expressions in functions.

    HyperScript now returns functions

    This one is a potentially breaking change, but the current behavior was broken in a different way. It was possible(and common) for children to be created before the parents the way JSX worked. This was an oversight on my original design that needs to be fixed, as it breaks context, and disposal logic. So now when you get your results back from h you need to call it. Solid's render function will handle this automatically.

    const getDiv = h("div", "Hello");
    
    document.body.appendChild(getDiv()); // call as a function to have it create the element.
    

    Special thanks to @fabiospampinato for identifying and bringing this long-standing issue to our attention.

    Removals and Deprecations

    className, htmlFor deprecated

    While they still work for now, Solid will remove support for these React-isms in a future version. They leave us with multiple ways to set the same attribute. This is problematic for trying to merge them. Solid updates independently so it is too easy for these things to trample on each other. Also when optimizing for compilation since with things like Spreads you can't know if the property is present, Solid has to err on the side of caution. This means more code and less performance.

    Experimental refetchResources removed

    This primitive ended up being too general to be useful. There are enough cases we can't rely on the refetch everything by default mentality. For that reason, we are dropping support for this experimental feature.

    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Jan 6, 2022)

    This release is a big one. It really focuses on improving Server Side Rendering. We add support for Streaming HTML, Isomorphic Error Boundaries, and Multiple Async Hydration Roots. We also made some small tweaks to resources to make it easier than ever to build powerful query caching solutions on top of them. And we have started experimenting with supporting even more types of reactivity.

    There are a lot of new features in this release many experimental. So feedback is very appreciated. There also are a few small API changes in this release to facilitate future features, so be sure to read the breaking changes below.

    New Features

    HTML Streaming

    This release adds support for HTML streaming. Now we not only stream data after the initial shell but the HTML as it finishes. The big benefit is that now for cached results or times when the network is slow, we no longer have to show the placeholder while waiting for the JavaScript bundle to load. As soon as the HTML is available it will be streamed and inserted.

    With it comes a new streaming API renderToStream. This is a universal API designed to handle both Node and Web writable streams. It returns an object that mirrors a Readable stream on both platforms that has both pipe (node) and pipeTo (web). The benefit of this pipe API is the user can choose when to insert the content in the output stream whether soon as possible, or onCompleteShell, or onCompleteAll. This decouples Solid's rendering from the stream a bit but leaves things open to performance improvements in the future.

    // node
    const stream = renderToStream(() => <App />).pipe(res);
    
    // web
    const stream = renderToStream(() => <App />).pipeTo(writable);
    

    Error Boundaries on the Server

    We've added support for Error Boundaries on the Server for all rendering methods(renderToString, renderToStringAsync, renderToStream). Errors can be caught both from synchronous rendering and from errors that happen in Resource resolution. However, Our approach doesn't guarantee all errors are handled on the server as with streaming it is possible that the Error Boundary has already made it to the browser while a nested Suspense component hasn't settled. If an Error is hit it will propagate up to the topmost Suspense Boundary that hasn't been flushed yet. If it is not handled by an Error Boundary before that it will abort rendering, and send the Error to the browser to propagate up to the nearest Error Boundary.

    This works now but there is more to explore here in improving Error handling in general with SSR. So look forward to feedback on the feature.

    Isolated Server Render/Hydration Contexts

    Sometimes you want to server render and hydrate multiple Solid apps on the same page. Maybe you are using the Islands architecture with something like Astro. We now have the ability to pass a unique renderId on all our server rendering methods and to the hydrate function. This will isolate all hydration and resource resolution. This means we can use things like server side Suspense in these solutions.

    Also now you only need to include the Hydration Script once on the page. Each Island will be responsible for initializing it's own resources.

    // on the server
    const html = renderToString(() => <Island1 />, { renderId: "island1" });
    
    // for the browser
    hydrate(() => <Island1 />, mountEl, { renderId: "island1" });
    

    createReaction

    This new primitive is mostly for more advanced use cases and is very helpful for interopt with purely pull based systems (like integrating with React's render cycle). It registers an untracked side effect and returns a tracking function. The tracking function is used to track code block, and the side effect is not fired until the first time any of the dependencies in the tracking code is updated. track must be called to track again.

    const [s, set] = createSignal("start");
    
    const track = createReaction(() => console.log("something"));
    
    // next time s changes run the reaction
    track(() => s());
    
    set("end"); // "something"
    
    set("final"); // no-op as reaction only runs on first update, need to call track again.
    

    This primitive is niche for certain use cases but where it is useful it is indispensible (like the next feature which uses a similar API).

    External Sources (experimental)

    Ever wanted to use a third party reactive library directly in Solid, like MobX, Vue Reactivity, or Kairo. We are experimenting with adding native support so reactive atoms from these libraries can be used directly in Solid's primitives and JSX without a wrapper. This feature is still experimental since supporting Transitions and Concurrent Rendering will take some more effort. But we have added enableExternalSource enable this feature. Thanks @3Shain for designing this solution.

    import { Reaction, makeAutoObservable } from "mobx";
    import { enableExternalSource } from "solid-js";
    import { render } from "solid-js/web";
    
    let id = 0;
    enableExternalSource((fn, trigger) => {
      const reaction = new Reaction(`[email protected]${++id}`, trigger);
      return {
        track: x => {
          let next;
          reaction.track(() => (next = fn(x)));
          return next;
        },
        dispose: () => {
          reaction.dispose();
        }
      };
    });
    
    class Timer {
      secondsPassed = 0;
    
      constructor() {
        makeAutoObservable(this);
      }
    
      increase() {
        this.secondsPassed += 1;
      }
    
      reset() {
        this.secondsPassed = 0;
      }
    }
    
    // component driven directly off MobX
    function App() {
      const timer = new Timer();
      setInterval(() => {
        timer.increase();
      }, 1000);
    
      return <button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>;
    }
    
    render(() => <App />, document.getElementById("app"));
    

    refetchResources (experimental)

    In efforts to allow for scaling from simple resources up to cached solutions we are adding some experimental features to createResource to work with library writers to develop the best patterns. Caching is always a tricky problem and with SSR and streaming being part of the equation the core framework needs at minimum to provide some hooks into orchestrating them.

    Sometimes it's valuable to trigger refetch across many resources. Now you can.

    import { createResource, refetchResources } from "solid-js";
    
    const userCache = {};
    
    function MyComponent(props) {
      const [data] = createResource(
        () => props.id,
        (userId, { refetching }) => {
          const cached = userCache[userId];
    
          // return cached value if available and not refetching
          if (cached && !refetching) return cached;
          return fetchUser(userId);
        }
      );
    }
    
    // somewhere else
    refetchResources();
    

    You can also pass a parameter to refetchResources to provide additional information to the refetching info of the fetcher. This could be used for conditional cache invalidation. Like only refetch resources related to users. This mechanism requires a bit of wiring but the idea is you'd wrap createResource in maybe a createQuery and implement your own conventions around resource cache management. Still working out how this should work best, but the goal is to provide the mechanisms to support resource caches without being responsible for their implementation.

    To opt-out being part of the global refetch createResource now takes a globalRefetch option that can be set to false. In addition to a new option to disable refetchResources there is no an onHydrated callback that takes the same arguments as the fetcher. When a resource is restored from the server the fetcher is not called. However, this callback will be. This is useful for populating caches.

    Improvements

    Better TypeScript Support

    Thanks to the tireless efforts of several contributors we now have significantly better types in Solid. This was a huge effort and involved pulling in maintainers of TypeScript to help us work through it. Thank you @trusktr for spearheading the effort.

    Better SourceMaps

    Work has been done to improve sourcemaps by updating babel-plugin-dom-expressions to better preserve identifiers from the JSX. Thanks to @LXSMNSYC for exploring and implementing this.

    Breaking Changes/Deprecations

    startTransition no longer takes callback as a second argument

    Instead it returns a promise you can await. This works better for chaining sequences of actions.

    const [start, isPending] = useTransition();
    
    start(() => doSomething()).then(() => allDone());
    

    Resource fetcher info object replaces getPrev

    To streamline API for refetch we are slightly updating the createResource:

    const [data] = createResource(sourceSignal, (source, { value, refetching }) => {});
    

    For those using existing 2nd argument:

    const [data] = createResource(sourceSignal, (source, getPrev) => {
      const value = getPrev();
    });
    
    // becomes
    const [data] = createResource(sourceSignal, (source, { value }) => {});
    

    Deprecating Legacy Streaming APIs

    pipeToNodeWritable and pipeToWritable are deprecated. They will still work for now with basic usage but some of the more advanced options didn't map over to the new APIs directly and have been removed. Move to using renderToStream.

    Bug Fixes

    • Fixed browser extensions modifying the head element breaking hydration.
    • Fixed reinserting <html> on hydration from document.
    • Fixed over-executing on multi-select with createSelector.
    • Fixed event delegation conflicting with document event listeners.
    • Fixed self owning source infinite recursion.
    • Fixed faulty treesplitting for hydration in client only render.
    • Fixed return type of preload on lazy components to always be a promise.
    • Fixed compile error with leading white space after opening tags when generating ssr.
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Oct 26, 2021)

    This release centers around the addition of the universal JSX transform and runtime generator to enable custom renderers. This opens up whole new worlds of possibility with the opportunity to support new platforms beyond the web.

    New Features

    Custom Renderers

    This release adds support custom renderers through a new "universal" transform. Solid now provides a sub module solid-js/universal that exports a createRenderer method that allows you to create your own runtimes. This will enable things like native mobile and desktop, canvas and webgl, or even rendering to the terminal. This is still new so very much looking for feedback.

    // example custom dom renderer
    import { createRenderer } from "solid-js/universal";
    
    const PROPERTIES = new Set(["className", "textContent"]);
    
    export const {
      render,
      effect,
      memo,
      createComponent,
      createElement,
      createTextNode,
      insertNode,
      insert,
      spread,
      setProp,
      mergeProps
    } = createRenderer({
      createElement(string) {
        return document.createElement(string);
      },
      createTextNode(value) {
        return document.createTextNode(value);
      },
      replaceText(textNode, value) {
        textNode.data = value;
      },
      setProperty(node, name, value) {
        if (name === "style") Object.assign(node.style, value);
        else if (name.startsWith("on")) node[name.toLowerCase()] = value;
        else if (PROPERTIES.has(name)) node[name] = value;
        else node.setAttribute(name, value);
      },
      insertNode(parent, node, anchor) {
        parent.insertBefore(node, anchor);
      },
      isTextNode(node) {
        return node.type === 3;
      },
      removeNode(parent, node) {
        parent.removeChild(node);
      },
      getParentNode(node) {
        return node.parentNode;
      },
      getFirstChild(node) {
        return node.firstChild;
      },
      getNextSibling(node) {
        return node.nextSibling;
      }
    });
    

    Working example here.

    Spreads Added to Solid's html

    It's been a long time coming but Solid's Tagged Template Literals now support element and component spreads using htm inspired syntax.

    html`<div ...${props} />`
    

    Fixes

    Dynamic Spreads now work on Components

    Previously spreads on components would only track property changes on bound objects and not when the whole object changed. This now works:

    <MyComponent {...getStuff()} />
    

    ClassList properly merges multiple classnames in the key

    It is common in libraries like Tailwind to apply multiple classes at the same time. There was an issue where true and false resolutions were cancelling each other out. This would only set text-sm.

    <div
      classList={{
        "px-2.5 py-1.5 text-xs": false,
        "px-3 py-2 text-sm": false,
        "px-4 py-2 text-sm": true,
        "px-4 py-2 text-base": false,
        "px-6 py-3 text-base": false
      }}
    />
    

    Consistent handling of HTMLEntities

    Things like &nbsp; used to render differently depending if in elements or components(or fragments). This has been made consistent across all three.

    Various improvements to Types and Transitions

    A lot of bugs from the last minor release were around Transitions that have been addressed. And as always Types have been gradually improving.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Aug 9, 2021)

    Expanding Solid's concurrency to include interruptible scheduling. Bug fixes around Types and around reactive execution order guarantees.

    New Features

    createUniqueId

    A universal id generator that works across server/browser.

    const id = createUniqueId();
    

    Note on the server this only works under hydratable components

    from

    A simple helper to make it easier to interopt with external producers like RxJS observables or with Svelte Stores. This basically turns any subscribable (object with a subscribe method) into a Signal and manages subscription and disposal.

    const signal = from(obsv$);
    

    It can also take a custom producer function where the function is passed a setter function returns a unsubscribe function:

    const clock = from(set => {
      const t = setInterval(() => set(1), 1000);
      return () => clearInterval(t);
    });
    

    Note: Signals created by from have equality checks turned off to interface better with external streams and sources.

    enableScheduling (experimental)

    By default, Solid's concurrent rendering/Transitions doesn't schedule work differently and just runs synchronously. Its purpose is to smooth out IO situations like Navigation. However, now you can opt into interruptible scheduling similar to React's behavior by calling this once at your program's entry. I've yet to see a realworld scenario where this makes a big difference but now we can do cool demos too and start testing it.

    startTransition

    Works like its counterpart in useTransition, this useful when you don't need pending state.

    import { createSignal, startTransition } from "solid-js";
    
    function App() {
      const [signal, setSignal] = createSignal("Howdy");
      function clickHandler(e) {
        startTransition(() => setSignal("Holla"));
      }
    
      /* ...stuff */
    }
    
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jun 28, 2021)

    Well, the time has come. We're happy to announce Solid 1.0. This is the culmination of 5+ years of work, but in another sense this is just the start. We have marked the APIs as stable(except for a couple that have (experimental) next to them, like SuspenseList). What started as a quest to show that reactivity still had it has become a fully-featured JavaScript UI Framework.

    While the 1.0 release doesn't bring behavior differences it does bring some breaking syntax changes. We've worked to make the simple Signals and our proxy objects have a more consistent API. And we've move the proxies out into their own sub module, renaming them from "State" to "Store". We feel this will reduce confusion and better reflect their purpose.

    There is only a single 1.0.0 release, the first major version, and I am so happy and thankful to be here. Everyone who has been instrumental in us getting here has my eternal gratitude. From those who were always ready with encouraging words, to the great group of contributors and core maintainers we've built up today.

    So thank you, and enjoy.

    Breaking Changes

    setSignal now supports function form

    While that in itself is a great new feature as you can do:

    const [count, setCount] = createSignal(0);
    
    setCount(c => c + 1);
    

    This promotes immutable patterns, lets you access the previous value without it being tracked, and makes Signals consistent with State.

    It means that when functions are stored in signals you need to use this form to remove ambiguity

    const [count, setCount] = createSignal(ComponentA);
    
    // Do this:
    setCount(() => ComponentB);
    
    // Don't do this as it will call the function immediately:
    setCount(ComponentB);
    

    https://github.com/solidjs/solid/blob/main/documentation/api.md#createsignal

    createState moved and renamed

    createState has been renamed to createStore and moved to solid-js/store. Also moved to solid-js/store: createMutable, produce, reconcile

    https://github.com/solidjs/solid/blob/main/documentation/api.md#createstore

    SSR Entry points

    renderToString and renderToStringAsync now only return their stringified markup. To insert scripts you need to call generateHydrationScript or use the new <HydrationScript> component.

    renderToNodeStream and renderToWebStream have been replaced with pipeToNodeWritable and pipeToWritable, respectively.

    https://github.com/solidjs/solid/blob/main/documentation/api.md#pipetonodewritable

    Options Objects

    Most non-essential arguments on reactive primitives are now living on an options object. This was done to homogenize the API and make it easier to make future additions while remaining backwards compatible.

    on

    No longer uses rest parameters for multiple dependencies. Instead, pass an array. This facilitates new option to defer execution until dependencies change.

    https://github.com/solidjs/solid/blob/main/documentation/api.md#on

    Actions renamed to Directives

    To remove future confusion with other uses of actions the JSX.Actions interface is now the JSX.Directives interface.

    https://github.com/solidjs/solid/blob/main/documentation/api.md#use___

    Source code(tar.gz)
    Source code(zip)
  • v0.26.0(Apr 10, 2021)

    This release is about finalizing some API changes on the road to 1.0. This one has one breaking change and not much else.

    Signals no longer always notify by default

    Solid's original behavior has been to always notify on signal change even if the value hasn't changed. The idea was to simulate stream behavior. However, this has some downsides:

    1. Inconsistent with State.. I made the decision to make state equality check by default, it is weird signals and memo's do not.
    2. More likely to hit infinite loops. Equality check naturally stops infinite loops in some cases. While infinite loops aren't good and code that produces them suspect, it is nice to keep things clean.
    3. It is consistent with other modern reactive libraries like MobX and Vue.

    The API has not changed. You can opt out of the default behavior by passing in your own comparator or false to the 2nd parameter of createSignal and the 3rd parameter of createMemo.

    My hope this is the last release before I start making 1.0 RC's. This one has big enough impact I want to get this out first. I imagine the remaining changes will be just syntax.

    Source code(tar.gz)
    Source code(zip)
  • v0.25.0(Mar 29, 2021)

    This release is about refining the the APIs as we approach the our release candidate for 1.0. And moving from master to main.

    Breaking Changes

    Resource API

    Minor difference to allow the first argument to be optional and support more features in the future. New full signature is:

    export function createResource<T, U>(
      fn: U | false | (() => U | false),
      fetcher: (k: U, getPrev: () => T | undefined) => T | Promise<T>,
      options?: { initialValue?: T }
    ): ResourceReturn<T>;
    

    3rd argument is now an options object instead of just the initial value. This breaking. But this also allows the first argument to be optional for the non-tracking case. Need a promise that only loads once? Don't have need to re-use the fetcher. Do this:

    const [data] = createResource(
      async () => (await fetch(`https://someapi.com/info`)).json()
    );
    

    on/onCapture

    These are an escape hatch for unusual events. Previously these were custom attributes but now they are namespaced like:

    <div on:someUnusualEvent={e => console.log(e.target)} />
    

    change main field to be node

    Now that we are supporting SSR for legacy(non-ESM) systems I need to use the main field to indicate a node env. We will be using the "browser" field for the client build in Solid. This straight up breaks Jest which doesn't respect that. I've created solid-jest to handle this.

    https://github.com/ryansolid/solid-jest

    New Features

    Namespace Types

    Types added for Namespace attributes. You probably won't need most of these because they are for more advanced usage. However to use them you need to extend the JSX Namespace:

    declare module "solid-js" {
      namespace JSX {
        interface Actions {  // use:____
    
        }
        interface ExplicitProperties { // prop:____
    
        }
        interface ExplicitAttributes { // attr:____
    
        }
        interface CustomEvents { // on:____
    
        }
        interface CustomCaptureEvents { // oncapture:____
    
        }
      }
    }
    

    Lazy component preload

    Lazy components now have a preload function so you can pre-emptively load them.

    const LazyComp = lazy(() => import("./some-comp"))
    
    // load ahead of time
    LazyComp.preload();
    

    Error Boundary reset

    Error boundaries now have the ability to reset themselves and try again. It is the second argument to the fallback.

    <ErrorBoundary fallback={(err, reset) => {
      if (count++ < 3) return reset();
      return "Failure";
    }}><Component /></ErrorBoundary>
    
    Source code(tar.gz)
    Source code(zip)
  • v0.24.0(Feb 4, 2021)

    This release is the start of the rework of the SSR solution. Consolidating them under a single method. Unfortunately, this one comes with several breaking changes.

    Breaking Changes

    Removed solid-js/dom

    It's been a few versions deprecated. It's gone.

    Updated Resource API

    Changed to more resemble SWR and React Query. Needed to remove createResourceStateso now need to use a getter over createResource to get same effect. See updated documentation.

    Change SSR render call signatures

    They now return results objects that include the generated hydration script. No more need to generate it separately. Also comes autowrapped in the script tag now.

    assignProps to mergeProps

    While you use them the same way mostly it no longer has Object.assign semantics and always returns a new object. This is important as in many cases we need to upgrade to a Proxy.

    Renamed getContextOwner to getOwner

    Removes confusion around context and consistent with new helper runWithOwner.

    Solid Element no longer uses State for props

    This reduces the size of the library especially for those not using state. It also should slightly increase performance as no need for deep nesting of proxies. It also makes things behave more consistently avoided unintended deep wrapping.

    Non-breaking Changes

    New non-reactive Async SSR

    I have now combined sync/streaming/async SSR into the same compiler output. To do so I have developed a new non-reactive Async SSR approach. After realizing how fast Solid renders, it occurred to me on the server we could do a much simpler approach if we were willing to re-render all content in Suspense boundaries. While that is some wasted work, compared to including the reactive system it's a killing.

    Increase SSR Performance

    Through reusing static strings in the template we reduce repeated creation costs. This small improvement can make 5-8% improvements where you have many rows.

    Event Delegation

    Solid is now being more strict on what events it delegates. Limiting to standard pointer/touch/mouse/keyboard events. Custom events will no longer be delegated automatically. This increases compatibility for Web Component users who don't compose their events. Non-delegated events will still work and binding array syntax with them.

    State getters no longer memos

    Automatic memos put some constraints on the disposal system that get in the way of making the approach flexible to hold all manner of reactive primitives. Some previous limitations included not being able to have nested getters. You can still manually create a memo and put it in a getter but the default will not be memoized.

    New Features

    children helper

    Resolves children and returns a memo. This makes it much easier to deal with children. Using same mechanism <Switch> can now have dynamic children like <For> inside.

    "solid" Export Conidition

    This is the way to package the JSX components to be compiled to work on server or client. By putting the "solid" condition the source JSX will be prioritized over normal browser builds.

    Bug Fixes

    • Top level primitive values not working with reconcile
    • Fix Dynamic Components to handle SVG
    • Rename potentially conflicting properties for event delegtion
    • Fixed State spreads to not loose reactiviy. Added support for dynamically created properties to track in spreads and helpers
    • TypeScript, always TypeScript
    Source code(tar.gz)
    Source code(zip)
  • v0.23.0(Dec 6, 2020)

    This release is mostly to support breaking change for TS users. JSX types no longer pollutes the global namespace. This means you need to update your projects to import it.

    For users TS 4.1 or above add to your tsconfig to have JSX types in all your TSX files:

    "compilerOptions" {
      "jsx": "preserve",
      "jsxImportSource": "solid-js",
    }
    

    Or mixing and matching? You can set JSX types per file using the pragma at the top of each file:

    /* @jsxImportSource solid-js */
    

    You can now import JSX types directly from Solid as neccessary:

    import { JSX } from "solid-js";
    

    For instance, to add a custom element you would:

    import { JSX } from "solid-js";
    
    declare module "solid-js" {
      export namespace JSX {
        interface IntrinsicElements {
          foo: CustomFooHTMLElementAttributes
        }
      }
    }
    
    Source code(tar.gz)
    Source code(zip)
  • v0.22.0(Nov 14, 2020)

    Unified Exports (Deprecation solid-js/dom)

    Solid now has streamlined exports for isomorphic development. This means from now on using solid-js/web instead of solid-js/dom. Based on compiler options it will swap out the appropriate packages for web. You should only ever import solid-js, solid-js/h, solid-js/html, and solid-js/web directly in your code.

    solid-js/web now exports an isServer field which indicates whether the code is executed for server rendering. This is constant in the respective packages meaning it can allow for powerful treeshaking/dead code elimination in final bundles even when used directly in end user code or 3rd party libraries.

    Dev Mode

    Aliasing solid-js to solid-js/dev links in a Dev mode for Solid. It's still a WIP process but it introduces some new APIs. First signals and state (and resources) have the ability to set a name for debug purposes as an options argument.

    We also export a serializeGraph method which will serialize all the signals below the executing context in the reactive graph.

    Finally there is a new globalThis._$afterUpdate hook that can be assigned that will be called after every render that can be used for tracking purposes.

    This is just the start but it is my intention to develop these features to allow for better HMR and DevTools.

    Note: If the libraries are not being pulled into your bundle and are treated as external you may need to alias solid-js to solid-js/dev in your bundler in order to use dev mode.

    Self contained HyperScript/Lit Modules

    We now ship the respective DOM expressions code. This makes it much easier to use directly from a CDN like Skypack. You literally can develop with Solid in the old school write it in notepad before npm was a thing sort of way.

    <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>
    

    Save this in a text file called "site.html" and double click it and instant Solid in your browser.

    renderToWebStream

    New renderToWebStream for synchronous SSR mode. This allows us to stream from things like Cloudflare Workers.

    createMutable

    New mutable state primitive. Useful for interopt with other libraries. We can use this potentially for things like Vue/MobX compat. Or when we need to interact with libraries that can't be aware of Solid's reactive system, yet we want to capture updates. It supports getters and setters.

    Use with caution as it can promote difficult to reason about code, anti-patterns, and unexpected performance cliffs. Keep in mind Vue and MobX care less about these inefficient patterns since they have a VDOM safety net. We do not. For advanced users only.

    const user = createMutable({
      firstName: "John",
      lastName: "Smith",
      get fullName() {
        return `${this.firstName} ${this.lastName}`;
      },
      set fullName(value) {
        const parts = value.split(" ");
        batch(() => {
          this.firstName = parts[0];
          this.lastName = parts[1];
        });
      }
    });
    console.log(user.fullName); // John Smith
    user.fullName = "Jake Murray";
    console.log(user.firstName); // Jake
    

    State Getter/Setters are now Wrapped

    Getters are now wrapped in createMemo and setters in batch. However, this introduces a new limitation that they can only be top level to have this behavior.

    State compatible with Prop Helpers

    You can now use state with assignProps and splitProps helpers.

    Removed DOM SSR

    No longer supporting hydratable DOM SSR in patched(ie... JSDOM) node environments. Use the standard SSR methods instead. Can still run Solid in JSDOM for things like Jest, but can't be used for isomorphic development.

    Source code(tar.gz)
    Source code(zip)
  • v0.21.0(Oct 18, 2020)

    Attribute and Prop changes

    We will now default to using Attributes where possible to be consistent. Solid is aiming to generally reflect the case insensitiveness of HTML. Custom Elements remain the one place that defaults to property setters on Dynamic elements.

    While TypeScript 4.2 is yet to be released, we are introduce attr, prop, use and style namespace directives. To allow more expressiveness in binding syntax.

    Other Changes

    • New on and onMount helpers
    • More performant SSR escaping
    • Lazy eval SSR Component props (fix SSR Context API)
    • Add support for SSR with Solid Styled Components
    • Fix Lit Dom Expressions style in Template tags
    • Fix JSX Types
    Source code(tar.gz)
    Source code(zip)
  • v0.20.0(Sep 25, 2020)

    Re-scheduling Reactivity.

    This release makes large changes to the Reactive System. Key changes are deferring createEffect to be after rendering and introducing createComputed do immediate reactive graph updates like loading async data.

    Concurrency

    In addition, the reactive model brings updates to Suspense and Transitions. Solid now has true concurrent rendering at a granular level. This mechanism does differ from React as it currently only supports a single future.

    createSelector

    New API to do delegated selection. Good for updating only the rows that change in large lists:

    const [selected, setSelected] = createSignal();
    const isSelected = createSelector(selected);
    
    return <For each={list()}>{
      item => <li class={isSelected(item.id) ? "selected" : ""}>{item.text}</li>
    }</For>
    

    This will only re-evaluate the class binding when the value equals the id passed in or if the previous value was that id. So 100 rows and only 2 executions (remove old, and set new). Optionally takes a comparison function so you can do things like multi-select as well.

    as prop in Styled Components

    Let's you override the element type in the view where used.

    Removed APIs

    afterEffects, createDependentEffect, and suspend have been removed as they no longer make sense with the new reactive system timing.

    Source code(tar.gz)
    Source code(zip)
  • v0.19.0(Aug 24, 2020)

    API Changes to support better SSR

    Breaking Changes:

    Set State

    Mutable form is no longer a default. It was strangely inconsistent as you could accidentally mutate in immutable forms. No indicator why it should behave differently and work. Increased the size of state for everyone and added performance overhead with additional proxy wrapping. Also it was based on returning undefined meaning function forms could never return undefined to blank a vlue. Solid has changed it into a state setter modifier produce after ImmerJS naming.

    // top level
    setState(produce(s => {
     s.name = "John"
    }));
    
    // nested
    setState('user', produce(s => {
     s.name = "John"
    }));
    

    Prop APIs

    After writing setDefaults, cloneProps, and about to introduce mergeProps it became clear we can do this all with a single assignProps helper. So the former has been removed and now we have:

    // default props
    props = assignProps({}, { name: "Smith" }, props);
    
    // clone props
    newProps = assignProps({}, props);
    
    // merge props
    assignProps(props, otherProps)
    

    It follows the same pattern as ES Object.assign adding properties to the first argument and returning it. Except this method copies property descriptors without accessing them to preserve reactivity.

    freeze & sample have been renamed

    These APIs never had the most obvious naming, borrowing from SRP and digital circuit concepts rather than common english. They are now batch and untrack respectively which better reflect their purpose. These are now deprecated and will be removed in next minor version.

    Resource API

    For better automatic hydration support it is prudent to change resource signatures to take functions that return promises rather than promises themselves. This factory function has a lot advantages. This allows the library to decide whether to execute it or not. In certain cases we can choose skipping creating the promise altogether. It also leaves the door open for things like retry.

    We use this mechanism to wire up streamed data from the server and automatic data hydration for resources rendered into the page in async SSR.

    SSR Improvements

    New experimental support for Suspense aware synchronous, asynchronous, and streaming SSR with hydration, progressive hydration, and automatic isomorphic data serialization. Completely removed what was there before with a simple static generator and more examples, so all existing projects using solid-ssr package will break with this release. This is a much better foundation, and I hope to build better things on top.

    New

    State Getters

    For convenience of passing derived values or external reactive expressions through Solid's state initializer you can now add getter's.

    const [state, setState] = createState({
      firstName: "Jon",
      lastName: "Snow",
      get greeting() { return `You know nothing ${state.firstName} ${state.lastName}` }
    });
    
    return <div>{state.greeting}</div>
    

    Control Flow

    Dynamic allows swapping Component dynamically.

    // element tag name
    const [comp, setComp] = createSignal("h1");
    
    <Dynamic component={comp()} {...otherProps} />
    
    // Component
    setComp(MyComp);
    

    ErrorBoundary catches uncaught downstream errors and shows a fallback.

    <ErrorBoundary fallback={<div>Something went terribly wrong</div>}>
      <MyComp />
    </ErrorBoundary>
    

    Portals render in the Head

    You can now render portals in the head with no additional div element.

    Multi-version detection

    Common hard to track issue with Solid is when multiple versions of the library are running on the same page. It breaks reactivity, and is sometimes difficult to notice. Solid now detects if a version has already been loaded at runtime and complains.

    Bug Fixes & Updates

    Arguably a new feature but Solid now detects computation owners with pending dependency changes when trying to resolve nested computations. In so it will resolve those dependencies first. This fixes a long time issue with conditional processing with not directly related reactive atoms.

    Improved TypeScript Types.

    Source code(tar.gz)
    Source code(zip)
  • v0.18.0(May 2, 2020)

    A lot of bug fixes, and introduction of string based SSR. Breaking Changes:

    • Removal of forwardRef. Value and function handled by just ref.
    • Change to how TypeScript is managed. Brought all JSX types inside the repo, and improved Component typing.
    • Changed default renderer in solid-ssr to string renderer.
    • Change inline styles to use setProperty and hyphenated or camelCase.

    Lots of small bug fixes.

    Source code(tar.gz)
    Source code(zip)
  • v0.17.0(Mar 25, 2020)

    Consolidation in preparation for release candidate

    • Big refactor of core reactive system and render list reconciler
      • Significantly smaller reducing core by atleast 3kb minified
    • Better handling of nested reactive nodes in Fragments
    • Update SSR mechanisms, added progressive event hydration, created repo for SSR environment (solid-ssr)
    • @once compiler hint to statically bind values
    • Better wrapping hueristics for booleans and ternaries in JSX

    Breaking Changes

    • Removed transform prop from control flow. Idiomatic approach is to make a HOC for transformations of this nature.
    • Removed selectWhen/selectEach control flow transforms.
    • Changed event system
      • on____ prop to stop differentiating on case. Super confusing.Instead will try to delegate unless unable. Made TypeScript all CamelCase (although technically both forms behave identically)
      • Removed model event delegation approach. Instead to create bound event use array: onClick={[handler, row.id]}. Inspired by Inferno's linkEvent helper.
      • Renamed events prop to on prop
      • Added onCapture prop for capture events
    Source code(tar.gz)
    Source code(zip)
  • v0.16.0(Jan 15, 2020)

    Big changes to experimental features:

    • New resource API createResource and createResourceState to replace loadResource. These are built to prioritize read capabilities and simplify implementation.
    • Support for Async SSR renderToString now returns a promise. Uses Suspense to know when it is done.
    • Progressive Hydration with code splitting support. Ability to track events and replay as hydration completes to reduce "uncanny valley". Components can be lazily loaded even during hydration. No support for async data on hydration yet, so render it from server and load into state synchronously.
    • New error boundary api with onError. If an error occurs in context or child context the nearest handler/s will be called.
    • Deprecating the force setState modifier as it is confusing.
    Source code(tar.gz)
    Source code(zip)
  • v0.15.0(Dec 17, 2019)

    A lot fixes and new features:

    • Suspense improvements: SuspenseList, useTransition, trigger on read. Update API, and added reload and retry capability. Removed need for awaitSuspense by making Show and Switch control flows Susepnse aware.
    • Sample all Components. No more fear of nesting Components in JSX expressions. Top level in a Component will always be inert now.
    • Support for safe boolean and logical operators. This allows for the same optimization as the Show control flow for simple inline JSX conditionals like <div>{state.count > 5 && <MyComp />}</div>.
    • Support for non-curried operator forms. All operators now support an accessor first form as well as the functional curried form. Ex map(() => state.list, item => item)
    • Fix issues with spreading over children props.
    • Better Type Definitions.
    Source code(tar.gz)
    Source code(zip)
  • v0.14.0(Nov 17, 2019)

    v0.14.0 brings changes to the render runtime and setState API

    • Adds diffing to batched computations to improve update performance
    • Supports support for mutable(TypeScript safe) setState API inspired by Immer. Function setters in Solid now pass a mutable version of state. Modifying will schedule updates. This form must not return a value. It can still be used immutably simply by returning the new value.
    • Changes how force and reconcile helpers work. They can now be used on nested paths.
    • Removes support for multi-path setState.
    Source code(tar.gz)
    Source code(zip)
  • v0.13.0(Oct 28, 2019)

    v0.13.0 contains large changes to the reactive system and compiler.

    The main update is to simplify reactivity by removing computation recycling. While this was a useful feature to avoid unnecessary computation nodes, Solid now uses batching as a different approach to get similar results. Most templating libraries can offer breakneck update speeds without fine-grained updates. The real cost of these top-down approaches is the need to redo structural reconciliation. The current approach is that different computations will be created for each:

    • Dynamic insert expression (any expression between tags)
    • Spread operator
    • JSX template entry point(Top level tag, Fragment, or Component Children)

    To aid in performance simple text inserts the textContent binding is now optimized so they can be batched.

    In addition, there are some improvements to template cloning and SVG handing in SSR.

    Source code(tar.gz)
    Source code(zip)
  • v0.12.0(Oct 18, 2019)

    v0.12.0 contains a breaking change to the reactive rendering system

    • Removal of explicit dynamic binding {( )}, bindings will default to reactive unless impossible to be so (literal, function declaration, simple variable)
    • SVG Camelcase attribute Support
    • Prettier now supported!
    Source code(tar.gz)
    Source code(zip)
  • v0.11.0(Sep 27, 2019)

    v0.11.0 continues to add updates to the reactive system as well as some new features:

    • Fix reactivity resolution ordering on downstream conditionals
    • Add basic (non-namespaced) SVG support
    • Add experimental Server Side Rendering and Client Side Hydration capabilities
    • Add Suspense aware control flow transformation (awaitSuspense)
    • Allow state objects to track functions
    • More TypeScript definition improvements and fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Aug 12, 2019)

    v0.10.0 makes significant changes to the reactive system. Key updates:

    • Fixed synchronicity on all hooks/control flows.
    • Adds the ability to use comparators on createMemo.
    • Fixes bugs with nested control flows.
    • Fixes bugs with Suspense.
    • Update Suspense delayMs to maxDuration to match React. (Usage of maxDuration still experimental)
    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Jul 20, 2019)

    This is a big one. It includes the Control Flow Refactor described in #42. It brings Solid up to date with the latest version JSX DOM Expressions. Read the release notes here. What this means:

    • Optimized List reconciliation is exposed for any array passed as child nodes. This includes Fragments which are now also just arrays. This addresses issues like #37. One side effect is that dynamic bindings are not activated until attached and are made inert when detached. If you need to maintain context I suggest wrapping in a createMemo so that the value is remembered between inserts.
    • Solid ships with Control Flow operators. However, you are not limited to them. While you should be conscious of wasted work, you can use any Components/functions to handle control flow. The control flow operators are much simpler now since they are independent of DOM manipulation.
    • To support purely Reactive array iteration I reintroduced the map operator. I've added pipe and reduce as well. These are very basic but can serve as a basis for users to create Functional operators. They are in the same vein as RxJS pipe-able operators.
    • The return type from JSX may be a Node, Function, or Array of those. Since not all JSX expressions return Nodes anymore the top level now needs to use insert from solid-js/dom instead of just appending the returned element. solid-js/dom now exports render for convenience which does both the insert and automatically wraps it with createRoot. This syntax is based on React's render.
    • While still not perfect, some big improvements to TypeScript support, by removing both Custom Directives (use forwardRef binding instead) and <$> tag. New Control Flow also now has explicit type defs. JSX Children are now handled consistently with react.
    • Newly released is also babel-preset-solid. This will take care of all the Solid specific configuration for the JSX plugin making it easier than ever to get started.

    There have been several small changes, but those are the highlights. Bear with me as I update all the examples over the next few days.

    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Jun 15, 2019)

    v0.8.0 brings further improvements in reducing bundle size and optimizations in reactivity. New Features:

    • Universal loadResource API
    • afterEffects hook
    • Switch Control Flow
    Source code(tar.gz)
    Source code(zip)
  • v0.7.2(May 27, 2019)

    This release fully internalizes the reactive library in Solid. This will allow further optimizations in the future as well as reducing generated bundle size even further. This release also fixes several bugs around using Context API's with Solid Element.

    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(May 25, 2019)

    v0.7.0 brings further improvements in tree shaking, Context API including Provide control flow, and suspense helpers for loading Async Components and Data. Introducing:

    • lazy: use this to lazy import Components
    • loadResource: use this to fetch any async source
    • createContext: to register a Context type to be use with Provide and useContext
    • useContext to use a context provided via the Provide control flow
    • setDefaults: sets default props for your components

    There is also performance improvements where the number extraneous placeholder DOM nodes has been reduced improving cloning and traversal time.

    This is a breaking change as in order to support this version, Solid has forked S.js the underlying library and now ships with it built in. This means Solid will no longer be compatible other S.js libraries. It is a turning point but enables the powerful new features.

    In terms of API there is also a breaking change, where if you wish to specify dependencies for an effect use createDependentEffect. createEffect now has the same signature as createMemo where the second argument is a default value.

    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(May 7, 2019)

    Solid is smaller than ever!

    v0.6.0 brings a Tree Shakeable runtime. This means when Solid used with JSX the compiler can intelligently only include the code that is being used.

    This is a breaking change in that:

    • No longer need to import 'r' and selectWhen and selectEach directives have been moved to solid-js from solid-js/dom. You should not need to import from 'solid-js/dom' directly anymore as your compiled code will do it automatically.
    • HyperScript and Lit imports have been made the default import now.. ex:
    import html from 'solid-js/html'
    
    • Tidied up the compiled template code. This should make it much nicer to debug when not minified.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Apr 29, 2019)

    Migration to TypeScript.

    Thank you @neodon and @r0skar for helping out on this one. This is still early days for TypeScript implementation so looking for review and improvements.

    Source code(tar.gz)
    Source code(zip)
Owner
Ryan Carniato
Ryan Carniato
:fire: An extremely fast, React-like JavaScript library for building modern user interfaces

Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server. Description The main obje

Inferno 15.6k Nov 24, 2022
A declarative, HTML-based language that makes building web apps fun

A declarative, HTML-based language that makes building web apps fun ?? Docs βˆ™ Try Online βˆ™ Contribute βˆ™ Get Support Intro Marko is HTML re-imagined as

Marko 11.9k Nov 23, 2022
Tiny (2 KB) turboboosted JavaScript library for creating user interfaces.

Develop web applications with 100% JavaScript and web standards. ?? RE:DOM is a tiny (2 KB) UI library by Juha Lindstedt and contributors, which adds

RE:DOM 3.2k Nov 28, 2022
πŸŒ™ The minimal & fast library for functional user interfaces

Moon The minimal & fast library for functional user interfaces Summary ?? Small file size (2kb minified + gzip) ⚑ Blazing fast view rendering ?? Purel

Kabir Shah 6k Nov 20, 2022
jCore - JavaScript library for building UI components

JavaScript library for building UI components

iOnStage 11 Jan 21, 2022
πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

Supporting Vue.js Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome ba

vuejs 200.9k Nov 26, 2022
πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

vue-next This is the repository for Vue 3.0. Quickstart Via CDN: <script src="https://unpkg.com/[email protected]"></script> In-browser playground on Codepen S

vuejs 33.8k Nov 23, 2022
Relay is a JavaScript framework for building data-driven React applications.

Relay Β· Relay is a JavaScript framework for building data-driven React applications. Declarative: Never again communicate with your data store using a

Facebook 17.4k Nov 29, 2022
A JavaScript Framework for Building Brilliant Applications

mithril.js What is Mithril? Installation Documentation Getting Help Contributing What is Mithril? A modern client-side JavaScript framework for buildi

null 13.5k Nov 24, 2022
A Web Component compiler for building fast, reusable UI components and static site generated Progressive Web Apps

Stencil: A Compiler for Web Components and PWAs npm init stencil Stencil is a simple compiler for generating Web Components and static site generated

Ionic 11.2k Nov 26, 2022
The tiny framework for building hypertext applications.

Hyperapp The tiny framework for building hypertext applications. Do more with lessβ€”We have minimized the concepts you need to learn to get stuff done.

Jorge Bucaran 18.9k Nov 24, 2022
🐰 Rax is a progressive React framework for building universal application. https://rax.js.org

Rax is a progressive React framework for building universal applications. ?? Write Once, Run Anywhere: write one codebase, run with Web, Weex, Node.js

Alibaba 7.8k Nov 26, 2022
πŸ™Œ Check if a Discord user is sponsoring you/someone on GitHub and give them roles!

Discord: Is User Sponsor? A bot that gives roles if a user is supporting you on GitHub! Uses Discord OAuth and Discord GitHub integration to get user'

EGGSY 18 Jun 27, 2022
KioskBoard - A pure JavaScript library for using virtual keyboards.

KioskBoard - Virtual Keyboard A pure JavaScript library for using virtual keyboards. Current Version 2.0.0 * Documentation and Demo https://furcan.git

Furkan MT 170 Nov 21, 2022
A JavaScript UI Library with JQuery like syntax

A JavaScript UI Library with JQuery like syntax. (Beta)

Sijey 5 Jan 16, 2022
Simple and elegant component-based UI library

Simple and elegant component-based UI library Custom components β€’ Concise syntax β€’ Simple API β€’ Tiny Size Riot brings custom components to all modern

Riot.js 14.7k Nov 30, 2022
ENS Avatar resolver library for both nodejs and browser.

ens-avatar Avatar resolver library for both nodejs and browser. Getting started Prerequisites Have your web3 provider ready (web3.js, ethers.js) [Only

Ethereum Name Service (ENS) 26 Nov 22, 2022
Our original Web Component library.

Polymer ℹ️ Note: This is the current stable version of the Polymer library. At Google I/O 2018 we announced a new Web Component base class, LitElement

Polymer Project 21.9k Nov 28, 2022
πŸ™‹β€β™€οΈ 3kb library for tiny web apps

3kb library for tiny web apps. Sometimes, all you want to do is to try and do somethingβ€”No boilerplate, bundlers, or complex build processes. Lucia ai

Aiden Bai 689 Nov 23, 2022