⚛️⚡ Vite + React + Typescript Component Library Template: Setup Explanation 🛠️

⚛️⚡ Vite + React + Typescript Component Library Template: Setup Explanation 🛠️

Some months ago I created a component library template using Vite and React, and the community has given it so much love and support! I'd like to first thank you all for the feedback and recommendations you have made (: also thanks to future devs that run into this post and use the library.

I never wrote a proper post explaining how to set it up and some of you have struggled to do it so, today I'm doing exactly that. You can find all the features the library has in the repo's README file, but I'll mention the most important ones here too. I encourage you to take a look at them first if you're not that familiar with:

  1. Vite: Run and build the project blazingly fast!

  2. TailwindCSS: Utility classes to define your styling

  3. Storybook 7: Components Preview 👀

  4. Release Please: CHANGELOG.md and GitHub tags generation

  5. Version release configuration for both the GitHub package registry and NPM registry.

Without further ado, let's dive into it 🚀

Repo setup

You can directly create a new repository by clicking the Use this template > Create a new repository button:

Then you can clone the newly generated repo and install the dependencies using pnpm install. If you don't have pnpm installed, you can always run corepack enable to activate it (only works from Node 18+). You could also use another package manager such as npm or yarn but I'd like pnpm for being faster and more efficient (:

You should also run pnpm prepare if it wasn't already. This will set up Husky in your local machine to have pre-commit linting hooks.

Now you're able to run all the scripts this repo comes with. For example, running pnpm dev will start the Storybook dev server with some example components. You can find the complete list of scripts in the README file or by simply taking a look at the package.json file.

Changelog update and version release

This repo uses release-please, a tool created by Google that, quotes "automates CHANGELOG generation, the creation of GitHub releases, and version bumps for your projects." unquote.

You can find the GitHub workflow that takes care of this in the .github/workflows/release-please.yml file (more specifically, the first step of the workflow that uses google-github-actions/release-please-action@v3. For it to work we first need to go to the repo's Settings tab and click on the Code and automation > Actions > General section, then scroll down to Workflow permissions and check off the Allow GitHub Actions to create and approve pull requests checkbox.

This will allow release-please to create the Pull Request against the main branch that will bump up the version, update the changelog file and finally release the GitHub tag after being merged (The PR is created by a bot so any repo administrator has to manually approve it and merge it).

Publishing the package

The repo is configured to use the NPM registry, which I will explain first. You can skip to the next section if you want to know how to do it using the GitHub package registry.

Using the NPM package registry

We simply need to get an NPM access token for our GitHub workflow to be able to publish the package to the registry and add it as a repository secret.

Log into npm and go to the Access Token tab to create a new token. I'll use a classic one for demo purposes.

You can use either the Publish or Automation type as we need the token to be able to publish new versions of our package.

Copy the value of your token and now let's open the repo's Settings tab and go to Security > Secrets and variables > Actions. Add a new repository secret called NPM_TOKEN and paste the value of your token.

And we're done! With this, the release-please.yml workflow will be able to use this token (in line 55) to publish the package to the npm registry 🎉

Using the GitHub package registry

The configuration is pretty straightforward as we don't even need to get a new access token.

The repo has a workflow example in the .github/examples/github-release-please.yml file. It's pretty much the same as the original workflow, just including the following changes:

  1. Adding the packages: write permission in line 8. This will be enough for the autogenerated GITHUB_TOKEN to have permission to publish the package to the GitHub registry during the Publish step.

  2. The registry URL is now https://npm.pkg.github.com (line 40)

  3. We now use the existing secrets.GITHUB_TOKEN as the access token in line 57 instead of having to create another one.

Simply replacing the existing release-please.yml file with the content of the example file is enough for the workflow part.

💡
You can also create a personal access token with more granulated permissions instead of having them in the permissions key inside the yaml file, and create a new repo secret and use it in line 56. What was explained above is just the simplest way to do it.

Last but not least, go to the package.json and make sure the "name" key uses the organization scope where the package will be published. For instance:

  • If I want to link the published package to the same vite-component-library-template repo, I'll have to change the name to `@ignacionmiranda/vite-component-library-template".

  • If your company is called Octocat, then the name would be "@octocat/your-library".

Finally, don't forget to update the repository.url value with the URL of your actual repo.

The above is the simplest explanation I came up with to set this up. If you want to have deeper insight, I encourage you to check the official GitHub docs about publishing Node.js packages.

Installing the library as a dependency

Using an NPM package

If your package is public, great! then you can simply go to your frontend application and run pnpm i <your-library> and start using it.

If your package is private, you'll need to log in using the npm cli or a .npmrc file passing your token along with the npm registry and be invited to the npm organization that publishes the package. Here you can find some official docs about private NPM packages.

Using a GitHub package

We need some additional steps if we use this approach, but nothing crazy (:

Inside your frontend app, you'll need to create a .npmrc file in the root of the project with the following content:

# The first section is your user name or organization name in a
# kebab-case format.

# If my username is IgnacioNMiranda, then the first line should be:
# @ignacionmiranda:registry=https://npm.pkg.github.com
@<your-org-or-user>:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

and then add the GITHUB_TOKEN variable to your .env file:

export GITHUB_TOKEN=<your-token>

The token has to be a personal access token, created with at least the read:packages permission in order to download packages from the GitHub Package Registry.

After running source .env or using your preferred tool to load env vars from a .env file into the current console instance, you should be able to install your GitHub package. For example, if the package is called @ignacionmiranda/vite-component-library the command we have to run is: pnpm i @ignacionmiranda/vite-component-library.

Using the library

Here are some examples of how to use the styles of the library and a React component in a Next.js application.

/* _app.tsx  */
import '<your-library>/dist/style.css'
// More imports and your App component ...
/* pages/index.tsx */
import { AtButton } from '<your-library>'
// More imports and your Page component...

Extra: Testing the library in a frontend app locally

There are some times when we want to test the components we're building without having to publish canary, alpha, beta, or whatever versions to the registry. In order to do it we can follow these steps:

  1. Run pnpm build:lib to build the component library and get the output in the dist folder.

  2. Run pnpm pack to create a .tgz file. This has the same content as the dist folder and will allow us to install the library in our frontend app locally.
    🚨 Right now, the pack command deletes the 'dependencies' and 'devDependencies' keys from the package.json because of the prepack command. As the pack command is normally run during the publish step in the GitHub workflow, it's not intended to be run locally, i.e. to delete these keys from the package.json. Make sure you revert this change after pushing any new commit to your repo.

  3. Go to your frontend app and add your library as a dependency in the package.json. Instead of setting the version, add the path to the .tgz file. For instance: "vite-component-library-template": "../../vite-component-library-template/vite-component-library-template-2.0.4.tgz" .

  4. Install the deps in your frontend app. Now you should be able to see the local changes you did in the library and use them in your local development for the frontend app.

Wrapping Up

Now we're capable of setting up a repository that contains a component library, following semantic versioning, being published to a package registry and using it in a frontend application. Hope this is useful and provides an easy explanation of how to set up this kind of application (: it can get really hard to make everything work together, becoming a real mess with all the config code and files. Feel free to create an issue in the repo if you have difficulties with something or if you just want to make recommendations to continue improving it! You can also ping me on Linkedin if you need help with anything else (:

Happy coding!