https://github.com/simllll/nuxt-library-demo
Right now it's not possible to create a library package for nuxt that utilizes all features like SSR, critical CSS injection and so on. I've created a demo repo to show how far I got and opened a question over here: https://cmty.app/nuxt/nuxt.js/issues/c9554.
I would consider it as bug, but if it's more like a feature request, please change the request.
I guess the right way to go would be find a way to load a Vue JSON Bundle (https://ssr.vuejs.org/guide/bundle-renderer.html#problems-with-basic-ssr) and allow a library to provide this json file.
Let me create a library that can be rendered on server and client side, with all the features it would have when I have the copmonent directly within the nuxt package.
Right now an external package cannot use all the features like ssr optimization, crticial css injections and so on.
Cant you just create different builds? umd for direct use on the client and cjs or esm build to use in Nuxt?
You can use components from packages in node_modules directly in a Nuxt app (with some caveats), so I dont think its really true that its not possible at all.
Eg once yarn-linked in your demo, remove the empty ts def in test.vue (as the nuxt-app doesnt use ts) and change the import to the following and the component should still show up with the scoped css on the index page:
import Test from 'test-component-lib/src/myComponents/components/test.vue'
Thanks @pimlie for your quick response,
I understand your appraoch, but I try to split the complexity of the app into several smaller, independent packages. E.g. I use vue-i18n, tailwind, different / own ts configs,... and other stuff. By compiling the package like I did, the "consumer" of the package (in my example nuxt-app) does not have to take care of a correct setup of tailwind or i18n and or whatsoever. It's already done by the package itself. If I include the component directly, I do not have this benefit and actually end up by not really having an own package, It's more that just the file lies in a different folder ;).
About your first comment, I could easily do different builds, but I couldn't find a way to tell nuxt to use the one (cjs) for backend and the other (umd) for frontend? Any hints on this?
Thanks
Simon
It shouldnt be necessary to have different builds just for Nuxt. As building your Nuxt project includes a build step, its safe to just use either a cjs or esm build. The umd build would only be used / necessary when you also want to use the library in a vanilla Vue app without build step.
To be honest it confuses me still often as well, but umd/cjs/esm builds are only about the way the code has been packaged into the dist file(s). If your library would need to run on IE9 then you should also transpile your code to IE9 for the cjs and esm builds (and not just umd, e.g. its not that cjs = ES5 and esm is ES6). Eg Nuxt could use the esm build for your package and use tree-shaking(*) to only pack the parts of the library that are actually used, but code from node_modules isnt normally transpiled so the code in your esm module should already run in all the browsers you want it to be.
* tree-shaking is not really that straight-forward due to sideEffects, there are some ifs and buts
It shouldnt be necessary to have different builds just for Nuxt.
E.g. I have a component that loads svg files, on the serverside it does something else as on the client side. How would you solve something like this in a library then?
There are some more cases where I would like to run different code on client and on server. Right now I couldn't find a way to do this properly with a "nuxt library".
And then there is still this open issue with css. There is no simple way to do include css straight forward on component level. E.g. I have a library that has around 20 components, each component has it's own css. My current workarround ist that I use extract-css and include the one "big" css file as soon as I use one of the components, I would prefer a way that does something more clever though. E.g. only collect css from the used components, and only load the parts that are needed. Maybe even allow purgecss to clean up the unused styles.
Looks like I finally found a working solution.
Basically what I do is:
if (process.client) {
module.exports = require('./index-client');
} else {
module.exports = require('./index-server');
}
and finally you get a component library that works on SSR and on the client with all the features (scoped css, etc.) and even works for "pure" vue js. If you have ideas to improve the "entry" file, just let me know, right now it kind of feels like a hack.
If I find some time I will update my repo too to provide a demo.
Regards
Simon
@simllll Where did you create the wrapper / entry file?!
@simllll Doesnt this affect your bundle size? Eg my first thought would be that both builds are always included as they cant be tree-shaked?
Eg thats why we have different keys in package.json to indicate different builds.
@codytaft what do men by where? I just created this file manually and use it as entry point.
@pimlie no it doesn't, because it's really just the entry file that gets processed during runtime, not during build time. i have following kind of a setup:
library -> is built with webpack in 3 modes (modern, server and client)
... this library provides shared components, some plugins and also a nuxt module which registers assets that are used within the library. the library itself is written "async", which means all the components are only loaded when needed. this improves also the bundle size.
nuxt project -> uses the shared component library. but does not transpile, compile or do anythign else with the library.
I tried it with the "module" "browser" and other methods which are there in the package.json, but nuxt always goes for the "main" or "module" (unsure right now) regardless of the current environment (client / server).
furthermore I actually have 3 builds right now, I also do a modern build, this my entry point file right now https://github.com/simllll/nuxt-library-demo/blob/master/packages/test-component-lib/src/loader.js
I'm suprised how well all this plays together right now, we even struggled with some other stuff like storybook before because we use typescript and other techniques that storybook doesn't like that much. with this approach all components are totally encapsulated, what they use in background is not of any matter for the one who uses the library.
I just updated my GIT repo, just check it out. I'm open for comments, improvements,... whatsoever.
https://github.com/simllll/nuxt-library-demo
Hopefully someone can take advantage of it. It sounds kinda complicated at the beginning due to the reason that you actually have to build your own build system. But either you use my template now or you spend some time to find out how things work, it gives you a great understanding of webpack and a nice approach to takkle bigger web projects.
regards
@simllll Very interesting approach, thanks for sharing! :100:
First of all this idea is literally advising a way to split the Vue ecosystem and building component libraries with nuxt first (or nuxt only) support.
.vue
SFC was designed as a way of making and sharing reusable, encapsulated and universal components. The only difference is that we skip transpile step for node_modules
. Everything is already compiled 3 times by webpack using most efficient requirements of target if compiling from source. There is no reason to make another build system on top of nuxt to do it. If whitelisting a library is not enough, we can copy entire library (non compiled) to the .nuxt
dir to build on runtime, however, is unnecessary.
Async entry point per component is not always meaning more efficiency, performance, faster TTI, etc. Each chunk comes with a cost. Overhead of loading and HTTP headers. Nuxt is splitting per page by default and WP4 should automatically hoist commonly shared parts. Everything else without proper analyzes and benchmark is overengineering and can lead to the worst perf. Not a thing to advice nuxt library authors as best practice.
It is mentioned that critical CSS is not working! For sure it is expected that bundling everything into a single js/css file (extract CSS, ..) makes vue SSR renderer considering it as a big block. Directly importing components per page should only import styles of used components and inline them. If you think this is not working please make a reproduction.
@simllll - you can also control what file gets served to what consumer by populating certain fields in your package.json:
main
for the CJS buildbrowser
: for the UMD buildmodule
: for the ESM builddoing so could eliminate the need for your "loader" file
Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:
Issues that are labeled as pending
will not be automatically marked as stale.
Im having similar issues.
essentially i have created a component library using vue-cli
with the following command vue-cli-service build --target lib --name sc components/index.js
If i am using
the library within a vue project, i have no issues. If i install the library in a nuxt environment per specs(https://vuejs.org/v2/guide/plugins.html), the components do not install.
Ive set my package.json file to
...
"main": "dist/sc.umd.js",
"unpkg": "dist/sc.umd.js",
"jsdelivr": "dist/sc.umd.js",
"browser": "dist/sc.common.js",
...
I have no clue what i am missing and cannot find any documentation on what i am missing. D
Do i have to create the library using nuxt?
Is there a different command for vue-cli to create the dist documents for nuxt?
Same question as person before
It is now possible easily to create a component library for Nuxt: https://github.com/nuxt/components#library-authors
See https://github.com/Krutie/Kru-Components and https://github.com/Krutie/Kru-Components/blob/master/src/nuxt.js
Not ideal approach, If components use plugins, assets, options from nuxt.config.js etc you have to copy it to root repo. Still better than nothing
Is there still no way to access plugins, assets, or options of a nuxt project from a nuxt component library??
Is there still no way to access plugins, assets, or options of a nuxt project from a nuxt component library??
Hi,
Use rollup and you can bundle all of it with the plugin you just need to add them into the config.
https://github.com/vuejs/rollup-plugin-vue
Most helpful comment
@codytaft what do men by where? I just created this file manually and use it as entry point.
@pimlie no it doesn't, because it's really just the entry file that gets processed during runtime, not during build time. i have following kind of a setup:
library -> is built with webpack in 3 modes (modern, server and client)
... this library provides shared components, some plugins and also a nuxt module which registers assets that are used within the library. the library itself is written "async", which means all the components are only loaded when needed. this improves also the bundle size.
nuxt project -> uses the shared component library. but does not transpile, compile or do anythign else with the library.
I tried it with the "module" "browser" and other methods which are there in the package.json, but nuxt always goes for the "main" or "module" (unsure right now) regardless of the current environment (client / server).
furthermore I actually have 3 builds right now, I also do a modern build, this my entry point file right now https://github.com/simllll/nuxt-library-demo/blob/master/packages/test-component-lib/src/loader.js
I'm suprised how well all this plays together right now, we even struggled with some other stuff like storybook before because we use typescript and other techniques that storybook doesn't like that much. with this approach all components are totally encapsulated, what they use in background is not of any matter for the one who uses the library.
I just updated my GIT repo, just check it out. I'm open for comments, improvements,... whatsoever.
https://github.com/simllll/nuxt-library-demo
Hopefully someone can take advantage of it. It sounds kinda complicated at the beginning due to the reason that you actually have to build your own build system. But either you use my template now or you spend some time to find out how things work, it gives you a great understanding of webpack and a nice approach to takkle bigger web projects.
regards