Publish NPM Typescript package with ECMA and CommonJS support
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.