npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@tsmodule/tsmodule

v44.7.0

Published

Create standardized TypeScript ESM packages for Node or browser.

Downloads

845

Readme

Create standardized TypeScript ESM packages for Node or browser. Includes --bundle and --binary build options, powered by esbuild.

Table of contents

Installation

Requirements (global)

  • Node v14+ (for ESM support)
  • PNPM

Existing projects

To convert an existing project (and install standardized package.json settings, dependencies, and config files), run this in your project directory:

tsmodule convert

You will need to move all TS source files to src/ if they are not there already. Ensure you read the module configuration notes regarding "index exports" as it relates to importing downstream.

New projects

Create a new package with:

tsmodule create [--react] project-name

Purpose

Create ESM packages using TypeScript

tsmodule create exists to bootstrap a Node or React project in as little time as possible. The created packages are modular, and tsmodule create --react will create a modular Next.js project with importable components and styles.

Ready out of the box:

  • package.json scripts
  • TypeScript, ESLint configs (Tailwind, PostCSS for React)
  • CI/CD with GitHub Actions

Develop projects in real-time

Build in dev mode and watch for changes:

tsmodule dev

Build to optimized ES modules

Production builds are minified ESM, with support for my-package/a/b/c path resolution (see Module configuration below).

tsmodule build [--bundle]

All projects:

  • Emit pure ESM, no polyfilling to CJS
  • Emit ESNext by default, no polyfilling to older feature sets

React projects created with create --react:

  • Bundle CSS by default
  • Use Tailwind by default

Optimize NPM dependencies with build --bundle

With -b, --bundle mode, all entry points are compiled "in-place" and runtime NPM dependencies will generally not be needed as they will be inlined. If you build in bundle mode, you can move your dependencies to devDependencies, as the only thing that will be needed to run any/all compiled-in-place entry point(s) in your module are the bundles themselves.

TSModule itself builds with -b, --bundle flag, and requires only three runtime NPM dependencies:

  1. esbuild, which does the heavy lifting for the build process, does not allow itself to be bundled;
  2. typescript, so TSModule can use the built tsc binary to generate .d.ts type declarations during builds; and
  3. pkg, for building binaries with build --binary (a specific standalone bundle mode).

Note: Bundling every entry point in place may not be what you want, i.e. if you only have a single entrypoint. In these cases, tsmodule build -b src/index.ts is more appropriate.

Build executable binaries with build --binary

Uses Vercel's pkg to build binaries from src/bin.ts.

IMPORTANT: This requires coercing to CJS, which is not possible if your program uses top-level await. For now, replace with async closures and monitor this issue for updates on full ESM support.

Run TypeScript directly

tsmodule file.ts
  • Uses Node module loader to resolve TS at runtime
  • Executable TypeScript files with #!/usr/bin/env tsmodule

Use Cases

Below are some example use cases of TS modules in practice.

Generic TypeScript library

The most common type of library will be a TS module with generic TypeScript exports in src/**/index.ts, e.g. universal-shell, a Promise wrapper around child_process.spawn that's used in tsmodule itself.

This library contains only one export, at src/index.ts (a function called shell), but you could import e.g. import { test } from "my-package/path/to/export" by exporting that identifier at src/path/to/export/index.ts.

React component library (using Next.js)

tsmodule create --react creates a TS module which is also a Next app; pages are in src/pages, and components are in src/components. Tailwind, PostCSS, and postcss-import are all supported by default.

CSS will be bundled from src/components/index.css and exported at my-package/styles, which the package.json style field also points to (for postcss-import support), so that components packages are modular.

{
  "style": "./dist/components/index.css",
  "exports": {
    ".": "./dist/index.js",
    "./*": "./dist/components/*/index.js",
    "./styles": "./dist/components/index.css",
    "./styles/*": "./dist/components/*/index.css",
    "./package.json": "./package.json"
  },
}

To use a component downstream, import the styles into the page, e.g.:

// src/pages/_app.tsx
import "my-package/styles";

Or in CSS (resolved by postcss-import using "style" field in package.json):

@import "my-package";

And render your component:

// src/pages/test.tsx
import { MyComponent } from "my-package";

export default function TestPage() {
  return (
    <MyComponent />
  );
}

Footnotes

Module configuration

All packages built with tsmodule build are ES modules. { "type": "module" } is forced to minimize ambiguity.

tsmodule build also forces the following tsconfig.json values during the type-check and declaration emit:

{
  "rootDir": "src/",
  "outDir": "dist/",
}

Index exports

Conditional exports in package.json are configured such that "index exports" are available at a subpath. For example:

src/a/b/c/index.ts

Will be available downstream via:

import { c } from "your-package/a/b/c"

Notes:

  • Index exports are the only entry points available for import, are ones located at src/**/index.ts(x?).1

  • The default package entry point for your-package is src/index.ts.

1 This has no restriction on internal imports between files, which can import from each other freely, including at runtime. However, consumers of your package will only be able to import from index exports as shown.

Package.json export

For information on why the "./package.json": "./package.json" export is specified, see #1.

License

MIT © C. Lewis