or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-bundling.mdindex.mdplugin-system.mdutilities.mdwatch-mode.md

watch-mode.mddocs/

0

# Watch Mode

1

2

Development-focused file watching system that automatically rebuilds when source files change, with comprehensive event handling and error recovery. Rollup's watch mode provides efficient incremental builds and detailed progress reporting.

3

4

## Capabilities

5

6

### Watch Function

7

8

Main watch function that creates a file watcher for automatic rebuilding during development.

9

10

```typescript { .api }

11

/**

12

* Creates a file watcher for automatic rebuilding

13

* @param configs - Watch configuration(s)

14

* @returns RollupWatcher event emitter

15

*/

16

function watch(configs: RollupWatchOptions | RollupWatchOptions[]): RollupWatcher;

17

18

interface RollupWatchOptions extends InputOptions {

19

/** Output configuration */

20

output?: OutputOptions | OutputOptions[];

21

/** Watch-specific options */

22

watch?: WatcherOptions | false;

23

}

24

```

25

26

**Usage Examples:**

27

28

```typescript

29

import { watch } from "rollup";

30

31

// Basic watch setup

32

const watcher = watch({

33

input: "src/main.js",

34

output: {

35

file: "dist/bundle.js",

36

format: "esm"

37

}

38

});

39

40

// Watch with specific options

41

const watcher = watch({

42

input: "src/main.js",

43

output: {

44

file: "dist/bundle.js",

45

format: "esm"

46

},

47

watch: {

48

exclude: "node_modules/**",

49

clearScreen: false

50

}

51

});

52

53

// Multiple configurations

54

const watcher = watch([

55

{

56

input: "src/main.js",

57

output: { file: "dist/esm.js", format: "esm" }

58

},

59

{

60

input: "src/main.js",

61

output: { file: "dist/cjs.js", format: "cjs" }

62

}

63

]);

64

```

65

66

### RollupWatcher Interface

67

68

Event emitter interface for handling watch events and controlling the watcher lifecycle.

69

70

```typescript { .api }

71

/**

72

* Watcher instance for rebuild-on-change functionality

73

*/

74

interface RollupWatcher extends AwaitingEventEmitter<{

75

change: (id: string, change: { event: ChangeEvent }) => void;

76

close: () => void;

77

event: (event: RollupWatcherEvent) => void;

78

restart: () => void;

79

}> {

80

/** Close the watcher and stop watching */

81

close(): Promise<void>;

82

/** Emit an event to all listeners */

83

emit<K extends keyof T>(event: K, ...parameters: Parameters<T[K]>): Promise<unknown>;

84

/** Register an event listener */

85

on<K extends keyof T>(event: K, listener: AwaitedEventListener<T, K>): this;

86

/** Register a one-time event listener */

87

onCurrentRun<K extends keyof T>(event: K, listener: AwaitedEventListener<T, K>): this;

88

/** Remove an event listener */

89

off<K extends keyof T>(event: K, listener: AwaitedEventListener<T, K>): this;

90

/** Remove all listeners */

91

removeAllListeners(): this;

92

/** Remove listeners for current run only */

93

removeListenersForCurrentRun(): this;

94

}

95

96

type ChangeEvent = 'create' | 'update' | 'delete';

97

type AwaitedEventListener<T extends Record<string, (...args: any) => any>, K extends keyof T> =

98

(...parameters: Parameters<T[K]>) => void | Promise<void>;

99

```

100

101

### Event Handling

102

103

Comprehensive event handling for monitoring build progress and responding to file changes.

104

105

```typescript { .api }

106

/**

107

* Event types emitted by the watcher

108

*/

109

type RollupWatcherEvent =

110

| { code: 'START' }

111

| {

112

code: 'BUNDLE_START';

113

input?: InputOption;

114

output: readonly string[];

115

}

116

| {

117

code: 'BUNDLE_END';

118

duration: number;

119

input?: InputOption;

120

output: readonly string[];

121

result: RollupBuild;

122

}

123

| { code: 'END' }

124

| {

125

code: 'ERROR';

126

error: RollupError;

127

result: RollupBuild | null;

128

};

129

```

