DEV Community

ihaback
ihaback

Posted on • Updated on

Create your own typescript library with Parcel.js

If you find yourself writing the same typescript code over and over again it might be time to put this code into a reusable package.

There are many ways of doing this. Bundlers like Rollup has been around for quite some time, but require quite a lot of setup. Modern alternatives like Parcel provides almost zero config out of the box but can also be configured if you have specific requirements.

The finished code

The repo

The published package

Getting started

mkdir parcel-library-starter
Enter fullscreen mode Exit fullscreen mode
cd parcel-library-starter
Enter fullscreen mode Exit fullscreen mode
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install Parcel

npm install --save-dev parcel
Enter fullscreen mode Exit fullscreen mode

Define project configuration in package.json

{
  "name": "@ihaback/your-typescript-lib",
  "version": "1.0.0",
  // The source field defines the entry point for your library
  "source": "src/index.ts",
  // The main field defines the target output of your library
  "main": "dist/main.js"
  // The types field will output a dist/types.d.ts file containing type definitions for your library
  "types": "dist/types.d.ts",
  // To add an ES module target, add the module field to your package.json
  "module": "dist/module.js"
}
Enter fullscreen mode Exit fullscreen mode

Create the entrypoint file in src/index.ts

// Chunk an array into smaller arrays of a specified size
export const chunk = (arr: Array<any>, size: number) => {
  return Array.from({ length: Math.ceil(arr.length / size) }, (_, i) =>
    arr.slice(i * size, i * size + size)
  );
};

Enter fullscreen mode Exit fullscreen mode

Setup a basic tsconfig.json file in the root of the folder

{
    "compilerOptions": {
        "target": "ES5",
        "lib": ["ES2015"],
        "types": ["jest"],
        "esModuleInterop": true
    }
}
Enter fullscreen mode Exit fullscreen mode

Setup a .gitignore file in the root of the folder

node_modules
dist
.parcel-cache
.cache
coverage
Enter fullscreen mode Exit fullscreen mode

Add dev and build commands to package.json

When you build your package Parcel will automatically transpile your code into a dist folder, and generate types that can be used in a repo that consumes this package. The dev command is handy during development.

{
  "scripts": {
    "dev": "parcel watch",
    "build": "parcel build"
  },
}
Enter fullscreen mode Exit fullscreen mode

Add dependencies for basic linting

npm i eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier eslint-config-prettier eslint-plugin-prettier @parcel/packager-ts @parcel/packager-ts @parcel/transformer-typescript-types -D
Enter fullscreen mode Exit fullscreen mode

Add a .eslintrc.js in the root of the project

module.exports = {
    "env": {
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:prettier/recommended"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint",
        "prettier"
    ],
    "rules": {
        "prettier/prettier": [
            "error",
            {
                endOfLine: "auto",
            },
        ]
    }
}

Enter fullscreen mode Exit fullscreen mode

Add a .eslintignore in the root of the project

node_modules
.parcel-cache
dist
.eslintrc.js
package.json
package-lock.json
coverage
Enter fullscreen mode Exit fullscreen mode

Add a lint script to your package.json

{
  "scripts": {
    "lint": "eslint . --fix",
  }
}
Enter fullscreen mode Exit fullscreen mode

Add testing to your project with jest

npm i jest ts-jest @types/jest -D
Enter fullscreen mode Exit fullscreen mode

Add a test for your code in src/index.test.ts

import { chunk } from ".";

describe("chunk", () => {
  test("should chunk array into smaller arrays of a specified size", () => {
    const bigArray = Array.from({ length: 100 }, (v, i) => i);

    const chunkedArray = chunk(bigArray, 25);

    expect(chunkedArray).toHaveLength(4);
  });
  test("should not chunck into multiple arrays if source array is less or equal to chunk size", () => {
    const bigArray = Array.from({ length: 100 }, (v, i) => i);

    const chunkedArray = chunk(bigArray, 100);

    expect(chunkedArray).toHaveLength(1);
  });
});

Enter fullscreen mode Exit fullscreen mode

Add script for triggering tests and update package.json

{
  "scripts": {
    "test": "jest --coverage",
  },
  "jest": {
    "preset": "ts-jest"
  }
}
Enter fullscreen mode Exit fullscreen mode

Prepare to publish your package to npmjs.com

Sign up on npmjs.com

Add a .npmignore file in the root of the project

**/.eslintrc.js
**/.eslintignore
**/.parcel-cache
**/.github/README.md
coverage
Enter fullscreen mode Exit fullscreen mode

Update your package name to include your npmjs.com username

"name": "@your-username-here/your-package-name-here"
Enter fullscreen mode Exit fullscreen mode
"name": "@ihaback/your-typescript-lib"
Enter fullscreen mode Exit fullscreen mode

Publish your package to npmjs.com

npm login
Enter fullscreen mode Exit fullscreen mode
npm publish --access public
Enter fullscreen mode Exit fullscreen mode

Top comments (0)