Replies: 2 comments 4 replies
-
Don't know much about this and the new exports maps but can't you just ship jsx and a compiled js for browser only environments? |
Beta Was this translation helpful? Give feedback.
-
So, I’m kind of the instigator of the initial discussion but as you know, I was keen to try and propose a progressive enhancement to what the bundler expects. Here’s how I published my latest version of solid-utils. Essentially generating 3 files (4 if you count ts declarations):
The first two are compiled and meant for browser use only. This way, they can be consumed via CDN calls. The latter one is rather a bet on future tooling. I do hope that bundler will more and more use the "source" key at the root of the ’package.json’ and apply the proper plugin as if this was a file you had locally. This also is in the same spirit of providing one source file and being able to transform regarding of whether we are doing SSR or not. Here’s what the relevant part of the ’package.json’ looks like: "source": "./dist/source/index.jsx",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"exports": {
".": {
"solid": "./dist/source/index.jsx",
"import": "./dist/esm/index.js",
"node": "./dist/cjs/index.js",
"require": "./dist/cjs/index.js",
"browser": "./dist/esm/index.js"
}
}, |
Beta Was this translation helpful? Give feedback.
-
I've been debating this for a while and now that I've gathered my thoughts I'd like to request some feedback from the community.
The question is:
Should Solid libraries be exporting precompiled code as you find in React or the direct JSX templates like you find in a library like Vue or Svelte?
Background
Solid is a hybrid solution of runtime and build time JavaScript. At build time we compile our JSX into optimal JavaScript. This JavaScript differs based on compiler settings. Are we outputting for client or for server? Is the output hydratable? Today we even support multiple types of SSR generation based on whether we want to use the reactive system on the server as well. If you are keeping track that's 6 different types of output before considering ES6 modules vs CJS.
Solid at runtime has different runtimes based on the environments too. We have our typical reactive client, and then the 2 different server models. These each have their own optimizations. This is a lot for a would-be third-party developer to consider.
Fortunately, there are some things in the works and there is some tooling that can help us here. I am in the process of combining the server bundles into a single compiled output and single runtime. However, this still at best leaves us with 3 different outputs at a minimum if we assume server-rendered is always hydratable. Secondly, conditional exports in package.json allow us to alias builds based on a keyword. I already use this to great effect with solid-js/web which depending will import different versions.
browser
andserver
keywords along withnode
allow us to select the right bundle based on the environment.Any 3rd party library could use the same convention to ship different bundles. However, what I've done with
solid-js/web
is expose staticisServer
booleans so that smart bundlers like Rollup can automatically dead code eliminate anyisServer
code branches from our client bundles. So anything you need on first render only can be safely placed here and won't end up in your client bundle even if compiled from the same source. So it's possible that 3rd parties won't need to use special exports for the most part.Shipping Source
The upside of shipping Source is that it is incredibly easy to author. Even TypeScript users only need to run tsc to output JS and types with
jsx: preserve
and they are done. You would still need to include the babel plugin for testing but JavaScript source could basically stay as is without any bundler or build step. It also doesn't tie your library to a version of the compiled output. JSX syntax changes a lot slower than compiled output. With the source things could continue to work across many versions without breaking.The downside of shipping Source is that browser only environments can't handle it. The end user needs to tell their bundler to transpile node modules. With the exception of Parcel this is pretty easy to do. Unfortunately, Parcel is used by CodeSanbox one of the easiest ways to share code online. Reckless compilation of node_modules can also be problematic. This would never be a problem in prebuilt starters but might be the push to go that way. As in the perception being the tooling is too complicated.
Libraries like Svelte define their own path to source, so we could come up with a special export path to go that way but it would never be the default if someone just was getting started, unless we provided a bundler plugin for each of Rollup, Webpack, and Parcel, etc..
Shipping Compiled
For starters 3rd party authors would need to produce 3 outputs otherwise their library would not be supported in all envs. We'd need to set the hydratable client as a separate export in the package map. This means every author would need to build for each of the 3 setups times cjs vs esm. It's possible we could just make everything type module and only export esm but I don't know if there are other traps there.
So the upside is the packages would be easy consumable for end-users in the browser and we'd still just be using the prescribed conditional exports to pick our package version. The downside is every author would need to setup their builds in a specific way to have it work. And we'd need to introduce new export for the hydratable client.
Hybrid?
I was thinking of this binary for the longest time which made me think that shipping source was the only really viable option. But we could ship the source under a special export and then build the source for the client only. So by default, it would work as a client library and then to do SSR it used the source via custom fields. This unfortunately includes client hydratable builds. So it wouldn't just work on client or server for SSR.
This still requires the 3rd party author to create the client build (at least if they want their stuff to run in the browser) but otherwise, they can ship with source. However, if they ever wanted to have different source between browser and server it's a bit trickier but they could use conditionals.
Simple source no difference with client server (ie.. uses isServer)
Different server and client source
In any case, I'm looking for thoughts here. This is a tricky matter and a lot of recent discussions have been about what guarantees or lack of guarantees come from using exports and an overall concern of opening this up to be a wild west of things.
Further Reading:
Beta Was this translation helpful? Give feedback.
All reactions