How To Deploy An NPM Package
Using Typescript and Rollup.js
Step 1: Create a Project
If you already have a project feel free to skip to Step 2.
Let’s start with a simple project structure: an /src directory where we’ll export index.ts and a package.json.
/src
-index.ts
package.json
We will be exporting a simple function called addTwo
. Add the following to the index.ts file.
export default function addTwo(num:string) {
return num + 2
}
Now, we will begin to install our dependencies.
Step 2: Install Typescript
npm i -D typescript
Because this is a typescript project, we should include a tsconfig.json file to specify the root level and any compiler options. We will use the following simple-case example.
//these options specify where we want our types to be build to
//aswell as specifying what not to include in the compilation
//we do not want to include our built files in dist(we will configure this in a later step) or our node_modules{
"compilerOptions": {
"declaration": true,
"declarationDir": "dist/types",
},
"exclude": ["dist", "node_modules"]
}
try running
tsc
If everything went well you should have a new index.js file in your /src dir.
Now run
tsc --emitDeclarationOnly
You should now have a new /dist directory with an index.d.ts file. These are your types.
Now, let’s install rollup.js
Step 3: Install Rollup.js and Plugins
Rollup compiles your modern modular code back down to other supported formats like CommonJS, AMD, and IIFE-style scripts. We will need the node-resolve plugin so that rollup can locate our modules.
npm i -D rollup @rollup/plugin-node-resolve
Your package.json should now look something like this:
{
"name": "rollup-typescript-starter",
"version": "1.0.0",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"dependencies": {},
"devDependencies": {
"@rollup/plugin-node-resolve": "^7.0.0",
"rollup": "^1.29.0",
"typescript": "^3.9.3"
},
"scripts": {
"build": "rollup -c"
},
"files": [
"dist"
]
}
Now let’s add a rollup.config.js file to the root directory.
import pkg from './package.json';const extensions = ['.js', '.ts']export default [// CommonJS (for Node) and ES module (for bundlers) build.{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs'
},
{
file: pkg.module,
format: 'es'
}
],
plugins: [
resolve({
extensions //specifies the extensions of files that the plugin will operate on
}),
]
}
Now let’s add try to build our code.
npm run build
What happened?
Because we are building using rollup and not through the typescript compiler (tsc
) we must configure a way to remove types through rollup. In comes babel!
Step 4: Install Babel
First, we install babel.
npm i -D @babel/core
Now let’s install the typescript preset. This will remove the types from the typescripts files.
npm i -D @babel/preset-typescript
Next, add a .babelrc file to your root directory.
{"presets": ["@babel/preset-typescript"]}
Finally, install the rollup babel plugin. This will allow rollup to use babel to transpile our typescript files and remove the types.
npm i -D @rollup/plugin-babel
Update your rollup.config.js file
import resolve from '@rollup/plugin-node-resolve';
import pkg from './package.json';
import babel from 'rollup-plugin-babel'const extensions = ['.js', '.ts']export default [// CommonJS (for Node) and ES module (for bundlers) build.{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs'
},
{
file: pkg.module,
format: 'es'
}
],
plugins: [
resolve({
extensions
}),
babel({
exclude: 'node_modules/**',
extensions
}),
],
},
Now let’s try building again
npm run build
Nice!
Step 5: Publish
Ok before we publish we want to make sure we build our types as well so they can be available to people who install the package.
Remember this command.
tsc --emitDeclarationOnly
Let’s add it to our build script in package.json, and while we’re at it let’s clean our /dist directory before every build to ensure that we have the latest build every time.
{
"name": "rollup-typescript-starter",
"version": "1.0.0",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"dependencies": {},
"devDependencies": {
"@rollup/plugin-node-resolve": "^7.0.0",
"rollup": "^1.29.0",
"typescript": "^3.9.3"
},
"scripts": {
"build": "rm -rf dist && rollup -c && tsc --emitDeclarationOnly"
},
"files": [
"dist"
]
}
Now let’s add our publish script.
{
"name": "rollup-typescript-starter",
"version": "1.0.0",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"dependencies": {},
"devDependencies": {
"@rollup/plugin-node-resolve": "^7.0.0",
"rollup": "^1.29.0",
"typescript": "^3.9.3"
},
"scripts": {
"build": "rm -rf dist && rollup -c && tsc --emitDeclarationOnly",
"prepublish:public": "npm run build && npm run bump-version",
"publish:public": "npm publish --access public",
},
"files": [
"dist"
]
}
The ‘pre’ prefix in front of ‘prepublish:public’ means that this script will run before the ‘publish:public’ script.
Now to publish to the npm repository run:
npm run publish:public
Congratulations! Now your package is available in the npm registry.