TypeScript Monorepo Setup with PNPM Workspaces, Vite, VueJS and TailwindCSS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so how do you structure a project when you want to share UI components between apps maybe you also want to share configuration LinkedIn rules or code formatting style well you might have heard about this way of organizing a code base as a mono repo in this video I will describe what the mono repo is and then I will try to explain the benefits of adopting this way of organizing projects finally we will build the simplest monoripo containing a vue.js application and the component Library I will also use Telvin CSS to share a consistent style guide between the applications and prettier and eslint to configure automatic code formatting and knitting rules I will focus on the basic mono repo structure and tooling without going into more complex tools such as lerna or turboripo which you might not even need when you are just starting out foreign [Music] izing a code-based containing multiple applications into a single repository it has a bad connotation mainly because the name sounds a lot like a monolithic architecture and that also has a bad connotation nowadays however this has nothing to do with a monolithic architecture in fact architecture and deployment of the application can be decoupled from the structure of the code base you are able to use a modular architecture such as microservices and also independently deployed application within a mono repo you will see that this way of organizing code makes more sense than the Alternatives let's look at some benefits of monorepose first they facilitate code sharing and reuse without necessarily having to publish npm packages you can enforce linking rules and styling or other configuration across applications it makes the onboarding and setup easier usually by just having to clone a single repos story and with a couple of comments and automations having the entire system up and running on your development machine it also makes tracking changes in a code base and creating more requests and feature branches much easier imagine you have to implement a specific business feature which requires changes in a bunch of repositories maybe it requires a database migration back-end changes new components in a component library or new UI changes if all of this are contained in separate repositories you have to create branches and merge requests on each this much request might depend on each other for example merging the backend changes without merging the database migration might leave your system in an undesirable state with a mono repo you can create a single branch and a single merge request to track all the changes required for a given feature lastly this can scale to very large repositories with lots of applications thanks to specialized tools like learner or Turbo repo so let's build a simple mono repo we will use pmpm a different package manager than the default npm you could also use yarn or npm they all have support for something called workspaces which is essentially the way you separate packages within a mono repo note that if you pick another package manager the commands and the behavior might be different so if you want to follow along make sure you have pmpm installed first let's initialize the git repository run pnpm init and getting it and create a git ignore file and add the node modules folder to it I will create a couple of folders in this repository one I like to call at app where all the different applications are stored and one called packages where libraries and configurations are stored inside the add app folder I will have a client application and the server for our example this is enough in a more complex app you might have separate folders for the application landing page that this may be servers I generated maybe you would have another one for database migrations and other stuff now let's tell pnpm that we are going to be using workspaces by creating the pmpm workspace yaml file in it we Define a couple of paths in which any folder we create will be interpreted as a standalone package let's create the hello world application using Veet which is a faster alternative to webpack for this I'm doing nothing special I'm just following the official documentation to generate application so that would be pnpm create Veet in the current folder that's big vue.js and typescript and take a look at the generated files first in the package Json let's change the name of our application in a mono report there is usually the convention to name packages with the add sign followed by the name of the app and then select the name of the package in this case let's name it at demo slash plan next let's look at the tsconfig file we might want to reuse this file to enforce some settings across all packages in the mono repo so let's move it to the root of our monoripo here we can keep only the common settings then every other package will extend this config TS configs have the capability by defining an extent property which can take a path to another TS config in the Target config you need to specify that it extends the root config and in the root config you have to specify that it is referenced by the Target config I will be running a few commands for our client app so what they usually do is create a torque to the client script so that I don't have to keep writing there's Dash filter at the demo slash client all the time next let's move typescript as a top level dependency for our monoripo since all our apps will use typescript and we want the version to stay consistent between them this will probably cause a pure dependency error for pmpm however you can safely ignore this for now I think there's also locked issue on the pnpm GitHub page for this when we install packages at the root level pnpm asks for a confirmation that we didn't do this by mistake so you need to add the W flag to the command okay let's start enforcing linking and code formatting rules for our entire mono repo for this what I like to do is install a few packages at the root level let's install pre-tier eslint and a few ESPN plugins and Custom configs let's go over them one by one and see what each does first the typestrip eslint plugin applies linting rules for typescript the typescript eslint parser has the ability for eslint to lint typescript files eslint config pre-tier removes eslint rules that conflict with pre-tier letting prettier handle those eslint plugin import ensure consistent import statements ESPN plugin simple import sort I really like this one it automatically sorts import statements for us this is basically my OCD eslint plugin view contains linting rules for vue.js and lastly prettier plugin telling CSS since we will be using termin CSS classes in our templates this plugin for pre-tier will allow it to automatically sort or css classes so that they remain consistent this makes a big difference for the developer experience when using thermi CSS now let's create our eslint RC file at the root of our mono repo I will just copy and paste this file and you will be able to find all of this in the GitHub repo in the description here we configure eslins plugin and extend the configs we just installed we need an override for the Dot View files since they will be using the custom view es link parser instead of the typescript parser to be able to parse The View files and apply view specific rule sets next let's create a pre-tier config again in the root of our mono repo here I just configured the Tailwind plugin and apply the few rules just for testing next let's create a Tailwind CSS config that will be used by both our client application as well as our component Library for this we can create a local package under the packages folder let's name it heroin-config for it to be an installable package it needs to have a package Json file we need to pick a name for our package and this will be used to install it we also add a few dependencies so PM PM there's Dash filter at demo Tailwind config add and we need to install auto prefixer post CSS and turwin CSS now let's configure these dependencies the street to post CSS config CJs file and the Tailwind config CJs file they have the CJs extension because they are common JS modules that will be imported using the requires keyword we need this because our project uses es modules otherwise let me paste the configuration files for Tailwind CSS I am doing nothing special here this is what you would get if you would follow the instructions from the termin CSS official docs I only added a color to our theme named it brand main so that we can use it in all our projects now let's use this Sterling CSS package in our client application first we need to install it when we install a package from the same mono repo as opposed to an external repository we need to use the pnpm workspace protocol so the command would look something like this pnpm client ad the name of our package which is at demo slash Tailwind Dash config followed by the add sign the keyword workspace and colon star meaning the latest version what is currently in the mono repo since we will not publish these packages there is no reason to version them next let's add the configuration files for termin CSS and post CSS just as they would be installed locally however they will not contain the configuration instead they import it from our package that we created earlier and finally let's add the termin CSS base tires to our Stark CSS file let's start the app in development mode to see that Termini CSS is running let me change the background color of the button in the hello world component to our brand color also we can observe that eslint and prettier work as expected we can see that automatic import sorting is working we can also see that we cannot place a different statement above an import statement let's add the termin CSS class to our button that will Target the MD breakpoint and color the text yellow hit save and determine CSS prettier plugin does its jobs and Source the classes accordingly let's say we decide to have semicolons in our code so I'll change semi to true in the prettier config.js file go back to our component hit save it automatically adds them for us great everything's working as expected next let's create the vue.js component library that can be reused I'll start by initializing a vid app just as we did for the client let's rename it to add demo slash UI lib in package.json copy and replace the TS config from the client as it is exactly the same it just extends the base tsconfig I'll use the generated git ignore file for the entire mono repo and remove it from the library and client next I'll copy over the Tailwind config.cgs file and post CSS config CGS let me create the shortcut command for the library in the root package.json and delete a few packages to the UI Library so we want to add our custom Tailwind package just as before and we also need the video plugin DTS to generate typescript types for our components in the vidconfig there will be some differences between the library and the client application the library will be built differently so let's first configure the DTs plugin we just installed next we configure the build options here we tell it that the entry file to our library is SRC slash index.ds and that the format will be an es module and give it a name we also want to configure the roll up options we use rollup to bundle our code together here we tell you that vue.js is an external dependency so that it doesn't get bundled with the rest of our library and we also tell it that the global view is imported from The View Library next we need to update some things in the package.json as well here we tell you that the exported module is under the dist folder and the file name is ui-lib.js and that the typescript types will be in the dist folder in main.d.ds we also tell it to export only the files in this directory we need to change the dev script as well for the dev script we want to build the component library in watch mode this will detect changes to files in our library and build it automatically let's do some cleanup and remove the auto generated component copy the base tearing stars and replace the auto generated Stars how I like to organize my components in the library is I make a folder for each component and this folder can also hold unit test for the components or story files if you use storybook let's create a component called my brand button this will be a simple button component it will take in a clock which will basically be the text of our button and apply a few Tailwind CSS classes to the bottom let's have the background color VR brand main color add some extra stars to make it look a bit better in the main TS file of the library we need to remove almost everything just leave the style import there and here we will add the export statements for each of our components so that they can be imported in independently okay let me try to build the library run pnpm lib build see I have an error here it seems that it cannot resolve the entry file index.ies well this could be an issue due to relative pets so let's try to resolve the entry file using the bet.resolve method okay since that's not it it seems that the file name is all wrong it's main dot yes not index.ds let's try again okay so the library seems to be very successfully as you can see it's about half a kilobyte of Js and about 30 kilobytes of stars this would be the base Sterling CSS tires yeah that's not so bad as you can see the g-zipped it's about six kilobits okay so you can see that all the build files that we are exporting were generated next let's install this UI library to the client application let's remove some of the auto generated template here and try to import our brand button component okay I'm adding it to the template here and let's try to run our app to see if the component shows up and as you can see the component is here and works great now here is something really cool that mono repos allow you to do with is imagine that you want to work on the UI library and the client application at the same time we want our client to run in Dev mode and we want the library to run in watch mode and build each time we change something in it propagating the changes to the client immediately for that we can create a Dev command in the root package.json which will run the dev commands on all our packages in the mono repo at once so let's add the command it's pnpm dash dash recursive dash dash parallel Stream Run Dev so this will run the dev comment on all the packages recursively and in parallel and stream the output to the console now since local modules are just Sim linked folders the library is this folder for example update automatically in the client's node modules folder let's try it out run pnpm Dev open our application and as you can see the button component is still there now let's change something in the UI library for example let's change the button text color hit save and you can see it updating live and that's it you now have a simple mono repo and once you reach the scaling limits of pmpm workspaces you might look into tools like turbo repo which offer features like caching and faster running of build commands defining more complex workflow pipelines they can also figure out what needs to be built based on changes and your Project's dependency graph and other interesting features in a future video I will transform this mono repo so you would develop and deploy using kubernetes so subscribe for that [Music] thank you
Info
Channel: Let's Talk Dev
Views: 15,890
Rating: undefined out of 5
Keywords: JavaScript, Monorepo, TypeScript, Programming, pnpm, TailwindCSS, workspace, lerna, turborepo, VueJS, Vue, Vite, Project, Setup, Example, tailwind css, tail wind, tail wind css
Id: HM03XGVlRXI
Channel Id: undefined
Length: 19min 43sec (1183 seconds)
Published: Sat Nov 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.