Guide: Using Local Private NPM Packages in Your Team
This guide targets team-internal libraries (utils/ui/core, etc.) that are not publicly published. It explains how to use local, private packages in ArenaPro projects without pushing them to a public registry.
When should you use a local package?
- You have reusable libraries shared across multiple maps/projects, but you don’t want to expose them publicly.
- You want fast iteration and validation without a full publish workflow.
- You need a reproducible installation process in CI/CD, while avoiding dependency on public registries.
Option 1: file: dependency (simple and stable)
If your package folder sits nearby your project, point to it in your project’s package.json via file:.
- Example structure:
my-project/ # your ArenaPro project
../my-utils/ # your local package (a sibling folder)- Declare the dependency in
my-project/package.json:
{
"name": "my-project",
"type": "module",
"dependencies": {
"my-utils": "file:../my-utils"
}
}- Install dependencies:
npm installAfter installation, node_modules/my-utils will be a local link to ../my-utils (not downloaded from the internet).
- Use it in code:
// client/src/index.ts
import { clampToRange } from "my-utils";
export function heal(player, amount) {
const hp = player.getData("hp");
player.setData("hp", clampToRange(hp + amount, 0, 100));
}- Pros: Simple, stable, works across platforms; CI/CD friendly.
- Cons: When editing
../my-utils, you might need to restart the build or reinstall if caches don’t pick up changes.
Tip: In your local package, set
"sideEffects": falseand export as ESM to enable better tree-shaking.
Option 2: npm pack + install tarball
When you want to validate your package under conditions close to a real publish (e.g., ignored files, build outputs, exports field), package it into a tarball and install it.
- In the local package directory:
npm packThis generates a tarball like my-utils-1.0.0.tgz.
- Install the tarball in the project directory:
npm install ../my-utils/my-utils-1.0.0.tgz- Pros: Very close to real publish behavior; ideal for pre-publish self-testing.
- Cons: You need to repack and reinstall after each change.
FAQ
Import fails:
ERR_MODULE_NOT_FOUND- Check that
exports/mainpoint to actual built outputs. - Ensure
type: "module"and ESM entry are consistent.
- Check that
ESM/CJS incompatibility:
require is not definedorCannot use import statement outside a module- Standardize on ESM output, or provide both ESM/CJS via
exportsand prefer ESM in the project.
- Standardize on ESM output, or provide both ESM/CJS via
Edits in the local package don’t take effect immediately
- With
file:: restart the build or reinstall; clear bundler caches. - With
npm pack: re-runnpm packand reinstall the new.tgzin the project.
- With
Missing types: editor cannot find
.d.ts- Add
"types": "dist/index.d.ts"inpackage.jsonand ensure the file exists.
- Add
Which option should I choose?
- Prefer
file:for simple, stable, and out-of-the-box workflows. - Prefer
npm pack+ tarball installation for pre-publish validation and CI/CD reproducibility.
For distributed teams, non-co-located folders, or advanced access control, consider a private registry (e.g., Verdaccio / GitHub Packages / GitLab Package Registry). That follows a “private publish” route and is out of scope for this page.