130

131

**Usage Examples:**

132

133

```typescript

134

import { watch } from "rollup";

135

136

const watcher = watch(config);

137

138

// Handle build events

139

watcher.on('event', (event) => {

140

switch (event.code) {

141

case 'START':

142

console.log('Starting build...');

143

break;

144

case 'BUNDLE_START':

145

console.log(`Building ${event.input}...`);

146

break;

147

case 'BUNDLE_END':

148

console.log(`Built in ${event.duration}ms`);

149

break;

150

case 'END':

151

console.log('Build complete');

152

break;

153

case 'ERROR':

154

console.error('Build error:', event.error);

155

break;

156

}

157

});

158

159

// Handle file changes

160

watcher.on('change', (id, { event }) => {

161

console.log(`File ${event}: ${id}`);

162

});

163

164

// Graceful shutdown

165

process.on('SIGINT', async () => {

166

await watcher.close();

167

process.exit(0);

168

});

169

```

170

171

### Watcher Control

172

173

Methods for controlling watcher behavior and lifecycle.

174

175

```typescript { .api }

176

/**

177

* Close the watcher and stop watching files

178

* @returns Promise that resolves when watcher is closed

179

*/

180

close(): Promise<void>;

181

182

/**

183

* Restart the watcher with current configuration

184

*/

185

restart(): void;

186

```

187

188

**Usage Examples:**

189

190

```typescript

191

// Programmatic control

192

const watcher = watch(config);

193

194

// Restart on command

195

process.on('SIGUSR2', () => {

196

console.log('Restarting watcher...');

197

watcher.restart();

198

});

199

200

// Close watcher

201

setTimeout(async () => {

202

console.log('Closing watcher...');

203

await watcher.close();

204

}, 30000);

205

```

206

207

## Watch Configuration

208

209

### WatcherOptions

210

211

Detailed configuration options for controlling watch behavior.

212

213

```typescript { .api }

214

interface WatcherOptions {

215

/** Allow input files inside output directory */

216

allowInputInsideOutputPath?: boolean;

217

/** Debounce delay for rebuilds (ms) */

218

buildDelay?: number;

219

/** Chokidar file watcher options */

220

chokidar?: ChokidarOptions;

221

/** Clear screen on each rebuild */

222

clearScreen?: boolean;

223

/** Files/patterns to exclude from watching */

224

exclude?: string | RegExp | (string | RegExp)[];

225

/** Files/patterns to include in watching */

226

include?: string | RegExp | (string | RegExp)[];

227

/** Skip writing files (generate only) */

228

skipWrite?: boolean;

229

/** Callback when files are invalidated */

230

onInvalidate?: (id: string) => void;

231

}

232

```

233

234

### Chokidar Integration

235

236

Advanced file watching options via Chokidar integration.

237

238

```typescript { .api }

239

interface ChokidarOptions {

240

/** Files/paths to ignore */

241

ignored?: any;

242

/** Don't emit events for initially added files */

243

ignoreInitial?: boolean;

244

/** Follow symbolic links */

245

followSymlinks?: boolean;

246

/** Base directory for relative paths */

247

cwd?: string;

248

/** Disable globbing */

249

disableGlobbing?: boolean;

250

/** Use polling instead of native events */

251

usePolling?: boolean;

252

/** Polling interval (ms) */

253

interval?: number;

254

/** Binary file polling interval (ms) */

255

binaryInterval?: number;

256

/** Always stat files */

257

alwaysStat?: boolean;

258

/** Maximum depth for recursive watching */

259

depth?: number;

260

/** Wait for write completion */

261

awaitWriteFinish?: boolean | {

262

/** Stability threshold (ms) */

263

stabilityThreshold?: number;

264

/** Poll interval (ms) */

265

pollInterval?: number;

266

};

267

/** Ignore permission errors */

268

ignorePermissionErrors?: boolean;

269

/** Atomic file moves */

270

atomic?: boolean | number;

271

/** Keep process alive */

272

persistent?: boolean;

273

/** Use fsevents on macOS */

274

useFsEvents?: boolean;

275

}

276

```

