Skip to content

PlayForm/Build

Build 🌀

Build is a powerful tool that compiles all your TypeScript files into JavaScript, leveraging the speed of ESBuild and the type-checking capabilities of the TypeScript compiler.

Feature 📦

  • Fast compilation using ESBuild
  • TypeScript support with type-checking (tsc & tsc-alias)
  • Watch mode for development (--Watch)
  • Customizable ESBuild configuration via object or function (--ESBuild)
  • Supports both CommonJS and ES modules
  • Glob pattern support for input files
  • Exclusion patterns for input files

Installation 🚀

Install the package as a development dependency:

# Using npm npm install -D -E @playform/build # Or using yarn # yarn add -D -E @playform/build # Or using pnpm # pnpm add -D -E @playform/build

Usage 🛠️

Command Line

Run the build tool from the command line, providing file patterns:

npx @playform/build 'Source/**/*.ts' 'OtherSource/**/*.mts'

CLI Options

Usage: Build [options] <File...> Arguments: File One or more glob patterns matching files to build 📝 Options: -V, --version Output the version number -E, --ESBuild <File> Path to a custom ESBuild configuration file (exports an object or a function) 📜 -T, --TypeScript <File> Path to a custom TypeScript configuration file (default: "tsconfig.json") 📜 -W, --Watch Enable watch mode: rebuild on file changes 👁️ -h, --help Display help information 

NPM Scripts

Add Build to your package.json scripts:

{ "scripts": { "Build": "Build 'Source/**/*.ts'", "Run": "Build 'Source/**/*.ts' --Watch", "prepublishOnly": "Build 'Source/**/*.ts'"	} }

Configuration ⚙️

ESBuild Configuration (--ESBuild) 📜

You can provide a custom configuration file to modify the default ESBuild options used by @playform/build. This file (e.g., ESBuild.js or esbuild.config.ts) should use export default with either a configuration object or a function.

1. Exporting an Object:

Provide an object with ESBuild options. These will be merged with the base configuration.

// ESBuild.js /** @type {import('esbuild').BuildOptions} */ const config = { minify: true, sourcemap: "external", platform: "node", // Add other esbuild options here }; export default config;

2. Exporting a Function:

Provide a function that receives the current ESBuild configuration object (BuildOptions from esbuild) as its argument. You can modify this object directly or return a new (partial) object containing options to be merged. This allows for dynamic configuration, such as filtering entry points.

// ESBuild.js /**  * @param {import('esbuild').BuildOptions} Current The configuration object before this function runs.  * @returns {import('esbuild').BuildOptions | void} Return changes to merge, or modify Current directly.  */ export default (Current) => { console.log("Applying custom ESBuild function..."); // Example: Filter out test files from entry points if (Array.isArray(Current.entryPoints)) { Current.entryPoints = Current.entryPoints.filter( (entry) => !/\.(test|spec)\.[mc]?[jt]s$/.test(entry), ); console.log("Filtered entry points:", Current.entryPoints); } // Example: Modify the config directly Current.define = {	...(Current.define ?? {}), // Preserve existing defines "process.env.BUILD_TIME": `"${new Date().toISOString()}"`, }; // Example: Return additional options to merge return { banner: { js: "// Generated by @playform/build", }, logLevel: "info", }; // If you only modify 'Current' directly, you can simply have no return: // return; // or return undefined; };

Usage:

Specify the path to your configuration file using the --ESBuild option:

npx @playform/build 'Source/**/*.ts' --ESBuild ESBuild.ts

See the base configuration used internally in Source/Variable/ESBuild.ts (link might need adjustment based on your actual path).

TypeScript Configuration (--TypeScript) 📜

By default, Build looks for tsconfig.json in the current working directory. You can specify a different path using the --TypeScript option. This tsconfig.json is used by ESBuild for path resolution and by the tsc and tsc-alias commands run after the build for type checking and path alias replacement.

A typical tsconfig.json might look like this:

// tsconfig.json { "compilerOptions": { // --- Essential for tsc/tsc-alias --- "outDir": "Target", // Must match esbuild's outdir/outfile directory "rootDir": "Source", // Or your source root "baseUrl": ".", // Often needed for path aliases "paths": { // Example alias - must match esbuild alias config if used "@/*": ["Source/*"]	}, // --- Type Checking Options --- "strict": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, // --- Module Settings (match esbuild target/format) --- "target": "ES2020", "module": "ESNext", // or CommonJS "moduleResolution": "node", // or node16/nodenext // --- Interoperability --- "esModuleInterop": true, "allowSyntheticDefaultImports": true, // --- Other --- "resolveJsonModule": true, "isolatedModules": true, // Good practice with transpilers like esbuild "noEmit": true // Important: Set noEmit to true as esbuild handles file emission	}, // Use @playform/build's base config for sensible defaults (optional) // "extends": "@playform/build/tsconfig", "include": ["Source/**/*"], // Files to be type-checked "exclude": ["node_modules", "Target"] // Exclude output and dependencies }

Important: Ensure compilerOptions.outDir in your tsconfig.json aligns with the output directory configured for ESBuild (either via the default Source/Variable/ESBuild.ts or your custom --ESBuild config). Also, set "noEmit": true as esbuild handles the file generation; tsc is only used for type checking here.

JSConfig Configuration (Optional) 📜

If you are working with JavaScript and JSDoc for type checking, you can use a jsconfig.json file instead of tsconfig.json. The principles are similar.

// jsconfig.json { "compilerOptions": { "outDir": "Target", "rootDir": "Source", "checkJs": true, // Enable type checking for JS files "target": "ES2020", "module": "ESNext", // or CommonJS "moduleResolution": "node", // or node16/nodenext "baseUrl": ".", "paths": { "@/*": ["Source/*"]	}, "noEmit": true // Still important	}, "extends": "@playform/build/jsconfig", // If you provide a base jsconfig "include": ["Source/**/*"], "exclude": ["node_modules", "Target"] }

Remember to pass the path to this file if it's not named tsconfig.json (even if it's a JS project, the default flag might still look for tsconfig.json unless you explicitly pass --TypeScript jsconfig.json).

Contributing 🤝

Contributions are welcome! Please see CONTRIBUTING.md for guidelines and feel free to submit a Pull Request.

Changelog

See CHANGELOG.md for a history of changes to this component.