Recommended resources
The freely available resources this lesson will direct you to.
Hello! Welcome to the final lesson of our course. Over the past several weeks, you've built a complete, type-safe observable library from scratch. You've implemented the core architecture, a suite of operators, a robust testing strategy, and a professional documentation and release workflow. In our last session, we crafted a comprehensive README.md, the public face of your project.
Today, we take the final and most exciting step: publishing your library to the npm registry. This lesson will guide you through the last checks and balances to ensure your package is ready for public consumption. We will perform a "dry run" to safely validate what will be published, and then execute the publish command to make your library available to the global JavaScript community.
By the end of this lesson, you will have successfully performed a dry run to validate your package contents and published your library to the npm registry, completing your journey from concept to a publicly available JS framework.
1. The Pre-Publish Checklist
Before publishing, it's critical to review your package.json one last time. This file is the manifest for your package, and it dictates how npm and other tools will interact with your code. Based on our work in previous lessons, most of this should be configured, but a final check is essential.
Here are the key fields to verify:
name: This must be unique on the npm registry. To avoid conflicts, it's a best practice to use a scoped name, like@your-npm-username/your-package-name. You would have set this up when initializing the project.version: Ourrelease-itsetup will manage this, but ensure it starts at a sensible value like0.1.0or1.0.0.private: This field must be removed or set tofalse. Ifprivate: trueis present, npm will refuse to publish the package as a safety measure.files: This array is crucial. It acts as a whitelist, specifying exactly which files and directories should be included in the published package. In our case, it should contain your build output directory (e.g.,"dist") and essential files likeREADME.mdandLICENSE. This prevents source code, test files, or local configuration from being published.main,module,types,exports: These fields, which we configured for Vite and TypeScript, are the entry points for your library. They ensure that consumers using CommonJS (require), ESM (import), and TypeScript can resolve your package correctly.
2. The Dry Run: Measure Twice, Publish Once
You would never deploy code to production without testing, and publishing to npm is no different. A published package version is largely immutable; you can't just overwrite it. This makes a pre-publish validation step essential. Npm provides a --dry-run flag for this purpose.
A dry run simulates the publishing process without actually sending anything to the registry. It's the perfect way to catch common mistakes, like forgetting a build step or accidentally including sensitive files.
To understand how to perform a dry run and what to look for, this article provides a clear, practical guide.
Best Practices for Creating a Modern npm Package
The Snyk blog post 'Best Practices for Creating a Modern npm Package' has an excellent, actionable section on the publishing workflow. It demonstrates how to use dry-run commands to inspect your package before it goes live.
Please read the section 'How to publish your npm package'. Pay close attention to the two commands demonstrated: npx pack --dry-run and npm publish --dry-run. Also, review the section that explains the purpose of the files field under 'Building for ECMAScript Module Format'.
As the article explains, we have two key commands for our dry run:
Step 1: Validate Package Contents with npm pack
First, run the build command to ensure your dist directory is up to date:
npm run build
Next, use npm pack with the --dry-run flag. This command shows you a list of every file that will be included in the final .tgz package file that gets uploaded to npm.
npm pack --dry-run
The output will look something like this, listing the files defined in your files array plus a few essentials npm always includes:
npm notice
npm notice 📦 your-package-name@1.0.0
npm notice === Tarball Contents ===
npm notice 1.2kB dist/index.js
npm notice 1.4kB dist/index.d.ts
npm notice 45B dist/style.css # (if you had any CSS)
npm notice 1.1kB LICENSE
npm notice 2.5kB package.json
npm notice 3.1kB README.md
npm notice === Tarball Details ===
npm notice name: your-package-name
npm notice version: 1.0.0
npm notice filename: your-package-name-1.0.0.tgz
npm notice package size: 4.8 kB
npm notice unpacked size: 9.3 kB
npm notice shasum: [shasum_hash]
npm notice integrity: [integrity_hash]
npm notice total files: 6
npm notice
Review this list carefully. If you see source files (.ts), test files, or configuration files (vite.config.ts), your files field in package.json needs to be corrected.
Test your understanding!
Imagine your project directory contains src/, dist/, tests/, package.json, and README.md. Your package.json has "files": ["dist"]. What files would you expect to see in the output of npm pack --dry-run?
Show answer
You would expect to see all the files within the dist/ directory, along with package.json and README.md. Npm automatically includes files like package.json, README.md, and LICENSE even if they aren't explicitly listed in the files array. The contents of src/ and tests/ would be correctly excluded.
Step 2: Validate the Publish Action
Once you're confident about the package contents, you can simulate the entire publish process:
npm publish --dry-run
This command does more than pack. It communicates with the npm registry to check for things like name availability and authentication, then reports what it would have done. It's the final sanity check before going live.
3. Going Live: Publishing to the Registry
With the dry runs completed successfully, you're ready to publish. This process involves two parts: authenticating yourself and running the publish command.
The following video provides a complete end-to-end demonstration, covering login, dealing with common errors, and correctly setting publish flags.
⚡️ Vite - Creating And Publishing NPM package (library)
In his video 'Vite - Creating And Publishing NPM package', Igor Babko walks through the entire process. The final segment is particularly relevant as it covers the actual publishing steps in detail.
Please watch the segment 'Publishing to npm Registry' (32:42 - 42:53). Focus on the npm login process, the error related to private packages, and the use of the --access=public flag for scoped packages.
Step 1: Authenticate with npm
If you haven't already, you'll need an account on npmjs.com. For security, it's highly recommended to enable two-factor authentication (2FA).
Once you have an account, log in via your terminal:
npm login
This will prompt you for your username, password, and (if enabled) a one-time password (OTP) from your authenticator app.
Step 2: Publish
This is the moment of truth. To publish a scoped package for the first time, you must include the --access=public flag. By default, npm assumes new scoped packages are private, which is a paid feature.
npm publish --access=public
If the command succeeds, you'll see a + @your-scope/your-package-name@1.0.0 message. Congratulations, your package is now live on the npm registry! You can view it at https://www.npmjs.com/package/@your-scope/your-package-name.
4. Verification and Future Releases
Publishing isn't the end of the story. It's crucial to verify that your package works for consumers.
The best way to do this is to create a small, separate test project, and install your newly published package just as a user would.
# In a new, separate directory
npm init -y
npm install @your-scope/your-package-name
Then, create a simple index.js or index.ts file and try to import and use your library. This is the ultimate test that your exports map, types, and build artifacts are all configured correctly. The video "How To Build a React UI Library" demonstrates this verification step clearly in its final section (22:50 onwards), even though it uses a React library.
For all future releases, you don't need to perform these steps manually. The release-it workflow we configured in a previous lesson handles this. Simply run:
npx release-it
release-it will prompt you for the version bump, automatically build the project, run npm publish (you may need to add --access=public to the npm config within .release-it.json for the first public release), tag the release in Git, and generate a changelog.
Conclusion
You have officially built and published a modern JavaScript library! This final step transforms your project from a local collection of files into a shareable, versioned, and professional package available to any developer in the world.
Key Takeaways:
- Validate your
package.json: Ensure yournameis unique,privateis false, and thefilesarray correctly whitelists your build artifacts. - Use Dry Runs:
npm pack --dry-runvalidates package contents, andnpm publish --dry-runvalidates the publishing action without making permanent changes. - Publishing Scoped Packages: Use
npm loginto authenticate andnpm publish --access=publicfor the initial public release of a scoped package. - Verify Externally: The ultimate test is to install and use your published package in a completely separate project.
- Automate Future Releases: Leverage your
release-itsetup for all subsequent versions to ensure a consistent and error-free release process.
This concludes our course. You've gone from an empty directory to a fully-realized, documented, tested, and published npm package. Congratulations on this significant achievement! The skills you've honed here are directly applicable to building high-quality, maintainable, and modern JavaScript projects.