Skip to main content
Version: main (5.2)

Build tools

Moodle provides React TypeScript component builds using esbuild integrated with Grunt. This page focuses on the React build toolchain used in Moodle.

What is covered

React build is integrated into Grunt

React is part of the JavaScript build pipeline alongside AMD and YUI. All JS build orchestration lives in .grunt/tasks/javascript.js.

New Grunt task: react, with three modes:

CommandDescription
grunt reactProduction build (minified, no sourcemaps)
grunt react:devDevelopment build (inline sourcemaps, no minification)
grunt react:watchesbuild native watch mode (see below)

Build orchestration is handled by .esbuild/build.mjs, which:

  1. Generates TypeScript path aliases.
  2. Builds all plugin and core React component bundles.

Context-aware grunt from React source directories

Running grunt in js/esm/src now triggers grunt react.

cd public/mod/book/js/esm/src
grunt

Watch mode uses esbuild native context

grunt react:watch uses esbuild's own context.watch() to monitor React source files. This is intentionally separate from grunt watch — esbuild maintains an incremental build graph internally, so rebuilds reuse the previous parse result rather than restarting from scratch on every change.

After each rebuild, ESLint runs on the changed source files in check-only mode (no --fix) to avoid re-triggering esbuild with auto-fixed rewrites.

grunt react:watch
warning

grunt watch does not monitor React files.

React linting

  • grunt eslint:react — runs ESLint with fix: true (auto-fix)

Cross-component alias generation is automatic

Aliases like @moodle/lms/<component>/* are generated from Moodle component metadata.

  • Generator: .esbuild/generate-aliases.mjs
  • Output: tsconfig.aliases.json
  • Source of truth: .grunt/components.js

Only components with real TypeScript files under js/esm/src are included.

What tsconfig.aliases.json is for

tsconfig.aliases.json is generated during the React build and provides TypeScript path mappings for the @moodle/lms/* aliases used in React source code. It is read by tsconfig.json so that editors and type-checking can resolve cross-component imports correctly.

warning

Do not edit tsconfig.aliases.json manually. It is generated by grunt react.

External packages are excluded from bundles

The following imports are marked as external in the esbuild configuration and are not bundled into component output:

  • react
  • react/*
  • react-dom
  • react-dom/*
  • @moodle/lms
  • @moodle/lms/*
  • @moodlehq/design-system
  • @moodlehq/design-system/*

This ensures shared runtime packages are not duplicated across bundles.

Directory conventions

React source and output follow this structure per component:

<component>/
└── js/
└── esm/
├── src/ # TypeScript/TSX source
└── build/ # Generated ES module output

Commands for developers

# Build all React components (production)
grunt react

# Build all React components (development)
grunt react:dev

# Watch React files with esbuild native watch
grunt react:watch

# React lint with auto-fix
grunt eslint:react

See also

  • Grunt - How to install Grunt and Watchman