solidjs / solid-docs

SolidJS Docs.
https://docs.solidjs.com/
228 stars 276 forks source link

Development solid export condition #391

Closed thetarnav closed 9 months ago

thetarnav commented 1 year ago

How should library authors set up export conditions to have separate entries for dev and prod? I'm making a tsup preset that would automatically configure those when building a library, this is just the last part that isn't working quite right.

This configuration works in the vite templates. dev.jsx is loaded in development and index.jsx in production when building. But In solid-start the dev.jsx entry is taken in both cases.

Having a separate entry for the server works without issues though.

{
  "solid": {
    "development": "./dist/dev.jsx",
    "import": "./dist/index.jsx"
  },
  "development": {
    "import": {
      "types": "./dist/index.d.ts",
      "default": "./dist/dev.js"
    }
  },
  "import": {
    "types": "./dist/index.d.ts",
    "default": "./dist/index.js"
  }
}
ryansolid commented 1 year ago

That is strange to say the least. I wouldn't expect a development condition showing up in prod. I believe the only place we touch this is in the vite-plugin-solid. https://github.com/solidjs/vite-plugin-solid/blob/master/src/index.ts#L327.. and in the adapters which definitely don't include "development"

thetarnav commented 1 year ago

If I switch the order of conditions (prod above dev), the prod entry is taken both in dev and prod in SolidStart. I believe I was using the default node adapter.

ryansolid commented 1 year ago

I've noticed rollup node resolve plugin is kinda broken in the last 2 major versions.. can you check what version you are on. 13 seems fine. 14/15 not so much.

thetarnav commented 1 year ago

You're right. Overriding @rollup/plugin-node-resolve dependency to 13.3.0 fixed it. Solid exports are used accordingly in development/server/production.

ryansolid commented 1 year ago

Yeah something is really broken here just don't know what.

apatrida commented 1 year ago

Seems like ark-ui is giving up on solid-start for now due to something related to this issue.
https://github.com/chakra-ui/ark/issues/1363

ryansolid commented 11 months ago

In setting up for SolidStarts next Beta Phase built on Nitro and Vinxi we are closing all PRs/Issues that will not be merged due to the system changing. If you feel your issue was closed by mistake. Feel free to re-open it after updating/testing against 0.4.x release. Thank you for your patience.

See https://github.com/solidjs/solid-start/pull/1139 for more details.

ryansolid commented 11 months ago

I'm going to transfer this one to docs instead. General how to make a package for SSR is good thing to have.

trusktr commented 11 months ago

