How to test packages locally before publishing using yalc
Published
Table of content
If you maintain an npm package, you might want to test changes locally in an app that depends on it before publishing. This article shows how to do that using yalc, an alternative to npm link and yarn link.
In this tutorial, we’ll use a common real-world example: a shared frontend configuration package consumed by an application. We’ll add new configuration settings to the frontend config package and test how those changes affect the app that uses it without publishing or pushing any code on GitHub.
This tutorial uses a React-based example, but the workflow using yalc is the same regardless of whether you use Vue, Svelte, or another framework.
Initial setup
In this tutorial, we’ll use two repositories:
- tutorial-frontend-config: this is the repository containing the frontend configuration to be shared across projects. It contains ESLint and Prettier configuration files.
- react-yalc-tutorial: it’s a small application built with Vite. It is a typical React/TypeScript app with a few components. It already uses the
tutorial-frontend-config.
# Clone the frontend config package and install its dependencies
git clone git@github.com:liv7c/tutorial-frontend-config.git
cd tutorial-frontend-config
npm install
# Go back to your parent folder (if needed)
cd ..
# Clone the example React app and install its dependencies
git clone git@github.com:liv7c/react-yalc-tutorial.git
cd react-yalc-tutorial
npm install
Before we continue, let’s install yalc globally so it’s ready to use:
npm install -g yalc
Everything is set up, so let’s get started.
Let’s update the config package
The tutorial-frontend-config repository contains all our shared frontend configuration rules for linting and formatting. We have a published version on npm, and several projects already depend on it.
Let’s say we want to try out a new ESLint plugin: eslint-plugin-perfectionist. It not only handles import ordering but also includes sorting rules for TypeScript types and component props.
Let’s go to our frontend config repo and create a new Git branch:
cd PATH_TO_REPO/tutorial-frontend-config
git switch -C feature/use-perfectionist-eslint-plugin
A quick tour of the tutorial-frontend-config repository
The tutorial-frontend-config repository is an npm workspace. A workspace is a way to have multiple packages within the same repo. In this case, there are two packages:
configsthat contains the package published on npm.example-app: a demo app that consumes the configs package.
Here are a few useful details about npm workspaces:
- When you run
npm installat the root of the workspace, it will install the dependencies of all workspace packages. This works thanks to theworkspaceproperty in the root package.json:
// in package.json
"workspaces": [
"packages/*",
"example-app"
],
- Packages can reference each other. I have an example app in the repo that references the other workspace package in its dependencies:
// in example-app/package.json
"@oliviacl/tutorial-frontend-config": "*",
When you want to work on a specific package inside a monorepo, navigate into that package’s folder. Each package has its own package.json file, which contains specific dependencies. In our case, we’ll be working in the configs package.
cd tutorial-frontend-config/packages/configs
Let’s add the Perfectionist plugin to our ESLint config
The goal is to modify the ESLint config to use a new plugin: eslint-plugin-perfectionist.
Make sure you are in the correct directory (
tutorial-frontend-config/packages/configs).
If we examine the eslint.js file, we currently use eslint-plugin-import with a few rules. With eslint-plugin-perfectionist, we can remove eslint-plugin-import and the rules we had for this plugin, as the perfectionist plugin will handle those functionalities. In the packages/configs directory, run:
npm uninstall eslint-plugin-import
Then remove all references to eslint-plugin-import from eslint.js:
// remove import
import importPlugin from "eslint-plugin-import";
// eslint.js
export default [
// delete the plugin from the plugins section
plugins: {
// Delete the following line
import: importPlugin,
},
rules: {
// Delete this block in the rules
'import/order': [
'warn',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
'newlines-between': 'always',
alphabetize: { order: 'asc', caseInsensitive: true },
},
],
}
]
Let’s commit those changes:
git add . && git commit -m 'chore(eslint): remove eslint-plugin-import with rules'
Then, let’s install the new ESLint plugin (make sure you are still in the packages/configs directory):
npm install eslint-plugin-perfectionist
We add it as a dependency so projects using our config don’t need to install it themselves.
Let’s update our ESLint config to use the plugin. We can use a ready-made config as mentioned in the plugin documentation.
First, import the plugin:
// in eslint.js
import perfectionist from 'eslint-plugin-perfectionist';
Then, add the perfectionist plugin:
// in eslint.js
export default [
js.configs.recommended,
...tseslint.configs.recommended,
perfectionist.configs['recommended-natural'],
// ...
];
Let’s commit this:
git add . && git commit -m "feat(eslint): add perfectionist plugin"
Testing our changes with yalc
This is where yalc comes in. We want to test the changes we made to our ESLint config before pushing or publishing the changes.
Publishing our package locally via yalc publish
yalc creates a local store on your computer inside a ~/.yalc directory. We can publish packages to this directory. yalc then makes it easy to use the packages published to that local store in applications that depend on them.
In the packages/configs directory, run:
yalc publish
After running the command, you should see the following message in your terminal:
@oliviacl/tutorial-frontend-config@1.0.4 published in store.
If you inspect the .yalc directory in your home folder, you should see the following structure:
❯ tree ~/.yalc
.yalc
├── installations.json
└── packages
└── @oliviacl
└── tutorial-frontend-config
└── 1.0.4
├── CHANGELOG.md
├── eslint.d.ts
├── eslint.js
├── index.d.ts
├── index.js
├── package.json
├── prettier.d.ts
├── prettier.js
├── README.md
└── yalc.sig
5 directories, 11 files
Adding the package via yalc add
Now, let’s change directory and move to the tutorial application we cloned in the previous section:
cd PATH_TO_REPO/react-yalc-tutorial
Make sure you’ve run npm install first. Now, to use our package published in the yalc local store, we only need to run:
yalc add @oliviacl/tutorial-frontend-config
If you open your package.json, you’ll see that the dependency was replaced with a reference to the .yalc directory:
// in your package.json
"devDependencies": {
"@oliviacl/tutorial-frontend-config": "file:.yalc/@oliviacl/tutorial-frontend-config",
}
Inside the repo, you should also see a .yalc folder containing the latest version of your package. When you run yalc add, yalc copies the package from the ~/.yalc store into your repo.
Run npm install. This will install any new dependencies required by the updated ESLint config.
If you run npm run lint, you should see new warnings coming from this new plugin:

