Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ pnpm run all:build # full production build
pnpm nx build:dev devextreme # single package, dev mode
pnpm nx build devextreme -c=testing # CI testing configuration
pnpm nx build:transpile devextreme # transpile only (babel-transform / build-typescript)
pnpm nx build:transpile:watch devextreme # transpile in watch mode (incremental JS + TS rebuild)
pnpm nx transpile:tests devextreme # transpile testing/**/*.js in place (replaces gulp transpile-tests)
pnpm nx dev devextreme # build:dev, then start all dev watches (replaces gulp dev)
pnpm nx dev-watch devextreme # start all dev watches in parallel, skipping the initial build
pnpm nx bundle:debug devextreme # debug bundle (Webpack via nx-infra-plugin)
pnpm nx bundle:prod devextreme # production bundle
pnpm nx build:localization devextreme # localization files only
Expand Down Expand Up @@ -197,7 +201,7 @@ For the full executor catalogue, conventions, and refactoring guidance, see @pac

## Build Pipeline

clean (`devextreme-nx-infra-plugin:clean` preserving CSS and npm metadata) → localization → component generation (Renovation) → transpile (`babel-transform` for JS, `build-typescript` for TS) → bundle (Webpack via `devextreme-nx-infra-plugin:bundle`, debug + prod targets) → TypeScript declarations → SCSS compile (`devextreme-scss`) → npm package preparation. Task orchestration goes through Nx; cross-package builds (`all:build-dev`, `all:build`) live in the `workflows` package. The `gulpfile.js` clean task is a thin delegate to `pnpm nx clean:artifacts devextreme`. Pre-commit hook runs `lint-staged` (stylelint + eslint --quiet).
clean (`devextreme-nx-infra-plugin:clean` preserving CSS and npm metadata) → localization → component generation (Renovation) → transpile (`babel-transform` for JS, `build-typescript` for TS) → bundle (Webpack via `devextreme-nx-infra-plugin:bundle`, debug + prod targets) → TypeScript declarations → SCSS compile (`devextreme-scss`) → npm package preparation. Task orchestration goes through Nx; cross-package builds (`all:build-dev`, `all:build`) live in the `workflows` package. The `gulpfile.js` clean task is a thin delegate to `pnpm nx clean:artifacts devextreme`. Pre-commit hook runs `lint-staged` (stylelint + eslint --quiet). The developer watch workflow (`pnpm run dev` / `dev:watch`) is now native composite Nx targets (`dev`, `dev-watch`) rather than gulp orchestrators — see the "Migrated gulp tasks" table in @packages/nx-infra-plugin/AGENTS.md.

## Conventions

Expand Down
2 changes: 0 additions & 2 deletions packages/devextreme/build/gulp/bundler-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,3 @@ const shell = require('gulp-shell');
gulp.task('bundler-config', shell.task(
'pnpm nx build:devextreme-bundler-config devextreme && pnpm nx build:devextreme-bundler-config devextreme -c prod'
));

gulp.task('bundler-config-watch', shell.task('pnpm nx build:devextreme-bundler-config:watch devextreme'));
1 change: 0 additions & 1 deletion packages/devextreme/build/gulp/transpile-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
const common = {
plugins: [
['babel-plugin-inferno', { 'imports': true }],
['@babel/plugin-transform-object-rest-spread', { loose: true }],
],
ignore: ['**/*.json'],
};
Expand Down
82 changes: 2 additions & 80 deletions packages/devextreme/build/gulp/transpile.js
Original file line number Diff line number Diff line change
@@ -1,84 +1,6 @@
'use strict';

const babel = require('gulp-babel');
const gulp = require('gulp');
const notify = require('gulp-notify');
const path = require('path');
const plumber = require('gulp-plumber');
const replace = require('gulp-replace');
const watch = require('gulp-watch');
const shell = require('gulp-shell');

const ctx = require('./context.js');
const testsConfig = require('../../testing/tests.babelrc.json');
const transpileConfig = require('./transpile-config');
const createTsCompiler = require('./typescript/compiler');

