Skip to main content

Useful JavaScript Tools

Created: December 7, 2025 Larry Qu 7 min read

Overview

JavaScript development in 2026 means navigating a sprawling ecosystem of tools for bundling, linting, testing, formatting, type-checking, and deploying code. This guide covers every major category — with comparison tables, configuration examples, and guidance for choosing the right tool for your project type.

Module Bundlers

Bundlers take your source files (JS, CSS, images) and produce optimized output for production. The 2026 landscape has four dominant players.

Comparison

Feature Vite webpack esbuild Rollup Turbopack
Speed (cold build) ~50ms HMR ~2-5s HMR ~0.1s ~1-2s ~0.05s HMR
Tree-shaking Yes (via Rollup) Yes Yes Best-in-class Yes
Configuration Minimal Verbose Minimal Moderate Minimal
Plugin ecosystem Rich (Vite/Rollup) Largest Growing Mature Early
SSR support Built-in Manual Limited Manual Manual
Dev server Instant Required plugin None None Instant

Vite

Vite uses native ES modules during development for instant server startup and near-instant HMR. It delegates bundling to Rollup for production, giving you both speed and optimal output. Vite dominates new projects in 2026.

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [react(), tailwindcss()],
  build: {
    target: 'es2020',
    minify: 'esbuild',
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
        },
      },
    },
  },
  server: {
    port: 3000,
    open: true,
  },
})

webpack

webpack remains the most configurable bundler with the richest plugin ecosystem. Its complexity is justified for large enterprise apps that need fine-grained control over module resolution, code splitting, and asset handling.

// webpack.config.js
module.exports = {
  entry: './src/index.js',
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  module: {
    rules: [
      { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ },
      { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] },
    ],
  },
  optimization: {
    splitChunks: { chunks: 'all' },
    runtimeChunk: 'single',
  },
}

esbuild

esbuild, written in Go, achieves 10-100x faster builds than JavaScript-based bundlers. Many tools (Vite, Vitest, TSX) use esbuild under the hood for transpilation and minification.

# Bundle and minify a single file
$ esbuild src/app.jsx --bundle --minify --outfile=dist/app.js --target=es2020

# With TypeScript and JSX
$ esbuild src/app.tsx --bundle --format=esm --outdir=dist --loader:.tsx=tsx

Rollup

Rollup produces the smallest bundles thanks to its superior tree-shaking. Library authors still prefer it for publishing npm packages.

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import terser from '@rollup/plugin-terser'
import typescript from '@rollup/plugin-typescript'

export default {
  input: 'src/index.ts',
  output: [
    { file: 'dist/index.cjs', format: 'cjs' },
    { file: 'dist/index.mjs', format: 'esm' },
  ],
  plugins: [resolve(), commonjs(), typescript(), terser()],
}

Turbopack

Turbopack, built by the Vercel team in Rust, targets sub-100ms HMR for large projects. It integrates natively with Next.js but supports standalone usage.

Linters and Formatters

Comparison

Tool Purpose Speed Configurability Language support
ESLint Linting Moderate (flat config) Extremely high JS, TS, JSX, Vue
Prettier Formatting Fast Low (opinionated) 15+ languages
oxc/lint Linting Very fast (Rust) Growing JS, TS
dprint Formatting Very fast (Rust) Moderate JS, TS, JSON, Markdown

ESLint (Flat Config)

ESLint’s flat config system (default since v9) eliminates legacy .eslintrc confusion.

// eslint.config.js
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
import reactHooks from 'eslint-plugin-react-hooks'

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  {
    plugins: { 'react-hooks': reactHooks },
    rules: {
      'react-hooks/exhaustive-deps': 'warn',
      '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
    },
  },
  { ignores: ['dist/**', 'node_modules/**'] },
]

Prettier

Prettier remains the standard for automated formatting. Pair it with ESLint using eslint-config-prettier to avoid rule conflicts.

// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "tabWidth": 2,
  "arrowParens": "always",
  "endOfLine": "lf"
}

oxc (Oxidation Compiler)

oxc is an emerging Rust-based toolchain that provides a linter, parser, and minifier. Its linter (oxlint) runs 50-100x faster than ESLint for large codebases and requires zero configuration for sensible defaults.

# Run oxlint on the project
$ npx oxlint@latest

# With specific rules
$ npx oxlint@latest --deny no-console --allow no-unused-vars

Testing Frameworks

Comparison

Framework Type Speed Assertions Mocking Snapshot E2E
Vitest Unit/Integration Very fast (esbuild) Built-in Built-in Built-in No
Jest Unit/Integration Moderate Built-in Built-in Built-in No
Playwright E2E Fast Built-in No Screenshot Yes
Cypress E2E Moderate Built-in Built-in Screenshot Yes
Testing Library Integration Framework-agnostic External External No No

Vitest

Vitest shares Vite’s config and transformation pipeline, making it the fastest choice for Vite-based projects.

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: './src/test/setup.ts',
    coverage: { provider: 'v8', reporter: ['text', 'html'] },
    include: ['src/**/*.{test,spec}.{ts,tsx}'],
  },
})
// src/components/Counter.test.tsx
import { describe, it, expect } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { Counter } from './Counter'

