solidjs / solid-start

SolidStart, the Solid app framework
https://start.solidjs.com
MIT License
5.05k stars 377 forks source link

[Bug]: Unable to import Soild's `html` function in Solid Start app #1618

Open trusktr opened 2 weeks ago

trusktr commented 2 weeks ago

Duplicates

Latest version

Current behavior 😯

More details here:

https://github.com/solidjs/solid/issues/1984

Expected behavior 🤔

All of Solid's packages, including solid-js should be importable in Solid Start.

Steps to reproduce 🕹

Steps:

  1. npm create solid and follow steps to create a Solid app
  2. Add import html from 'solid-js/html' to any JS or TS file.
  3. Try to run the app and see the error

Context 🔦

Some components, for example 3rd party components, might be importing Solid's html. It would be great for a Solid app with SSR enabled to not have an issue importing such code (there will be more problems to wrangle after importing such as running certain components only on the client, but that's a next step after first getting imports working).

Fixed by

Your environment 🌎

No response

trusktr commented 2 weeks ago

Working towards fixing this here:

trusktr commented 2 weeks ago

I've confirmed after linking modified solid-js including this change into a Solid Start app that I'm able to progress towards normal import statements.

Even if I'm not calling html on the server side, the app is a lot cleaner being able to hoist import statements out of components or conditional top-level awaits.

trusktr commented 2 weeks ago

Having normal import statements makes things really easy in VS Code too, for example VS Code will autocomplete import statements for anything that you need to import, which is super convenient.

For example write this code (with | representing the cursor location):

createEff|

and VS Code will propose to import createEffect from solid-js, etc. So it will be great for all APIs to be conveniently importable.

The html export from solid-js/html is not currently named, so VS Code will not autocomplete the import for html. Fix for that here:

VS Code will not automatically add await import() expressions, so when someone autocompletes an import statement, it'll go to the top of the file, then they have to manually move that into their conditional or onMount.

trusktr commented 2 weeks ago

Oh my goodness.... YES!

https://github.com/ryansolid/dom-expressions/pull/345 cleans up my Solid Start modules that import lume.

For example I had this ugly code,

ugly code

```ts import {batch, createSignal, onCleanup, onMount} from 'solid-js' ...normal imports... export type TiltCardAttributes = Element3DAttributes | 'rotationAmount' | ... // Solid Start import issue: https://github.com/solidjs/solid-start/issues/1614 if (globalThis.window?.document) await defineElement() async function defineElement() { const {default: html} = await import('solid-js/html') const {Element3D, Motor, stringAttribute, numberAttribute, booleanAttribute} = await import('lume') const {autoDefineElements} = await import('lume/dist/LumeConfig.js') return @element('lume-tilt-card', autoDefineElements) class TiltCard extends Element3D { @numberAttribute rotationAmount = 12 ..etc.. override template = () => { let plane: Element3D const state = createMutable({...}) ... return html` (plane = e)} ... > ... ` } } } // Temporary hack type to get around the async defineElement() workaround type TiltCardCtor = Awaited> export type TiltCard = InstanceType declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'lume-tilt-card': ElementAttributes } } } declare global { interface HTMLElementTagNameMap { 'lume-tilt-card': TiltCard } } ```

Which as you can imagine, gets worse when trying to define more than one custom element in a single file (with JSX types for type checking in Solid components), for example:

even worse code

```ts // ...normal imports... export type ScrollerAttributes = Element3DAttributes | 'scrollX' | 'scrollY' | ... export type ScrollItemAttributes = Element3DAttributes | 'skip' if (globalThis.window?.document) await defineElement() async function defineElement() { const {default: html} = await import('solid-js/html') const {Element3D, ScrollFling, booleanAttribute} = await import('lume') const {autoDefineElements} = await import('lume/dist/LumeConfig.js') @element('lume-scroll-item', autoDefineElements) class ScrollItem extends Element3D { @booleanAttribute skip = false } @element('lume-scroller', autoDefineElements) class Scroller extends Element3D { override readonly hasShadow = true @booleanAttribute scrollX = true @booleanAttribute scrollY = true ... override template = () => html` ... ` } return [Scroller, ScrollItem] as const // <----------------------------- HACK } type ScrollerCtor = Awaited>[0] // <----------------------------- HACK export type Scroller = InstanceType declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'lume-scroller': ElementAttributes } } } declare global { interface HTMLElementTagNameMap { 'lume-scroller': Scroller } } type ScrollItemCtor = Awaited>[1] // <----------------------------- HACK export type ScrollItem = InstanceType declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'lume-scroll-item': ElementAttributes } } } declare global { interface HTMLElementTagNameMap { 'lume-scroll-item': ScrollItem } } ```

The code is now much cleaner with normal imports thanks to https://github.com/ryansolid/dom-expressions/pull/345:

clean code

```ts // ...normal imports... import html from 'solid-js/html' import {element, type ElementAttributes, booleanAttribute} from '@lume/element' import {type Element3DAttributes, Element3D, ScrollFling} from 'lume' import {autoDefineElements} from 'lume/dist/LumeConfig.js' export type ScrollItemAttributes = Element3DAttributes | 'skip' @element('lume-scroll-item', autoDefineElements) class ScrollItem extends Element3D { @booleanAttribute skip = false } declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'lume-scroll-item': ElementAttributes } } } declare global { interface HTMLElementTagNameMap { 'lume-scroll-item': ScrollItem } } export type ScrollerAttributes = Element3DAttributes | 'scrollX' | 'scrollY' | ... @element('lume-scroller', autoDefineElements) class Scroller extends Element3D { override readonly hasShadow = true @booleanAttribute scrollX = true @booleanAttribute scrollY = true ... override template = () => html` ... ` } declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'lume-scroller': ElementAttributes } } } declare global { interface HTMLElementTagNameMap { 'lume-scroller': Scroller } } ```