Publish NPM Typescript package with ECMA and CommonJS support

Literally You
3 min readJul 11, 2022

--

This tutorial assume you are already familiar with GitHub, Git, Typescript and “How to contribute to a project on Github?” .

Before we start. Create a public GitHub repository. Clone it to your local development environment. Now, follow the steps below.

  • Create package.json file with npm init -y
  • Install Typescript npm install typescript
  • Create typescript config file named tsconfig.json with following content:
{
"compilerOptions": {
"target": "ES2017",
"strict": true,
"moduleResolution": "Node",

"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": true,
"preserveConstEnums": true,
"allowJs": false,
"forceConsistentCasingInFileNames": true
},
"include": ["src"],
"exclude": ["node_modules", "**/__tests__/*","lib"]
}

“compilerOptions.moduleResolution” resolves problem specified here.

Come up with desired ES version in “compilerOptions.target”. Rest of compilerOptions are project-specific and described here.

Fields “exclude” and “include” are important. Do not change.

  • Add /lib and /node_modules directories to .gitignore

Lib directory contains output of our bundled library. That is what actually npm install your-awesome-lib saves to node_modules when developer install your package.

  • Create file tsconfig.cjs.json

This one will generate CommonJS files in directory lib/cjs

{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"sourceMap": false,

"outDir": "lib/cjs",
},
}
  • Create file tsconfig.esm.json

Besides ES output in lib/esm this config generates *.d.ts files with information about types in separate lib/types directory .

{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "esnext",
"outDir": "lib/esm",
"declaration": true,
"declarationDir": "lib/types",
"sourceMap": false
},
"exclude": [
"node_modules",
"**/__tests__/*"
]
}
  • Fill package.json fields

Add "name": "your-awesome-lib". Name of your library goes here. This should be unique in npm registry.

You should not touch "version": "1.0.0" of your package. Use npm-version command for versioning your library.

Choose "licence": "MIT". Make your code free for all. Additionally you can add field with your username or real name: "author": "SmartestMan" .

NPM is GitHub-friendly. Put your repository link here "repository": "github-user/your-awesome-lib-project".

Add script to bundle both ECMAScript and CommonJs code to /lib directory: "build": "tsc — project tsconfig.esm.json & tsc — project tsconfig.cjs.json" .

Add ESLint npm install eslint --save-dev && eslint --init .

The script list below helps with automation of your versioning and publishing routine.

"fix": "eslint --fix \"src/**\"",
"lint": "eslint \"src/**\"",
"prepare": "npm run build",
"prepublishOnly": "npm run lint",
"preversion": "npm run lint",
"version": "npm run fix && git add -A src",
"postversion": "git push && git push --tags"

Important section! Support wider range of target platforms. Let NPM know where different types of bundle located.

"exports": {
"node": {
"require": "./lib/cjs/index.js",
"import": "./lib/esm/index.js"
},
"browser": "./lib/esm/index.js"
},
"main": "./lib/cjs/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/types/index.d.ts",

This properties help npm resolve path to library based on runtime environment. No matter browser or NodeJS, typescript or native javascript target project use.

  • Create src/index.ts file with all exports provided.

All code of your library is imported from index.ts . To make your code tree-shakable do separate logic as following:

// src/index.ts
import awesomeUtil from './awesomeUtil'
export * from './awesomeUtil'
export {
useBool,
}
// src/awesomeUtil.ts
export type AwesomeUtilReturnValue= string|null|number
const awesomeUtil = ()=>{
//Do some awesome stuff
return 'Amazing!
}
export default awesomeUtil
  • Finally, publish your package!

Run npm publish command. You will be prompted to login your npm account, or create a new one. Your code is automatically compiled, pushed to GitHub and becomes available with npm install your-awesome-lib or yarn add your-awesome-lib command for any user in the internet.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Literally You
Literally You

Written by Literally You

A nicheless blog where I leave my digital footprint on the internet. Sharing professional skills, experience, lifestyle, ideas, science and more.

No responses yet

Write a response