Top Related Projects
Zero-config CLI for TypeScript package development
The simplest and fastest way to bundle your TypeScript libraries.
📦 Zero-configuration bundler for tiny modules.
Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
Rust-based platform for the Web
Quick Overview
TSDX is a zero-config CLI tool that helps you develop, test, and publish modern TypeScript packages with ease. It provides a streamlined development experience by handling the complex configuration of tools like Rollup, Jest, and TypeScript, allowing developers to focus on writing code rather than managing build processes.
Pros
- Zero-config setup for TypeScript package development
- Optimized build process with Rollup for multiple output formats (CJS, ESM, UMD)
- Integrated testing setup with Jest and code coverage reporting
- Automatic generation of TypeScript declaration files
Cons
- Limited customization options for advanced use cases
- May not be suitable for projects with very specific build requirements
- Learning curve for developers unfamiliar with the TSDX ecosystem
- Potential over-abstraction for simple projects
Code Examples
- Creating a new TSDX project:
npx tsdx create my-library
- Developing with TSDX:
# Run the project in development mode
npm start
# Build the project
npm run build
# Run tests
npm test
- Example of a simple TypeScript function in a TSDX project:
// src/index.ts
export function greet(name: string): string {
return `Hello, ${name}!`;
}
Getting Started
-
Install TSDX globally:
npm install -g tsdx
-
Create a new project:
tsdx create my-library cd my-library
-
Start development:
npm start
-
Write your code in the
src
directory and tests in thetest
directory. -
Build your project:
npm run build
-
Publish your package:
npm publish
Competitor Comparisons
Zero-config CLI for TypeScript package development
Pros of tsdx
- Zero-config CLI for TypeScript package development
- Optimized build process with rollup
- Includes Jest setup for testing
Cons of tsdx
- Limited customization options
- May not be suitable for complex project structures
- Potential for outdated dependencies
Code Comparison
tsdx:
import { sum } from './';
describe('sum', () => {
it('adds two numbers', () => {
expect(sum(1, 2)).toBe(3);
});
});
Both repositories are identical, as they are the same project. The code example above demonstrates a typical test file structure in a tsdx project.
Summary
tsdx is a popular tool for TypeScript package development, offering a streamlined setup process and optimized builds. However, its one-size-fits-all approach may not be suitable for all projects, especially those requiring more complex configurations. The project aims to simplify the development process for TypeScript libraries, but users should be aware of potential limitations in customization and the need to keep dependencies up-to-date.
The simplest and fastest way to bundle your TypeScript libraries.
Pros of tsup
- Faster build times due to esbuild integration
- Supports multiple output formats (ESM, CJS, IIFE) out of the box
- Simpler configuration with fewer dependencies
Cons of tsup
- Less comprehensive testing setup compared to tsdx
- Fewer built-in optimizations for different environments
- May require additional configuration for advanced use cases
Code Comparison
tsup configuration:
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
})
tsdx configuration:
// No explicit configuration needed for basic setup
// tsdx.config.js (optional)
module.exports = {
rollup(config, options) {
return config
},
}
Both tsup and tsdx aim to simplify TypeScript project setup and building, but they take different approaches. tsup leverages esbuild for faster compilation and offers more flexibility in output formats, while tsdx provides a more opinionated and comprehensive development environment with additional features like automatic testing setup and optimizations for different target environments.
The choice between tsup and tsdx depends on project requirements, with tsup being more suitable for simpler projects or those prioritizing build speed, and tsdx offering a more robust solution for complex TypeScript libraries.
📦 Zero-configuration bundler for tiny modules.
Pros of microbundle
- Smaller bundle size and faster build times
- Supports a wider range of module formats (UMD, CJS, ESM)
- More flexible configuration options
Cons of microbundle
- Less opinionated, requiring more setup and configuration
- Fewer built-in development tools and testing features
- Less comprehensive TypeScript support out of the box
Code Comparison
microbundle configuration:
{
"scripts": {
"build": "microbundle",
"dev": "microbundle watch"
}
}
TSDX configuration:
{
"scripts": {
"start": "tsdx watch",
"build": "tsdx build",
"test": "tsdx test"
}
}
microbundle offers more flexibility in configuration, while TSDX provides a more opinionated and streamlined setup. TSDX includes built-in testing and development tools, making it easier to get started with TypeScript projects. However, microbundle's smaller bundle size and support for various module formats make it a strong choice for projects with specific build requirements.
Both tools aim to simplify the process of building and bundling TypeScript libraries, but they cater to different needs and preferences in terms of configuration, features, and project structure.
Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
Pros of ncc
- Simpler setup and usage, requiring fewer configuration steps
- Produces a single file output, making deployment easier
- Supports compilation of non-TypeScript projects
Cons of ncc
- Less flexibility in output formats and configurations
- Limited built-in development tools and testing support
- May not optimize as aggressively for TypeScript-specific features
Code Comparison
ncc:
ncc build input.js -o dist
tsdx:
{
"scripts": {
"build": "tsdx build",
"test": "tsdx test",
"lint": "tsdx lint"
}
}
Key Differences
- ncc focuses on simplicity and single-file output, while tsdx provides a more comprehensive development environment for TypeScript projects
- tsdx offers built-in testing, linting, and development tools, whereas ncc primarily handles compilation and bundling
- ncc can be used for various JavaScript projects, while tsdx is specifically tailored for TypeScript library development
Use Cases
- Choose ncc for quick, simple bundling of Node.js projects or when a single-file output is desired
- Opt for tsdx when developing TypeScript libraries that require a full development toolkit, including testing and linting
Community and Maintenance
Both projects are actively maintained and have strong community support. ncc is backed by Vercel, while tsdx has a dedicated community of contributors.
Rust-based platform for the Web
Pros of SWC
- Significantly faster compilation and bundling compared to TSDX
- Supports a wider range of JavaScript and TypeScript features
- Actively maintained with frequent updates and improvements
Cons of SWC
- Steeper learning curve and more complex configuration
- Less opinionated, requiring more setup for specific use cases
- May have occasional compatibility issues with certain JavaScript/TypeScript features
Code Comparison
TSDX configuration (tsconfig.json):
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"lib": ["dom", "esnext"],
"importHelpers": true,
"declaration": true,
"sourceMap": true
}
}
SWC configuration (.swcrc):
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": true
},
"target": "es5"
},
"module": {
"type": "es6"
}
}
While TSDX provides a more streamlined setup for TypeScript projects, SWC offers greater flexibility and performance at the cost of increased complexity. TSDX is better suited for quick TypeScript library development, while SWC is more powerful for larger projects requiring fine-tuned control over compilation and bundling.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Despite all the recent hype, setting up a new TypeScript (x React) library can be tough. Between Rollup, Jest, tsconfig
, Yarn resolutions, ESLint, and getting VSCode to play nicely....there is just a whole lot of stuff to do (and things to screw up). TSDX is a zero-config CLI that helps you develop, test, and publish modern TypeScript packages with ease--so you can focus on your awesome new library and not waste another afternoon on the configuration.
- Features
- Quick Start
- Optimizations
- Customization
- Inspiration
- API Reference
- Contributing
- Author
- License
- Contributors â¨
Features
TSDX comes with the "battery-pack included" and is part of a complete TypeScript breakfast:
- Bundles your code with Rollup and outputs multiple module formats (CJS & ESM by default, and also UMD if you want) plus development and production builds
- Comes with treeshaking, ready-to-rock lodash optimizations, and minification/compression
- Live reload / watch-mode
- Works with React
- Human readable error messages (and in VSCode-friendly format)
- Bundle size snapshots
- Opt-in to extract
invariant
error codes - Jest test runner setup with sensible defaults via
tsdx test
- ESLint with Prettier setup with sensible defaults via
tsdx lint
- Zero-config, single dependency
- Escape hatches for customization via
.babelrc.js
,jest.config.js
,.eslintrc.js
, andtsdx.config.js
Quick Start
npx tsdx create mylib
cd mylib
yarn start
That's it. You don't need to worry about setting up TypeScript or Rollup or Jest or other plumbing. Just start editing src/index.ts
and go!
Below is a list of commands you will probably find useful:
npm start
or yarn start
Runs the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for your convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab.
Your library will be rebuilt if you make edits.
npm run build
or yarn build
Bundles the package to the dist
folder.
The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module).
npm test
or yarn test
Runs your tests using Jest.
npm run lint
or yarn lint
Runs Eslint with Prettier on .ts and .tsx files.
If you want to customize eslint you can add an eslint
block to your package.json, or you can run yarn lint --write-file
and edit the generated .eslintrc.js
file.
prepare
script
Bundles and packages to the dist
folder.
Runs automatically when you run either npm publish
or yarn publish
. The prepare
script will run the equivalent of npm run build
or yarn build
. It will also be run if your module is installed as a git dependency (ie: "mymodule": "github:myuser/mymodule#some-branch"
) so it can be depended on without checking the transpiled code into git.
Optimizations
Aside from just bundling your module into different formats, TSDX comes with some optimizations for your convenience. They yield objectively better code and smaller bundle sizes.
After TSDX compiles your code with TypeScript, it processes your code with 3 Babel plugins:
babel-plugin-annotate-pure-calls
: Injects for#__PURE
annotations to enable treeshakingbabel-plugin-dev-expressions
: A mirror of Facebook's dev-expression Babel plugin. It reduces or eliminates development checks from production codebabel-plugin-rename-import
: Used to rewrite anylodash
imports
Development-only Expressions + Treeshaking
babel-plugin-annotate-pure-calls
+ babel-plugin-dev-expressions
work together to fully eliminate dead code (aka treeshake) development checks from your production code. Let's look at an example to see how it works.
Imagine our source code is just this:
// ./src/index.ts
export const sum = (a: number, b: number) => {
if (process.env.NODE_ENV !== 'production') {
console.log('Helpful dev-only error message');
}
return a + b;
};
tsdx build
will output an ES module file and 3 CommonJS files (dev, prod, and an entry file). If you want to specify a UMD build, you can do that as well. For brevity, let's examine the CommonJS output (comments added for emphasis):
// Entry File
// ./dist/index.js
'use strict';
// This determines which build to use based on the `NODE_ENV` of your end user.
if (process.env.NODE_ENV === 'production') {
module.exports = require('./mylib.cjs.production.js');
} else {
module.exports = require('./mylib.development.cjs');
}
// CommonJS Development Build
// ./dist/mylib.development.cjs
'use strict';
const sum = (a, b) => {
{
console.log('Helpful dev-only error message');
}
return a + b;
};
exports.sum = sum;
//# sourceMappingURL=mylib.development.cjs.map
// CommonJS Production Build
// ./dist/mylib.cjs.production.js
'use strict';
exports.sum = (s, t) => s + t;
//# sourceMappingURL=test-react-tsdx.cjs.production.js.map
AS you can see, TSDX stripped out the development check from the production code. This allows you to safely add development-only behavior (like more useful error messages) without any production bundle size impact.
For ESM build, it's up to end-user to build environment specific build with NODE_ENV replace (done by Webpack 4 automatically).
Rollup Treeshaking
TSDX's rollup config removes getters and setters on objects so that property access has no side effects. Don't do it.
Advanced babel-plugin-dev-expressions
TSDX will use babel-plugin-dev-expressions
to make the following replacements before treeshaking.
__DEV__
Replaces
if (__DEV__) {
console.log('foo');
}
with
if (process.env.NODE_ENV !== 'production') {
console.log('foo');
}
IMPORTANT: To use __DEV__
in TypeScript, you need to add declare var __DEV__: boolean
somewhere in your project's type path (e.g. ./types/index.d.ts
).
// ./types/index.d.ts
declare var __DEV__: boolean;
Note: The
dev-expression
transform does not run whenNODE_ENV
istest
. As such, if you use__DEV__
, you will need to define it as a global constant in your test environment.
invariant
Replaces
invariant(condition, 'error message here');
with
if (!condition) {
if ('production' !== process.env.NODE_ENV) {
invariant(false, 'error message here');
} else {
invariant(false);
}
}
Note: TSDX doesn't supply an invariant
function for you, you need to import one yourself. We recommend https://github.com/alexreardon/tiny-invariant.
To extract and minify invariant
error codes in production into a static codes.json
file, specify the --extractErrors
flag in command line. For more details see Error extraction docs.
warning
Replaces
warning(condition, 'dev warning here');
with
if ('production' !== process.env.NODE_ENV) {
warning(condition, 'dev warning here');
}
Note: TSDX doesn't supply a warning
function for you, you need to import one yourself. We recommend https://github.com/alexreardon/tiny-warning.
Using lodash
If you want to use a lodash function in your package, TSDX will help you do it the right way so that your library does not get fat shamed on Twitter. However, before you continue, seriously consider rolling whatever function you are about to use on your own. Anyways, here is how to do it right.
First, install lodash
and lodash-es
as dependencies
yarn add lodash lodash-es
Now install @types/lodash
to your development dependencies.
yarn add @types/lodash --dev
Import your lodash method however you want, TSDX will optimize it like so.
// ./src/index.ts
import kebabCase from 'lodash/kebabCase';
export const KebabLogger = (msg: string) => {
console.log(kebabCase(msg));
};
For brevity let's look at the ES module output.
import o from"lodash-es/kebabCase";const e=e=>{console.log(o(e))};export{e as KebabLogger};
//# sourceMappingURL=test-react-tsdx.esm.production.js.map
TSDX will rewrite your import kebabCase from 'lodash/kebabCase'
to import o from 'lodash-es/kebabCase'
. This allows your library to be treeshakable to end consumers while allowing to you to use @types/lodash
for free.
Note: TSDX will also transform destructured imports. For example,
import { kebabCase } from 'lodash'
would have also been transformed to `import o from "lodash-es/kebabCase".
Error extraction
After running --extractErrors
, you will have a ./errors/codes.json
file with all your extracted invariant
error codes. This process scans your production code and swaps out your invariant
error message strings for a corresponding error code (just like React!). This extraction only works if your error checking/warning is done by a function called invariant
.
Note: We don't provide this function for you, it is up to you how you want it to behave. For example, you can use either tiny-invariant
or tiny-warning
, but you must then import the module as a variable called invariant
and it should have the same type signature.
â ï¸Don't forget: you will need to host the decoder somewhere. Once you have a URL, look at ./errors/ErrorProd.js
and replace the reactjs.org
URL with yours.
Known issue: our
transformErrorMessages
babel plugin currently doesn't have sourcemap support, so you will see "Sourcemap is likely to be incorrect" warnings. We would love your help on this.
TODO: Simple guide to host error codes to be completed
Customization
Rollup
ââ ï¸â Warning:
These modifications will override the default behavior and configuration of TSDX. As such they can invalidate internal guarantees and assumptions. These types of changes can break internal behavior and can be very fragile against updates. Use with discretion!
TSDX uses Rollup under the hood. The defaults are solid for most packages (Formik uses the defaults!). However, if you do wish to alter the rollup configuration, you can do so by creating a file called tsdx.config.js
at the root of your project like so:
// Not transpiled with TypeScript or Babel, so use plain Es6/Node.js!
module.exports = {
// This function will run for each entry/format/env combination
rollup(config, options) {
return config; // always return a config.
},
};
The options
object contains the following:
export interface TsdxOptions {
// path to file
input: string;
// Name of package
name: string;
// JS target
target: 'node' | 'browser';
// Module format
format: 'cjs' | 'umd' | 'esm' | 'system';
// Environment
env: 'development' | 'production';
// Path to tsconfig file
tsconfig?: string;
// Is error extraction running?
extractErrors?: boolean;
// Is minifying?
minify?: boolean;
// Is this the very first rollup config (and thus should one-off metadata be extracted)?
writeMeta?: boolean;
// Only transpile, do not type check (makes compilation faster)
transpileOnly?: boolean;
}
Example: Adding Postcss
const postcss = require('rollup-plugin-postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = {
rollup(config, options) {
config.plugins.push(
postcss({
plugins: [
autoprefixer(),
cssnano({
preset: 'default',
}),
],
inject: false,
// only write out CSS for the first bundle (avoids pointless extra files):
extract: !!options.writeMeta,
})
);
return config;
},
};
Babel
You can add your own .babelrc
to the root of your project and TSDX will merge it with its own Babel transforms (which are mostly for optimization), putting any new presets and plugins at the end of its list.
Jest
You can add your own jest.config.js
to the root of your project and TSDX will shallow merge it with its own Jest config.
ESLint
You can add your own .eslintrc.js
to the root of your project and TSDX will deep merge it with its own ESLint config.
patch-package
If you still need more customizations, we recommend using patch-package
so you don't need to fork.
Keep in mind that these types of changes may be quite fragile against version updates.
Inspiration
TSDX was originally ripped out of Formik's build tooling. TSDX has several similarities to @developit/microbundle, but that is because Formik's Rollup configuration and Microbundle's internals had converged around similar plugins.
Comparison with Microbundle
Some key differences include:
- TSDX includes out-of-the-box test running via Jest
- TSDX includes out-of-the-box linting and formatting via ESLint and Prettier
- TSDX includes a bootstrap command with a few package templates
- TSDX allows for some lightweight customization
- TSDX is TypeScript focused, but also supports plain JavaScript
- TSDX outputs distinct development and production builds (like React does) for CJS and UMD builds. This means you can include rich error messages and other dev-friendly goodies without sacrificing final bundle size.
API Reference
tsdx watch
Description
Rebuilds on any change
Usage
$ tsdx watch [options]
Options
-i, --entry Entry module
--target Specify your target environment (default web)
--name Specify name exposed in UMD builds
--format Specify module format(s) (default cjs,esm)
--tsconfig Specify your custom tsconfig path (default <root-folder>/tsconfig.json)
--verbose Keep outdated console output in watch mode instead of clearing the screen
--onFirstSuccess Run a command on the first successful build
--onSuccess Run a command on a successful build
--onFailure Run a command on a failed build
--noClean Don't clean the dist folder
--transpileOnly Skip type checking
-h, --help Displays this message
Examples
$ tsdx watch --entry src/foo.tsx
$ tsdx watch --target node
$ tsdx watch --name Foo
$ tsdx watch --format cjs,esm,umd
$ tsdx watch --tsconfig ./tsconfig.foo.json
$ tsdx watch --noClean
$ tsdx watch --onFirstSuccess "echo The first successful build!"
$ tsdx watch --onSuccess "echo Successful build!"
$ tsdx watch --onFailure "echo The build failed!"
$ tsdx watch --transpileOnly
tsdx build
Description
Build your project once and exit
Usage
$ tsdx build [options]
Options
-i, --entry Entry module
--target Specify your target environment (default web)
--name Specify name exposed in UMD builds
--format Specify module format(s) (default cjs,esm)
--extractErrors Opt-in to extracting invariant error codes
--tsconfig Specify your custom tsconfig path (default <root-folder>/tsconfig.json)
--transpileOnly Skip type checking
-h, --help Displays this message
Examples
$ tsdx build --entry src/foo.tsx
$ tsdx build --target node
$ tsdx build --name Foo
$ tsdx build --format cjs,esm,umd
$ tsdx build --extractErrors
$ tsdx build --tsconfig ./tsconfig.foo.json
$ tsdx build --transpileOnly
tsdx test
This runs Jest, forwarding all CLI flags to it. See https://jestjs.io for options. For example, if you would like to run in watch mode, you can run tsdx test --watch
. So you could set up your package.json
scripts
like:
{
"scripts": {
"test": "tsdx test",
"test:watch": "tsdx test --watch",
"test:coverage": "tsdx test --coverage"
}
}
tsdx lint
Description
Run eslint with Prettier
Usage
$ tsdx lint [options]
Options
--fix Fixes fixable errors and warnings
--ignore-pattern Ignore a pattern
--max-warnings Exits with non-zero error code if number of warnings exceed this number (default Infinity)
--write-file Write the config file locally
--report-file Write JSON report to file locally
-h, --help Displays this message
Examples
$ tsdx lint src
$ tsdx lint src --fix
$ tsdx lint src test --ignore-pattern test/foo.ts
$ tsdx lint src test --max-warnings 10
$ tsdx lint src --write-file
$ tsdx lint src --report-file report.json
Contributing
Please see the Contributing Guidelines.
Author
License
Contributors â¨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
Top Related Projects
Zero-config CLI for TypeScript package development
The simplest and fastest way to bundle your TypeScript libraries.
📦 Zero-configuration bundler for tiny modules.
Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
Rust-based platform for the Web
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot