Build a React UI Library from scratch - TypeScript, Storybook, Jest & Rollup
HTML-код
- Опубликовано: 27 июл 2024
- We're doing a deep dive into how to build a React UI Library from scratch in this video - building a simple Button with a variant prop and creating a "story" of it as well as tests. We also publish to NPM and import it directly into another project. If this helps, please drop a like and comment to let me know if you need me to cover anything else (or if you just wanna say hi!) ✌️
Code: nickderaj.com/youtube/react-u...
Chapters:
00:00 - Introduction
00:30 - Initialise the NPM project
01:50 - Setting up TypeScript & what the settings mean
07:24 - Folder structure - why use index.ts?
10:34 - Setting up Rollup
15:12 - Publishing to NPM
17:52 - Importing the package in another project
19:14 - Customising our Button
22:25 - Adding postcss to Rollup
26:10 - Setting up Storybook
27:44 - Adding a Button.stories.ts file
30:07 - Adding react as a peer dependency
30:32 - Setting up tests with Jest
33:09 - Final deployment
33:55 - Outro & Thanks :) Наука
Thanks for your work.
No problem!
Dude. You are amazing . Thank You
I’m glad it helped! Thanks :)
thank you so much for this lesson
You're very welcome!
I have a style.css with my jsx file. When I build this and publish, the component ia working but style.css isn't reflecting on the component
I am trying to use useNavigation from 'react-router-dom' inside my Button component and after exporting in another project I am facing the error:
Cannot read properties of null (reading 'useContext')
Thank you for sharing the repo, I really understood but I don't wanna do it from scratch hehe,
Haha I’m the same, I like to follow along with the video but not write it all from scratch
I followed the video. Everything works fine except css. What could be the problem?
I have some error . This is my error:
code E402
npm ERR! 402 Payment Required
Hey, awesome video! I had a lot to learn.
I need some help. Initially, the project I'm working on had a 'components' folder containing all the Box, Button, Input, etc. My project simply used those components.
We decided to move to a monorepo approach. I successfully used Rollup to create that bundle. The bundle size in its unzipped form is around 132 KB. However, when I include it in our project and import Buttons or Inputs in many files, and try to build this project (since it's also a React library), the bundle size increases exponentially. After replacing all occurrences with component imports and building it, my bundle size increased by 16 MBs. I've tried what I could, but I really need help to resolve this. For now, I've simply marked it as external, but I want to understand the root cause of this problem and how we can fix it.
I would really appreciate your help if possible !
I am creating a serious Ui library but the problem with the rollup is that it doesnot support experimental things like "use client" and others. And i also found it terrible for large projects as it bundles all components inside a single file and had problems splitting them. Considered moving to webpack for now.
great video, looking for something similar
question : do you recommend building using javascript ,coz in out company we dont use typescript , what should i do differently with js
Typescript is just built on top of JavaScript - everything you can do in TypeScript you can do in JavaScript, just don't add the types!
Hi Nick, Thanks a bunch! I managed to create a component library following your advice, and it's working well. I have a couple of questions I'd love your input on. First, when dealing with more complex components like a calendar or a data table, what's the best approach? Is it okay to use third-party libraries, or is that a bit too much? Second, if we go with third-party libs, how do we handle dependencies to prevent conflicts with other components and the main project( the one that we use this lib as a dependancy)? I'd appreciate your guidance on the most recent approach. Also, could you show me how to stay updated with these libraries, especially if we lock dependancies? Lastly, I'm stoked about using TypeScript, but I'm wondering if other third-party libs we want to use for composite components might not support TypeScript. Any advice on that front? Thanks again!
Hey Kanchana, glad it helped!
Regarding complex components, it's up to you really. You can built them from scratch using JS and CSS, you could use external libraries like Tailwind or you could use a UI library like Material UI. My preferred approach is using Tailwind and building them from scratch since I have full control over everything but do whatever style you like. One thing to note is that UI libraries can bloat your package and make the file size unnecessarily big if that's a concern.
For dependency conflicts, I haven't had any so far honestly so can't really advise on that - but when we build & publish the package I think Rollup should handle that side of things.
To stay up to date with packages in your Github repo you could use dependabot to auto-update packages, then you'll have to release a new version of the package for users to update to on their side (github.com/dependabot).
Finally, TypeScript compiles down to a couple of files - one is a plain JavaScript file and one is a "types" file. If the user is only using JavaScript it will just ignore the types file and work as intended so don't worry about that!
Hope it helps! ☺
@@nickderaj
Thank a million for your support.🙏 You're Absolutely right!!!. I had a bad experience using other UI libraries like Material-UI or Semantic UI within our UI library, because they made our bundle size larger with unnecessary code. The main issue was conflicts with dependencies. For example, if Material-UI's date picker uses Dependency A and Semantic UI's file uploader also uses the same Dependency A, both end up in our node-modules. Now, if we upgrade the date picker, Semantic UI's file uploader might still be using the old version of Dependency A. This can lead to breaking changes, causing issues with the entire UI library. I hope you understand what I mean.
I'm finding it challenging to build components like a calendar with a date range selector, charts, data table with lazy loading or pagination, drag-and-drop rows, sorting, etc. 😓 I really appreciate the way you approach things and create your components. However, it's a bit difficult for me to think about some features. I'm worring some times when stakeholders asking me, why should we build a component if It's already build🙃. Your advice could be really helpful for me.
@@kanchanakularathna9422
I think you might be over-engineering it if you're trying to make it entirely future-proof. You don't HAVE to update all the packages all the time - some people are still using NextJS 12 for example, using the pages router, since it works as intended in production and updates will cause engineers to spend a bunch of time (money) on updates which won't make any difference to the end user.
If you're time constrained then you can do the quick way using a UI library or copy-paste some existing components and fix the issues that arise when you update packages a few months/years down the line when you have more time or just don't update the packages unnecessarily (only if there's some security issues for example).
@@nickderaj Thank you for the explanation. Actually, my first task is to develop a new UI library in my new workplace. Your ideas are very important to me as I make future decisions. Thanks again 🙌
Question, are not npm and yarn the same? (package manager)
They do the same thing but yarn is a little bit quicker/more secure. There’s others like pnpm as well that are better for monorepo projects (lots of projects in one repo) but for the most part I just use yarn!
Throwing error while using hooks
Hi Nick i have done it exact in your way and i have used it on my nextjs project too and it works fine. My problem is when i deploy that nextjs project on Vercel then it shows me some kind of error telling authentication token not provided and i chatgpt it and added token on environmental variables too but the error keeps coming so can you please provide me some suggestion how to fix it and when some other person uses my library also i don't want them to face same problem as well and i can't provide my authentication token for everyone also.
Did you deploy a project from a template? There isn’t authentication token at build time in the package I built - you sure it’s not from your project itself?
@@nickderaj i have made a simple nextjs project and i have used my library component only but while i deploy that project into vercel it throws an authentication token not provided error so how to set authentication token at build time ?
@@silentco_der You can set it in your vercel configs, it sounds like you're missing an environment variable..? But it shouldn't be coming from the package you made unless you added something not in the video
Hello Nick,
Firstly, thank you for this video.
I understand how to build library and I made it.
But, i can't see anything at all. how to serve this package on like localhost or something else ?
Glad it helped! :)
Check the part at 15:12 onwards - we publish the package to the NPM repo so you can just import it into your other projects with “npm install” like any other public package
@@nickderaj Okay, I got it that part. you are great :). I publish it to our private npm server and we are trying in our react projects and works perfect :). Actually my question is different. I want to see what I am doing while coding components. example, "npm start" and serve localhost:8080 in library project.
I am trying like rollup-html rollup-serve plugin and I changed rollup.config.mjs but doesnt work. Because in "dist" directory has no index.js, App.js and index.html for react lifecycle.
I hope, i explained myself :)
Ahh I get what you mean, you can’t run it like normal unless you create an index.html or something since it’s just components. I wouldn’t create it however since it’s not relevant to a UI package
That’s why I added the Storybook package so we can see the components and make changes without having to publish every time. You can see around 29:18 I’m viewing the components I built without publishing
@@nickderaj okay, thank you so much for explanation. I get it why dont create reactjs things. Have a good day :)
best video I've seen so far. but i'm having some problems... i use tailwind but after bundling my styles dont refllect
any idea what the issue is?
Thank you! :)
I had a bunch of issues with compiling the CSS so after a day of banging my head against the computer I decided to just accept it and install Tailwind on the projects that use it, which I likely would have done anyway.
I might revisit this in the future though, saw some people said to use babel or some bundler packages, think it was called "swc" if I remember correctly, to fix it.
@@nickderaj ohh I see. Thanks for the response. I'll just do as you've said and install tailwind on the projects that needs it.
Hi there, I experienced the same issue with the styles not showing from the button.css file. However, you moved straight onto Storybook, even though you commented on this issue. Do you know what the solution to this would be please? Many thanks
I tried changing the postcss settings to: postcss({ extensions: ['.css'], inject: false, extract: true, modules: true }),
But then I need to do: import { Button } from "packagename"; AND import "packagename/dist/esm/index.css";
How would you propose just being able to do: import { Button } from "packagename" ... so that the component AND the components styles (in the Button.css file) come down via that import?
Hey, sorry I can’t remember the exact solution to this as it was awhile ago but I’ll revisit this as I had quite a few issues with the css side and remember seeing the dist/esm/index.css trick but it looked horrible.
I remember on another project I just used tailwind across the board and installed tailwind on the project using it as well to avoid this whole css issue. Also saw people commenting that babel would’ve been a lot easier when I was looking up this issue so might give that a go next time.
An alternative solution would be to load all your css files (or put them all into one root index.css and import that) in the main file of your app and all the styles should be imported
Your head blocks away the installed dependencies for rollup highlighting the packages on the screen would have been useful
The code (and the package.json) file are in the link in the description
Adding custom css part also import in making libraries , you aren't covering that
can you please share roolup comment
Which rollup comment are you referring to? The code is in the description if that helps!
hi @@nickderaj , how set the tailwind config
I like this video but you audio is not clear enough. May be next time try to record audio without earphones
Oh hm thanks for letting me know, I tried without the mic but it picks up the sound of me typing - I'll try invest in a little mic soon
Your face was too far away from the camera, please come closer.
Is that sarcasm ? 😂 my table is super short