It works!
Making multiple changes and propagating them with yalc push
Now, let’s say we want to make more changes to tutorial-frontend-config. In tutorial-frontend-config, we could modify the prettier config and update it to use double quotes, for instance:
// in packages/configs/prettier.js
export default {
semi: true,
trailingComma: 'es5',
// we switch singleQuote from true to false
singleQuote: false,
printWidth: 100,
tabWidth: 2,
useTabs: false,
arrowParens: 'always',
endOfLine: 'lf',
};
To propagate the changes, no need to run yalc publish. You can run:
# run this command from packages/configs
yalc push
yalc push pushes the changes to the Yalc store and automatically updates all projects using the published version in yalc.
You should see a command output that looks like this:
@oliviacl/tutorial-frontend-config@1.0.4 published in store.
Pushing @oliviacl/tutorial-frontend-config@1.0.4 in /Users/YOUR_USERNAME/projects/react-yalc-tutorial
Package @oliviacl/tutorial-frontend-config@1.0.4 added ==> /Users/YOUR_USERNAME/projects/react-yalc-tutorial/node_modules/@oliviacl/tutorial-frontend-config
If you go back to the react-yalc-tutorial project and open the .yalc folder, you should see that the Prettier file has been updated. And if you run npx prettier --check src or enable format-on-save, you should see the new Prettier rules being applied.
Cleaning things up when done testing with yalc remove
Once we’re done testing, we can run the following command inside react-yalc-tutorial:
yalc remove @oliviacl/tutorial-frontend-config
This command removes the yalc entry from package.json and cleans up the yalc.lock file.
If you’re testing multiple packages with yalc and want to remove all of them at once, run:
yalc remove --all
Working with component libraries
In this tutorial, we worked with a configuration package that doesn’t require a build step. However, the workflow with yalc is almost the same when working with a component library that has a build step.
The only difference is that you will want to run npm run build to build your library before running yalc publish or yalc push. yalc will copy all the files that should be published, using your package.json as a source of truth.
npm run build && yalc publish
Conclusion
In this post, we looked at how to use yalc to test a package locally without publishing it or pushing any changes. It’s a very useful tool for trying out changes locally.
yalc is a great alternative to npm link or yarn link and, as you saw in the example, is pretty straightforward to use.
I hope this tutorial was helpful! As always, if you have any questions or would like to chat, don’t hesitate to reach out on Bluesky.