Building and Publishing Your TypeScript Code as a NPM Package
João Textor
Posted on October 3, 2023
I love open-source software. The previous couple of weeks, I posted about how I created a key generator and how I tested the code using jest.
Today, time has come to publish that code as a library on npmjs.com, so it can be consumed by anyone.
Are you ready for this?
Table of Contents
- TL;DR
- First, the requirements
- Dependency installing
- Logging in to npm
- Configuring tsconfig.json
- Configure package.json
- Building our project
- Testing
- Publishing
TL;DR
This article explains how to publish a TypeScript project as an open-source library on npmjs.com. It covers the following steps:
- Ensure you have an npmjs.com account and a suitable npm version.
- Install the
tsup
library for bundling TypeScript projects. - Log in to your npmjs.com account using the npm CLI.
- Configure your tsconfig.json file with specific options.
- Set up your package.json file with essential package details.
- Use the
fix-tsup-cjs
library to improve CommonJS module usage. - Build your project with
npm run build
. - Test the installation with
npm install . -g
. - Finally, publish your package to npmjs.com with
npm publish
.
First, the requirements
First of all, before we start the publishing process, we need to make sure:
- We've created and account on npmjs.com.
- Our npm version is at least 9.8 (I've used 10.1, but 9.8 is fine)
Dependency installing
We are going to use a library called tsup
to bundle our TypeScript project. So, make sure you install it by running:
npm install tsup --save
Logging in to npm
After you've created your account on npmjs.com, login to it using the npm cli. You can type it using the terminal inside VS Code if you want:
npm login
After hitting 'Enter', you'll see the following message.
Just hit 'Enter' again to open the login page in your web browser. You will receive an One-time Password, so check your email and paste it in the form.
Your CLI should show a message like this: Logged in on https://registry.npmjs.org/.
You are good to continue!
Configuring tsconfig.json
Here we are making some configuration so tsup
creates the bundle correctly.
Here are the options you should enable in your tsconfig.json (some may already be enabled):
{
"compilerOptions": {
/* Language and Environment */
"target": "ES2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
/* Modules */
"module": "CommonJS" /* Specify what module code is generated. */,
"noEmit": true /* Disable emitting files from a compilation. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
"noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */,
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["./"],
"exclude": ["node_modules"] // which files to skip
}
Configure package.json
Configuring the package.json
file correctly is a crucial part in packaging and publishing your code to npmjs.com, so I will briefly describe the configurations I make.
First, let's see the configuration file, and later I will explain it.
{
"name": "easy-key-generator",
"version": "1.1.9",
"description": "Easy library for generating secret keys.
It supports various features like groups, separators,
key format, and the possibility of generating multiples
keys at once.",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"dev": "tsc --watch",
"build": "tsup index.ts --format cjs,esm --dts && npx fix-tsup-cjs",
"lint": "tsc",
"test": "jest"
},
"author": "João Textor",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/joaotextor/easy-key-generator"
},
"keywords": [
"key generator",
"code generator"
],
"devDependencies": {
"@types/jest": "^29.5.5",
"@typescript-eslint/eslint-plugin": "^6.7.0",
"@typescript-eslint/parser": "^6.7.0",
"eslint": "^8.49.0",
"jest": "^29.7.0",
"prettier": "^3.0.3",
"ts-jest": "^29.1.1",
"tsup": "^7.2.0",
"typescript": "^5.2.2"
}
}
- name is the name of your package. Try choosing an unique one. Search for existing packages in npmjs.com.
- version: self-explanatory. I started with 1.0.0, but you're free to choose what you want. Be aware that each time you publish to npmjs.com, the next time it must contain a newer version.
- description: this is where you briefly describe what your packages does.
-
main: this is where you declare the path to your main bundled file (which not yet exists). This is the javascript file which users will import using
import
. -
module: this is the bundled javascript file to be imported using
require
, as a commonJS module. -
types: the path to your
d.ts
file, which contains your types. -
scripts: here we created a
build
script that will calltsup
to bundle ourindex.ts
, which is our project's main file; we've passed the option --format withcjs,esm
params, which will create the commonJS file and a ES Module file; finally, the --dts option is tellingtsup
to create our type file withd.ts
extension. Next we will callnpx fix-tsup-cjs
. Why? I'll explain later on. - author: This is where you put your name, so everyone can blame you publicly if your library introduce bugs into their projects (just kidding...or not!)
- license: You can inform an open-source license here if you want.
- repository: want to make easier for people to yell at you online? Place the repository to your library here 😅. They might also submit a PR to fix your undesired bugs 😄.
Explaining the npx fix-tsup-cjs
When bundling your project using tsup
, you might notice that when importing the CommonJs module using something like const KeyGenerator = require("easy-key-generator");
when calling your class' constructor you must type this: new KeyGenerator.default()
. Also, when calling a method, let's say generate()
, you need to call it by using KeyGenerator.default().generate
.
This sucks, right? Why can't you instantiate your class by using only KeyGenerator()
?
Well, the library fix-tsup-cjs
enables you to do exactly that, that's why we executed it after bundling our project using tsup
.
Building our project
Well, now that everything is setup correctly, is time for us to build our project.
Just type npm run build
in your terminal in the root of your project and hit 'Enter'.
Testing
Before publishing the package, your should test installing it.
To test the install, type npm install . -g
in the root of your project. NPM should be able to install it globally as any other package.
If anything goes wrong in this step, it means something is wrong with your configuration.
Publishing
Finally, it's time to publish your package to npmjs.com. Type npm publish
, get your fingers crossed and TA-DA!
Congratulations, you've successfully published your TypeScript code to npmjs.com! It is now available to the npm community.
In this guide, we've covered the essential steps to publish your TypeScript project on npmjs.com. By following these steps and maintaining your package, you can share your code with the world and contribute to the open-source community. Happy coding!
If you did read through the entire post until here, please leave a reaction and a comment, and hit the follow button because next week we will be learning how to automatize the work of publishing a node package by using GitHub Actions!
Until next week!
Posted on October 3, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.