277

278

## Advanced Watch Patterns

279

280

### Development Server Integration

281

282

```typescript

283

import { watch } from "rollup";

284

import express from "express";

285

286

const app = express();

287

const watcher = watch({

288

input: "src/main.js",

289

output: {

290

file: "dist/bundle.js",

291

format: "esm"

292

},

293

watch: {

294

clearScreen: false,

295

exclude: ["node_modules/**", "dist/**"]

296

}

297

});

298

299

// Serve files

300

app.use(express.static("dist"));

301

302

// Handle build events

303

watcher.on('event', (event) => {

304

if (event.code === 'BUNDLE_END') {

305

console.log('✓ Build complete, files updated');

306

} else if (event.code === 'ERROR') {

307

console.error('✗ Build error:', event.error.message);

308

}

309

});

310

311

app.listen(3000, () => {

312

console.log('Dev server running on http://localhost:3000');

313

});

314

```

315

316

### Conditional Rebuilding

317

318

```typescript

319

import { watch } from "rollup";

320

321

const watcher = watch({

322

input: "src/main.js",

323

output: {

324

file: "dist/bundle.js",

325

format: "esm"

326

},

327

watch: {

328

buildDelay: 1000, // Wait 1s before rebuilding

329

exclude: [

330

"node_modules/**",

331

"**/*.test.js",

332

"docs/**"

333

]

334

}

335

});

336

337

// Custom file change handling

338

watcher.on('change', (id, { event }) => {

339

if (id.includes('.test.')) {

340

console.log('Test file changed, skipping rebuild');

341

return;

342

}

343

344

if (event === 'delete') {

345

console.log(`File deleted: ${id}`);

346

} else {

347

console.log(`File ${event}: ${id}`);

348

}

349

});

350

351

// Error recovery

352

watcher.on('event', (event) => {

353

if (event.code === 'ERROR') {

354

console.error('Build failed:', event.error.message);

355

console.log('Waiting for file changes to retry...');

356

}

357

});

358

```

359

360

### Multi-Config Watch

361

362

```typescript

363

import { watch } from "rollup";

364

365

// Watch multiple build targets

366

const watcher = watch([

367

// Main application

368

{

369

input: "src/main.js",

370

output: {

371

file: "dist/app.js",

372

format: "esm"

373

},

374

watch: {

375

include: "src/**"

376

}

377

},

378

// Service worker

379

{

380

input: "src/sw.js",

381

output: {

382

file: "dist/sw.js",

383

format: "iife"

384

},

385

watch: {

386

include: "src/sw/**"

387

}

388

},

389

// Styles (with different plugin)

390

{

391

input: "src/styles/main.css",

392

output: {

393

file: "dist/styles.css",

394

format: "es"

395

},

396

plugins: [postcss()],

397

watch: {

398

include: "src/styles/**"

399

}

400

}

401

]);

402

403

// Track which configs are building

404

const buildingConfigs = new Set();

405

406

watcher.on('event', (event) => {

407

switch (event.code) {

408

case 'BUNDLE_START':

409

const input = Array.isArray(event.input) ? event.input[0] : event.input;

410

buildingConfigs.add(input);

411

console.log(`Building ${input}... (${buildingConfigs.size} active)`);

412

break;

413

414

case 'BUNDLE_END':

415

const builtInput = Array.isArray(event.input) ? event.input[0] : event.input;

416

buildingConfigs.delete(builtInput);

417

console.log(`✓ Built ${builtInput} in ${event.duration}ms`);

418

break;

419

}

420

});

421

```