The Node.js exports thing something to avoid (imo) because it is not part of the ES Module standard. I avoid it altogether, and find other means to do dev vs prod (f.e. set env vars, give devs the tools to configure whether their build will compile out the branches or not, but by default leave the branches in and don't shipped multiple formats of the code stripped and non-stripped).

They are not out in Node.js yet, but standard importmaps are a lot better because:

  1. end app author has full control of dependencies.
    • issues like node module resolution accidentally placing two versions of Solid into a bundle are easy to solve explicitly when using importmaps
    • wrong dist vs prod file being imported is no issue (the app author makes that choice)
    • individual files inside any package can be mapped to alternative implementations, etc.
  2. import maps will work everywhere, in a standard way (see the Node.js import maps tracking issue which is an important item on the loaders to-do list).
    • when Node comes out with importmaps, they will likely become supported as a standard by all build tools (tools like Webpack, etc, currently understand exports, but not import maps)

With import maps, users will be able to opt into dev vs prod in a more explicit way. This will be great because the current automatically-try-to-guess method embedded in the tooling can leave people stuck and feeling out of control when issues like that one from Chakra happen, especially in the many possible use cases for Solid.js outside of components (f.e. server apps, data manipulation, state management libraries, etc, where SSR, loading mock APIs, dev vs prod, etc, may not be concerns and these roadblocks get in the way of doing great things).

Here's a sample of importmap flexibility, where we can override a specific file from a package with another:

https://codepen.io/trusktr/pen/KKEPGYB?editors=1010

Keep an eye out for Node import maps, because this is something we should align with!

In the meantime, besides the above, this this 160-line-long exports field monster is a problem (in my opinion):

https://github.com/solidjs/solid/blob/51c94859098170c913c02a0fe1d9003d1664d130/packages/solid/package.json#L46-L206

If I could make the choice, it would be deleted, and Solid would ship vanilla standard ES modules, and then Solid would build the tooling around that instead of around Node.js, making Solid easily portable and more interoperable.

Building around Node.js is locking into non-standard ways of doing things that will not progress forward very well, especially for a library that is a client-side library, unlike Node.js packages that are intended for Node.js runtime only. The exports field is designed specifically for Node.js runtime libraries, and relying on this for a mostly-browser library is just not ideal.

The future is libraries/frameworks that simply work based on standards that are buildless-first, without any issues like the Chakra issue, but that have opt-in tooling to achieve what is needed (f.e. prod vs dev, srr vs client, etc).

I highly recommend (highly wish) for Solid.js to become as vanilla as possible, which not only simplifies things for users that want to use Solid.js in any way besides the default way with Solid's default tooling, but will also simplify maintenance.

There is a better way. People have been doing dev vs prod builds (etc) long before Node.js exports existed.

The ideal setup, imo

As far as the library structure, that's it! You are done! Super simple.

Benefits:

  1. This works everywhere with the most minimal amount of friction. Something like Chakra's issue will never happen.
  2. A vanilla ES module client app can write a simple import map to point to where local solid-js is installed, and it just works
  3. the devtools experience is great with or without source maps (mostly the difference is just stripped types).
  4. Just about every single JS ecosystem modern build tool on the planet can import from this structure without failure, without any possible complication
  5. Any runtime can easily import from this (Deno, Node, Bun, etc)
  6. It is very very easy to go buildless on both server or client with this setup, with no complications
  7. Build tools can be added to achieve dev vs prod, ssr vs not, compile html template tags or not (like Lit's new compiler), with a 100% opt-in experience beyond the super basic package setup.
  8. It will be easier to make more integrations for Solid.js, even in build setups that are not so mainstream, because they don't need to implement all this conditional module lookup algos.
  9. Generally speaking, it will just be way easier for any tools in the world to simply consume these files.

If someone from core officially endorses trying out a simpler setup, I will be willing to help prototype it.

trusktr commented 11 months ago

Here's one of my packages (which as you might guess, follows those ideas):

https://github.com/lume/element

I've committed the dist/ folder so it is all easy to see from the repo (commiting dist/ is not on my list of recommendations, but for my needs this makes it easy to clone the lume super repo and everything works out of the box with no build, which is something I valued, and makes live vanilla demos like this one possible: https://raw.githack.com/lume/lume/develop/examples/gltf-model.html).

We can see that https://github.com/lume/element/blob/main/src/index.ts maps to https://github.com/lume/element/blob/main/dist/index.js along with sibling source map and declaration files. The same applies to other files.

main and types fields simply point to dist/index.js and dist/index.d.ts.

Other problems with Solid's setup I forgot to mention above

I can think of more.

An ES module setup as close to vanilla as possible is simply the way to go. Maximal ease, portability, longevity, and interoperability.


Solid 2.0

Let's please 🙏 consider this for Solid 2.0. I see we're already going in the same direction:

https://github.com/solidjs/signals/blob/dcf7521abad59cacce53a881efd5191627cc46c6/package.json#L35C9-L45

shiro commented 11 months ago

My 2 cents: Yesterday I went to inspect getRequestEvent, which took me to a declaration file, which had no reference to dom-expressions at all, so I had to go to github and use global search for it in solid start, solid and finally dom-expressions...

Not sure if other IDEs can do it, but at least the current behaviour with the TS language server for vim isn't great (I assume it's similar with other tools). If it's possible to go to the source directly, that would be great, also being able to consume just signals would be cool as well!

trusktr commented 11 months ago

Yep, it would be nice!

Not sure if other IDEs can do it

IDEs will never be able to do it because generic IDEs are not designed to specifically understand Solid's bespoke file copying pipeline. Only a hypothetical IDE plugin made by Solid team could enable it (wouldn't be worth it).

aminya commented 11 months ago

do not use exports

@trusktr I agree with your suggestion to support import maps if someone is interested in using them, but I don't think it is a good idea to break the Nodejs exports. Nodejs has its own standard that many tools support. Breaking the tooling in each new version is a huge mistake that can hinder the adoption of newer versions.

trusktr commented 11 months ago

If Solid 2.0 will already be an ecosystem breaking change, and if all of Solid's prescribed tools that the team manages (f.e. app generators, Solid Start, any plugins for vite/babel/etc) are updated to work on 2.0, then this change will be for the better.

A clear migration path should be defined. I will gladly help write this.

Here's just one more example of problem with the current setup:

Screenshot 2023-12-20 at 9 06 58 PM

Which do I auto-complete? Devs should just see one option: "I just want X thing from solid.js".

This will be a philosphical question for core team: "how much does Solid.js want to be able to move forward, and how much does it want to stay full backwards compatible"?

React takes it to the extreme on one end of the spectrum at almost 100% backwards compatibility with one main notable change being the one to setState in class components when it went from sync to async, but that was basically all.

On the other hand, Three.js has the most simple package setup that will last forever, making maintenance as simple as possible, and it makes breaking ecosystem-changes when it determines it is for the better future (it has a 10 month deprecation cycle and anything can break in 10 months for the better), and provides a very nice migration guide along the way. And look at Three, it is doing great. The ecosystem is huge for being in a niche area as opposed to normal non-WebGL/GPU web development.

Solid.js started as a passion free time unpaid non-corporate project aiming to be one of the best and most innovative. Will Solid continue to strive for that? If so, breaking changes wiill be a must.

aminya commented 11 months ago

I am all on for improvements and innovation, but I do not consider import maps superior to Nodejs exports. It's just a matter of different standards. Browsers sometimes have fallen behind the innovations of Nodejs, and I do not necessarily think import maps are inherently better. I respect your choice if you're on the team with "browsers and no local tooling", but it should be considered that many people are not, and there are many benefits from other perspectives.

So, a yay for innovation, but a nay for breaking things for the sake of a change.

LadyBluenotes commented 9 months ago

Consolidated this into #473