const REMOVE_DEBUG_REGEXP = /\/{2,}\s{0,}#DEBUG[\s\S]*?\/{2,}\s{0,}#ENDDEBUG/g;

const src = [
'js/**/*.*',
'!js/**/*.d.ts',
'!js/**/*.{tsx,ts}',
'!js/__internal/**/*.*',
];

const TS_OUTPUT_BASE_DIR = 'artifacts/dist_ts';
const TS_COMPILER_CONFIG = {
baseAbsPath: path.resolve(__dirname, '../..'),
relativePath: {
tsconfig: 'js/__internal/tsconfig.json',
alias: 'js',
dist: TS_OUTPUT_BASE_DIR,
},
tsBaseDirName: '__internal',
messages: {
createDirErr: 'Cannot create directory',
createFileErr: 'Cannot create file',
compilationFailed: 'TS Compilation failed',
},
};

const watchJsTask = () => {
const watchTask = watch(src)
.on('ready', () => console.log('transpile JS is watching for changes...'))
.pipe(plumber({
errorHandler: notify
.onError('Error: <%= error.message %>')
.bind() // bind call is necessary to prevent firing 'end' event in notify.onError implementation
}));
watchTask
.pipe(babel(transpileConfig.cjs))
.pipe(gulp.dest(ctx.TRANSPILED_PATH));
watchTask
.pipe(replace(REMOVE_DEBUG_REGEXP, ''))
.pipe(babel(transpileConfig.cjs))
.pipe(gulp.dest(ctx.TRANSPILED_PROD_RENOVATION_PATH));
return watchTask;
};
watchJsTask.displayName = 'transpile JS watch';

const watchTsTask = async() => {
const compiler = await createTsCompiler(TS_COMPILER_CONFIG);
const tsWatch = compiler.watchTs();

tsWatch
.pipe(plumber({
errorHandler: notify
.onError('Error: <%= error.message %>')
.bind() // bind call is necessary to prevent firing 'end' event in notify.onError implementation
}))
.pipe(babel(transpileConfig.tsCjs))
.pipe(gulp.dest(ctx.TRANSPILED_PATH))
.pipe(replace(REMOVE_DEBUG_REGEXP, ''))
.pipe(gulp.dest(ctx.TRANSPILED_PROD_RENOVATION_PATH));
};
watchTsTask.displayName = 'transpile TS watch';

gulp.task('transpile-watch', gulp.parallel(watchJsTask, watchTsTask));

gulp.task('transpile-tests', gulp.series('bundler-config', () =>
gulp
.src(['testing/**/*.js'])
.pipe(babel(testsConfig))
.pipe(gulp.dest('testing'))
));
gulp.task('transpile-tests', shell.task('pnpm nx transpile:tests devextreme'));
36 changes: 7 additions & 29 deletions packages/devextreme/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ gulp.task('js-bundles-debug', shell.task(
: 'pnpm nx run devextreme:bundle:debug'
));

gulp.task('js-bundles-watch', shell.task(
context.uglify
? 'pnpm nx run devextreme:bundle:watch -c production'
: 'pnpm nx run devextreme:bundle:watch'
));

