-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optionally add compiled/bundled version of library when using the package command #2572
Comments
For future readers who want to generate separate UMD/IIFE/ES outputs for each component in your library, here is a minimal example of the setup I chose https://github.com/lokimckay-references/svelte-web-component-library-example |
There would be cases where there's only one I can't think of an easy way to scan and compile the Svelte files as there's a whole lot of possibilities on how the author wants the compiled version to look like. Rather than guessing and making a lot of assumptions, I think it would be better if we provide some options for the author to fill in themselves, that way we also don't need to reserve With the use cases above, the options that currently comes to mind would be something like interface Config {
kit?: {
package?: {
/** input path relative to 'src/lib' and output path relative to 'package' or whatever dir is */
bundle?: Array<[input: string, output: string]>; // or maybe make it an object with key as input and value as output?
/** will enable customElement option and use this string to register the element name */
customElementTag?: string; // or maybe just 'tag'?
// and other options, theoretically speaking...
// namespace?: 'html' | 'mathml' | 'svg' | 'foreign';
}
}
} Everything else should be left as default values, and the example config would look like export default {
kit: {
package: {
bundle: [
['index.js', 'standalone/index.js'],
['core/index.js', 'standalone/core.js'],
['icons/index.js', 'standalone/icons.js'],
['utils/index.js', 'standalone/utils.js'],
],
// or as an object, but then one input can't generate two different outputs
// not sure why anyone wants that, but it's something to consider
bundle: {
'index.js': 'standalone/index.js',
'core/index.js': 'standalone/core.js',
'icons/index.js': 'standalone/icons.js',
'utils/index.js': 'standalone/utils.js',
},
/** cannot be used when bundle has multiple inputs? */
// customElementTag?: 'stacked-up';
}
}
} |
Thanks for sharing, going to try this out. One of my projects stalled after realizing that bundling isn't supported yet. |
Would a package entry that takes an object or array of objects be more future proof here: export default {
kit: {
package: {
format: 'esm',
entry: "index.js",
output: "standalone.js" // or ["standalone.js", "standalone_two.js"]
customElementTag?: 'stacked-up';
}
}
} and export default {
kit: {
package: [
{
format: 'esm',
entry: "index.js",
output: "esm/index.js" // or ["standalone.js", "standalone_two.js"]
customElementTag?: 'stacked-up';
},
{
format: 'umd',
entry: "index.js",
output: "umd/index.js" // or ["standalone.js", "standalone_two.js"]
customElementTag?: 'stacked-up';
},
{
format: 'esm',
entry: "utils/index.js",
output: "utils/index.js" // or ["standalone.js", "standalone_two.js"]
}
]
}
} Actual options TBD, but this feels like the safest way to support multiple entry/output files/ folders with potentially custom config for each bundle' |
Out of curiosity would building a Svelte package via kit instead of vanilla Svelte + Rollup technically be more performant (speed and bundle size) since it uses Vite under the covers? |
Would love to see this come to fruition. Currently creating a Sveltekit/ Tailwind/ Histoire ui lib and it's ready for npm. Went to publish and realized I needed to somehow process the Tailwind classes which sent me down a very long rabbit hole that eventually led here (and about 10 other places). Seems like there's some ways with svelte-preprocess but still researching the best way. |
@oneezy there is a way that could work using an experimental feature of vite-plugin-svelte and it may work better in the future. You can use a vite devserver and ssrLoadModule with custom queries to get preprocessed output and write that to disk if you want. If you combine that with vitePreprocess in your svelte config it should work out the tailwind classes. but you'd have to distribute a css file alongside your lib so it actually works then. Generating that is not going to happen with this, you'd have to use a regular vite build for it. The above could be turned into an option to vite-plugin-svelte to also emit preprocessed output during build, which svelte package could then use more easily. I mentioned it briefly at the end of our release party stream, there will be improvements around svelte package. |
Yo @dominikg ! You're exactly the man I wanted to speak to about this. I watched the Sveltekit As a side note, I really like the direction you guys have written up here. Your proposal @pngwn feels pretty clean and would love to see something like this in the near future. |
Hi! |
This is already possible with using and configuring Rollup as @lokimckay suggested and it works well. An adapter to handle this could be a nice idea |
It is possible to assemble a .svelte component first as a client-side component, and then as an SSR (server-side rendering) component. Then create an index.js file in which, depending on the SSR variable, export either the SSR bundle or the client bundle. import IconClient from "./components/IcLAboutUncirculatedDoc.client";
import IconSsr from "./components/IcLAboutUncirculatedDoc.ssr";
const SSR = import.meta.env.SSR;
let module;
if (SSR) {
module = IconSsr;
} else {
module = IconClient;
}
export { module as IcLAboutUncirculatedDoc }; In this case, such a component can be rendered as usual. And it will work for both SSR and the browser. And it will be properly tree-shaken during the build. <script>
import { IcLAboutUncirculatedDoc } from './icons'
</script>
<IcLAboutUncirculatedDoc /> But the solution turns out to be complex. await build({
configFile: false,
plugins: [
svelte({
compilerOptions: {
hydratable: true,
// dev: true,
},
}),
],
build: {
minify: true,
lib: {
entry: {
"icons/index.client": "src/icons/index.ts",
},
formats: ["es"],
name: "lib",
},
rollupOptions: {
external: ["svelte/internal"],
output: {
entryFileNames: `[name].js`,
chunkFileNames: `[name].js`,
assetFileNames: `[name].[ext]`,
manualChunks: (id, { getModuleInfo }) => {
if (id.includes("/icons/components/")) {
let [, name] = id.split("/icons/components/");
name = name.split("/").at(-1);
name = name.replace(".svelte", ".client");
return "icons/components/" + name;
}
},
},
},
},
});
await build({
configFile: false,
plugins: [
svelte({
compilerOptions: {
hydratable: true,
// dev: true,
},
}),
],
build: {
emptyOutDir: false,
minify: true,
ssr: true,
lib: {
entry: {
"icons/index.ssr": "src/icons/index.ts",
},
formats: ["es"],
name: "lib",
},
rollupOptions: {
external: ["svelte/internal"],
output: {
entryFileNames: `[name].js`,
chunkFileNames: `[name].js`,
assetFileNames: `[name].[ext]`,
manualChunks: (id, { getModuleInfo }) => {
if (id.includes("/icons/components/")) {
let [, name] = id.split("/icons/components/");
name = name.split("/").at(-1);
name = name.replace(".svelte", ".ssr");
return "icons/components/" + name;
}
},
},
},
},
}); |
But if i understand correctly - this would still need to be used within a svelte app, correct? Or is this solution somehow framework agnostic? |
Not necessary. The compiled Svelte component can be used programmatically, framework agnostic. |
Describe the problem
Right now
sveltekit package
only preprocesses TS/Svelte files to JS/"vanilla Svelte" files and exports these in their raw form. This is good when you want to use the library within another Svelte project, which is probably the 80% use case.However, if you want to use the component library as-is, for example on another project not using Svelte, you need to add this functionality on your own currently.
Describe the proposed solution
Add an option to also provide a ESM-style bundled version of the component library. Provide that as an export for the
"main"
or"module"
export. What I'm not sure about here is how to then differentiate between the compiled and raw version when generating the"exports"
field. Should we double down on the "special svelte field" and do?
If so, which tooling packages need updating for this to work correctly?
Another idea: Provide the bundle inside a special folder called
standalone
, so people using the bundle would doimport { SomeComponent } from 'some-library/standalone';
. This would make it easier for bundlers/tooling because they wouldn't have to know about the "svelte" field. I think this is my prefered solution.Alternatives considered
Some docs on how to achieve this
Importance
would make my life easier
Additional Information
Continuation of #518
The text was updated successfully, but these errors were encountered: