TIL - How to write a web component with SolidJS

Search for a command to run...

Thanks for this Guide! The CSS import didn't work for me. If anyone has the same issue, I could resolve it by attaching "?inline" to the import:
import styles from "./MyComponent.css?inline";
As a React developer, I never really questioned React's approach to reactivity. But I recently discovered two other frameworks: SolidJS and Svelte. Both frameworks have in common to not rely on a virtual DOM and to offer, what I call, “opt-in reactiv...
And when do we need them?

And why would you do that?

In modern Front-End development, it is well known you should never use an HTML table to achieve your page layout. That doesn't mean you must not use the table value from the display CSS property. About display: table; The behavior of the display: ta...

Today, I wanted to test the library: SolidJS. It features JSX support and is known for its great performance.
The first step I did was to follow the Getting Started guide and start from a given template:
> npx degit solidjs/templates/ts my-app
> cd my-app
> npm i
I removed all content from src/ folder and created an empty index.ts.
This file will serve as an entry point for the lib.
In vite.config.ts, I added the lib configuration:
export default defineConfig({
plugins: [solidPlugin()],
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
name: 'my-component',
fileName: (format) => `my-component.${format}.js`
},
// ...
},
});
With the lib property, Vite provides a way to bundle a library from the given entry point.
This library mode still gives you access to the demo page with npm run start.
I then created a file for my component.
// src/MyComponent.tsx
const MyComponent: Component<Props> = (props) => {
return <> {/*...*/} </>;
}
And I did not export the component like I am used to with react, but I rather registered it with the customElement helper from the solid-element module.
The
solid-elementis a separate module that needs to be installed.
// src/MyComponent.tsx
import { customElement } from "solid-element";
/* ... */
customElement("my-component", { someProp: "defaultValue" }, MyComponent)
The custom customElement helper works by giving the module a tag name (e.g. "my-component") and binding it to your component (e.g. MyComponent).
You need to pass as a second argument the default props values. Omitting this object prevents the props from receiving data from their corresponding attribute (e.g.
some-propattribute should bridge data tosomePropprop).
Vite allows writing css-modules files (e.g. MyComponent.module.css) in order to scope the style to a specific component. Because of the Shadow DOM, styles written in the web component are scoped to the web component by default. That means, in this case, I do not need to rely on the css-modules feature.
In order to add style to my component, I wrote a standard CSS file and import it into the component file.
import styles from "./MyComponent.css";
The styles object is the actual styles string and can be embedded into the web component using the <style> tag.
const MyComponent: Component<Props> = (props) => {
return <>
<style>{styles}</style>
{/*...*/}
</>;
}
Because class names are kept untouched by Vite, I can add class names as I would normally do in an HTML markup:
<div class="myComponent" />
After setting up my component, I imported the component file in the index.ts file.
// src/index.ts
import "./MyComponent.tsx";
I then added the custom web component in the markup of the index.html file (Vite's "demo" page).
<body>
<my-component some-prop="someValue">
</body>
Everything looked fine. I then built the lib (npm run build) and got three files.
style.css: can be ignored because style is also embedded in the JS.my-component.es.js: the ES module output JSmy-component.umd.js: the universal module output JSBoth modules seem to work fine when imported into an HTML document, but the UMD is way smaller because minified.
This process is quite straightforward once you know what needs to be configured. I think it is a good starting point, for me, to learn SolidJS and to dip a toe in the web components world.