function getTranspileConfig() {
if(env.TEST_CI) {
return 'ci';
Expand Down Expand Up @@ -120,9 +114,9 @@ function createMiscBatch() {
return gulp.parallel(tasks);
}

function createMainBatch(dev) {
function createMainBatch() {
const tasks = [];
if(!dev && !env.BUILD_TESTCAFE) {
if(!env.BUILD_TESTCAFE) {
tasks.push('js-bundles-debug');
}
if(!env.TEST_CI || env.BUILD_TESTCAFE) {
Expand All @@ -132,40 +126,24 @@ function createMainBatch(dev) {
return (callback) => multiProcess(tasks, callback, true);
}

function createDefaultBatch(dev) {
const tasks = dev ? [] : ['clean'];
function createDefaultBatch() {
const tasks = ['clean'];
tasks.push('localization');
tasks.push('transpile');

if(REMOVE_NON_PRODUCTION_MODULE) {
tasks.push('state-manager-optimize');
}

tasks.push(dev && !env.BUILD_TESTCAFE ? 'main-batch-dev' : 'main-batch');
if(!env.TEST_CI && !dev && !env.BUILD_TESTCAFE) {
tasks.push('main-batch');
if(!env.TEST_CI && !env.BUILD_TESTCAFE) {
tasks.push('npm');
tasks.push('check-license-notices');
}
return gulp.series(tasks);
}

gulp.task('misc-batch', createMiscBatch());
gulp.task('main-batch', createMainBatch(false));
gulp.task('main-batch-dev', createMainBatch(true));
gulp.task('main-batch', createMainBatch());

gulp.task('default', createDefaultBatch());
gulp.task('default-dev', createDefaultBatch(true));

gulp.task('test-env', shell.task('pnpm nx test-env devextreme'));

gulp.task('dev-watch', gulp.parallel(
'transpile-watch',
'bundler-config-watch',
'js-bundles-watch',
'test-env'
));

gulp.task('dev', gulp.series(
'default-dev',
'dev-watch'
));
6 changes: 4 additions & 2 deletions packages/devextreme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
"@babel/eslint-parser": "catalog:",
"@babel/plugin-proposal-decorators": "7.29.7",
"@babel/plugin-transform-modules-commonjs": "7.29.7",
"@babel/plugin-transform-nullish-coalescing-operator": "7.29.7",
"@babel/plugin-transform-optional-chaining": "7.29.7",
"@babel/plugin-transform-runtime": "7.29.7",
"@babel/plugin-transform-typescript": "7.29.7",
"@babel/preset-env": "7.29.7",
Expand Down Expand Up @@ -191,8 +193,8 @@
"build:modular": "cd ./playground/modular && webpack",
"build:modular:watch": "cd ./playground/modular && webpack --watch",
"build:community-localization": "pnpm nx build:community-localization devextreme",
"dev": "cross-env DEVEXTREME_TEST_CI=true gulp dev",
"dev:watch": "cross-env DEVEXTREME_TEST_CI=true gulp dev-watch",
"dev": "cross-env DEVEXTREME_TEST_CI=true nx run devextreme:dev",
"dev:watch": "cross-env DEVEXTREME_TEST_CI=true nx run devextreme:dev-watch",
"dev:playground": "vite",
"transpile-tests": "gulp transpile-tests",
"update-ts-reexports": "dx-tools generate-reexports --sources ./js --exclude \"((dialog|export|list_light|notify|overlay|palette|set_template_engine|splitter_control|themes|themes_callback|track_bar|utils|validation_engine|validation_message)[.d.ts])\" --compiler-options \"{ \\\"typeRoots\\\": [] }\"",
Expand Down
121 changes: 115 additions & 6 deletions packages/devextreme/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,18 @@
"{projectRoot}/artifacts/dist_ts"
]
},
"build:ts:internal:watch": {
"executor": "devextreme-nx-infra-plugin:build-typescript",
"cache": false,
"options": {
"srcPattern": "./js/__internal/**/*.{ts,tsx}",
"tsconfig": "./js/__internal/tsconfig.json",
"outDir": "./artifacts/dist_ts",
"resolvePaths": true,
"resolvePathsBaseDir": "./js",
"watch": true
}
},
"build:cjs": {
"executor": "devextreme-nx-infra-plugin:babel-transform",
"options": {
Expand Down Expand Up @@ -268,6 +280,31 @@
"{projectRoot}/artifacts/transpiled-renovation-npm"
]
},
"build:cjs:watch": {
"executor": "devextreme-nx-infra-plugin:babel-transform",
"cache": false,
"options": {
"babelConfigPath": "./build/gulp/transpile-config.js",
"configKey": "cjs",
"sourcePattern": "./js/**/*.{js,jsx}",
"excludePatterns": [
"./js/**/*.d.ts",
"./js/__internal/**/*"
],
"outDir": "./artifacts/transpiled",
"watch": true,
"copyAssets": [
{ "from": "./js/localization/messages", "to": "./localization/messages" },
{ "from": "./js/viz/vector_map.utils/_settings.json", "to": "./viz/vector_map.utils/_settings.json" }
]
},
"configurations": {
"production": {
"outDir": "./artifacts/transpiled-renovation-npm",
"removeDebug": true
}
}
},
"build:npm:esm": {
"executor": "devextreme-nx-infra-plugin:babel-transform",
"options": {
Expand Down Expand Up @@ -341,6 +378,26 @@
"{projectRoot}/artifacts/transpiled-renovation-npm/__internal"
]
},
"build:cjs:internal:watch": {
"executor": "devextreme-nx-infra-plugin:babel-transform",
"cache": false,
"options": {
"babelConfigPath": "./build/gulp/transpile-config.js",
"configKey": "tsCjs",
"sourcePattern": "./artifacts/dist_ts/__internal/**/*.{js,jsx}",
"outDir": "./artifacts/transpiled/__internal",
"renameExtensions": {
".jsx": ".js"
},
"watch": true
},
"configurations": {
"production": {
"outDir": "./artifacts/transpiled-renovation-npm/__internal",
"removeDebug": true
}
}
},
"build:npm:esm:internal": {
"executor": "devextreme-nx-infra-plugin:babel-transform",
"options": {
Expand Down Expand Up @@ -507,6 +564,34 @@
}
}
},
"build:transpile:watch": {
"executor": "nx:run-commands",
"cache": false,
"options": {
"commands": [
"pnpm nx build:ts:internal:watch devextreme",
"pnpm nx build:cjs:watch devextreme",
"pnpm nx build:cjs:watch devextreme -c production",
"pnpm nx build:cjs:internal:watch devextreme",
"pnpm nx build:cjs:internal:watch devextreme -c production"
],
"cwd": "{projectRoot}",
"parallel": true
},
"dependsOn": ["build:ts:internal"]
},
"transpile:tests": {
"executor": "devextreme-nx-infra-plugin:babel-transform",
"cache": false,
"options": {
"babelConfigPath": "./testing/tests.babelrc.json",
"sourcePattern": "./testing/**/*.js",
"outDir": "./testing"
},
"dependsOn": [
"build:devextreme-bundler-config"
]
},
"state-manager:optimize": {
"executor": "devextreme-nx-infra-plugin:state-manager-optimize",
"options": {
Expand Down Expand Up @@ -1691,13 +1776,37 @@
"cache": true
},
"dev": {
"executor": "nx:run-script",
"options": {
"script": "dev"
},
"executor": "nx:run-commands",
"cache": false,
"dependsOn": [
"^build"
]
"build:dev"
],
"options": {
"cwd": "{projectRoot}",
"command": "pnpm nx dev-watch devextreme"
}
},
"dev-watch": {
"executor": "nx:run-commands",
"cache": false,
"options": {
"cwd": "{projectRoot}",
"parallel": true,
"commands": [
"pnpm nx build:transpile:watch devextreme",
"pnpm nx build:devextreme-bundler-config:watch devextreme",
"pnpm nx bundle:watch devextreme",
"pnpm nx test-env devextreme"
]
}
},
"test-env": {
"executor": "nx:run-commands",
"cache": false,
"options": {
"command": "node ./testing/launch",
"cwd": "{projectRoot}"
}
},
"test-env": {
"executor": "nx:run-commands",
Expand Down
2 changes: 1 addition & 1 deletion packages/devextreme/testing/tests.babelrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"presets": [["@babel/preset-env", { "modules": false }]],
"plugins": [
["transform-es2015-modules-commonjs", { "strict": false, "allowTopLevelThis": true }, "add-module-exports"],
["@babel/plugin-transform-modules-commonjs", { "strict": false, "allowTopLevelThis": true }, "add-module-exports"],
"@babel/plugin-transform-nullish-coalescing-operator", "@babel/plugin-transform-optional-chaining"
],
"ignore": ["**/*.json"]
Expand Down
Loading
Loading