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

  • New Grunt task: react
  • Dev variant: react:dev

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

  1. Generates TypeScript path aliases.
  2. Builds platform bootstrap code (react_autoinit).
  3. Builds plugin/core React component bundles.

Context-aware grunt from React source directories

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

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

Watch mode supports React TS/TSX files

grunt watch monitors js/react/src/**/*.ts and js/react/src/**/*.tsx and then:

  1. Runs eslint:react-check (check-only, no auto-fix).
  2. Runs reactbuild to rebuild only changed files.

This avoids watch loops caused by lint auto-fixes rewriting files.

React linting tasks are split by behavior

  • grunt eslint:react uses ESLint with fix: true
  • grunt eslint:react-check runs without auto-fix (used by watch)

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/react/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 package handling is defined for esbuild

The externals plugin (.esbuild/externals.mjs) marks these imports as external:

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

This ensures shared runtime packages are not duplicated in each bundle.

Directory conventions

React source and output follow this structure per component:

<component>/
└── js/
└── react/
├── 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 for JS/React changes
grunt watch

# React lint with auto-fix
grunt eslint:react

# React lint check-only
grunt eslint:react-check

See also

  • Grunt - How to install Grunt and Watchman