describe('Counter', () => {
  it('renders initial count', () => {
    render(<Counter />)
    expect(screen.getByText('Count: 0')).toBeDefined()
  })

  it('increments on click', async () => {
    render(<Counter />)
    fireEvent.click(screen.getByRole('button', { name: /increment/i }))
    expect(await screen.findByText('Count: 1')).toBeDefined()
  })
})

Playwright

Playwright executes tests across Chromium, Firefox, and WebKit with auto-waiting, network interception, and trace viewer.

// e2e/checkout.spec.ts
import { test, expect } from '@playwright/test'

test('user completes purchase flow', async ({ page }) => {
  await page.goto('/products')
  await page.click('[data-testid="add-to-cart"]')
  await page.click('[data-testid="checkout"]')
  await page.fill('[name="email"]', '[email protected]')
  await page.fill('[name="card"]', '4242424242424242')
  await page.click('[data-testid="pay-now"]')
  await expect(page.locator('[data-testid="confirmation"]')).toBeVisible()
})
// playwright.config.ts
import { defineConfig } from '@playwright/test'

export default defineConfig({
  testDir: './e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
    { name: 'firefox', use: { browserName: 'firefox' } },
    { name: 'webkit', use: { browserName: 'webkit' } },
  ],
})

Package Managers

npm ships with Node.js and remains the default. Yarn introduced workspaces and offline caching. pnpm uses hard links to save disk space and enforces strict dependency isolation. Bun is a runtime that doubles as a package manager, claiming 10x faster installs.

# Installation speed benchmark (clean install, 50 dependencies)
npm install    # ~15s
yarn install   # ~12s
pnpm install   # ~8s
bun install    # ~2s

Package.json Scripts (Works with Any Package Manager)

{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint src/ && prettier --check src/",
    "format": "prettier --write src/",
    "test": "vitest run",
    "test:watch": "vitest",
    "test:e2e": "playwright test",
    "typecheck": "tsc --noEmit",
    "preview": "vite preview"
  }
}

Type Checkers

TypeScript is the standard. JSDoc annotations offer a lighter alternative for projects that cannot adopt a build step.

// TypeScript: full static type checking
interface User {
  id: string
  email: string
  role: 'admin' | 'user'
}

function formatUser(user: User): string {
  return `${user.email} (${user.role})`
}
// JSDoc: type checking without a build step
/**
 * @param {string} id
 * @param {string} email
 * @param {'admin' | 'user'} role
 * @returns {string}
 */
function formatUser(id, email, role) {
  return `${email} (${role})`
}

Enable JSDoc checking in tsconfig.json:

{
  "compilerOptions": {
    "checkJs": true,
    "allowJs": true,
    "noEmit": true,
    "strict": true,
    "target": "ESNext",
    "moduleResolution": "bundler"
  }
}

Runtime Alternatives

Node.js v22+ dominates server-side JavaScript. Bun and Deno offer compelling alternatives with built-in TypeScript support, modern APIs, and improved developer experience.

Runtime Built-in TS Test runner Package manager Node compat
Node.js Via tsx/ts-node node:test npm/pnpm/yarn Native
Bun Yes Bun:test Bun ~95%
Deno Yes Deno.test deno.land/x ~90%

Meta-Frameworks

Meta-frameworks combine a frontend UI library with routing, SSR, data fetching, and build tooling.

Framework UI Library Rendering Bundle Router File-based Routing Static Export
Next.js React SSR/SSG/ISR Yes Yes Yes (output: export)
Nuxt Vue SSR/SSG Yes Yes Yes
Remix React SSR No (React Router) Yes Yes (via adapter)
SvelteKit Svelte SSR/SSG Yes Yes Yes
Astro Any (islands) SSG/SSR No Yes Yes (default)

Performance Benchmarks

The following figures represent cold build times for an中等-sized application (~500 modules) in 2026:

Tool      | Cold Build | HMR (single edit) | Bundle Size (gzip)
----------|------------|--------------------|---------------------
Vite      | 2.1s       | ~50ms              | 42kB
webpack 5 | 8.4s       | ~300ms             | 44kB
esbuild   | 0.3s       | N/A (no HMR)       | 46kB
Turbopack | 1.2s       | ~30ms              | 43kB

Which Tools to Choose

Project Type Bundler Testing Linting Package Manager
Library (npm package) Rollup + tsup Vitest ESLint + Prettier pnpm
Single-Page App Vite Vitest + Testing Library ESLint + Prettier pnpm
Static Site (SSG) Astro or Next.js Vitest (Astro) / Jest (Next) ESLint + Prettier pnpm
SSR App Next.js / Remix / SvelteKit Vitest + Playwright ESLint + Prettier pnpm
Monorepo Turborepo + Vite Vitest (workspace mode) ESLint + oxlint pnpm
Quick Prototype Vite (vanilla template) Skip or Vitest oxlint (no config) bun

Resources

Comments

Share this article

Scan to read on mobile