diff --git a/packages/devextreme-vue/gulpfile.js b/packages/devextreme-vue/gulpfile.js index 66653047b468..9b16501973be 100644 --- a/packages/devextreme-vue/gulpfile.js +++ b/packages/devextreme-vue/gulpfile.js @@ -6,6 +6,7 @@ const header = require('gulp-header'); const ts = require('gulp-typescript'); const config = require('./build.config'); const generateVueComponents = require('devextreme-internal-tools').generateVueComponents; +const path = require("path"); const GENERATE = 'generate'; const CLEAN = 'clean'; @@ -15,7 +16,10 @@ const NPM_PACKAGE = 'npm.package'; const NPM_LICENSE = 'npm.license'; const ADD_HEADERS = 'npm.license-headers'; const NPM_README = 'npm.readme'; +const NPM_BUILD_ESM = "npm.build-esm"; +const NPM_BUILD_CJS = "npm.build-cjs"; const NPM_BUILD = 'npm.build'; +const NPM_PREPARE_MODULES = "npm.prepare-modules"; const NPM_PACK = 'npm.pack'; const VUE_VERSION = 3; @@ -60,20 +64,67 @@ gulp.task(NPM_README, () => gulp.src(config.npm.readme).pipe(gulp.dest(config.npm.dist)) ); -gulp.task(NPM_BUILD, gulp.series( - gulp.parallel(NPM_LICENSE, NPM_PACKAGE, NPM_README), - () => { - return gulp.src([ - config.src, - ...config.ignoredGlobs - ]) - .pipe(ts('tsconfig.json')) - .pipe(gulp.dest(config.npm.dist)); - } -)); +gulp.task( + NPM_BUILD_ESM, + gulp.series(() => + gulp + .src([config.src, `!${config.testSrc}`]) + .pipe(ts("tsconfig.esm.json")) + .pipe(gulp.dest(config.npm.dist + "/esm")) + ) +); + +gulp.task( + NPM_BUILD_CJS, + gulp.series(() => + gulp + .src([config.src, `!${config.testSrc}`]) + .pipe(ts("tsconfig.json")) + .pipe(gulp.dest(config.npm.dist + "/cjs")) + ) +); + +gulp.task( + NPM_BUILD, + gulp.series( + gulp.parallel( + NPM_LICENSE, + NPM_PACKAGE, + NPM_README, + NPM_BUILD_ESM, + NPM_BUILD_CJS + ) + ) +); + +gulp.task(NPM_PREPARE_MODULES, (done) => { + const packParamsForFolders = [ + ["common"], + ["core", ["config"]], + ["common/data"], + ]; + const modulesImportsFromIndex = fs.readFileSync( + config.npm.dist + "esm/index.js", + "utf8" + ); + const modulesPaths = modulesImportsFromIndex.matchAll(/from "\.\/([^;]+)";/g); + const packParamsForModules = [...modulesPaths].map(([, modulePath]) => { + const [, , moduleFilePath, moduleFileName] = + modulePath.match(/((.*)\/)?([^/]+$)/); + + return ["", [moduleFileName], moduleFilePath]; + }); + + [...packParamsForFolders, ...packParamsForModules].forEach( + ([folder, moduleFileNames, moduleFilePath]) => + makeModule(folder, moduleFileNames, moduleFilePath) + ); + + done(); +}); gulp.task(ADD_HEADERS, function () { - const pkg = require('./package.json'); + const pkg = require("./package.json"); const now = new Date(); const data = { pkg: pkg, @@ -105,6 +156,63 @@ gulp.task(ADD_HEADERS, function () { gulp.task(NPM_PACK, gulp.series( NPM_CLEAN, NPM_BUILD, + NPM_PREPARE_MODULES, ADD_HEADERS, shell.task(['npm pack'], {cwd: config.npm.dist}) )); + +function makeModule(folder, moduleFileNames, moduleFilePath) { + const distFolder = path.join(__dirname, config.npm.dist); + const distModuleFolder = path.join(distFolder, folder); + const distEsmFolder = path.join(distFolder, 'esm', folder); + const moduleNames = moduleFileNames || findJsModuleFileNamesInFolder(distEsmFolder); + + try { + if (!fs.existsSync(distModuleFolder)) { + fs.mkdirSync(distModuleFolder); + } + + if (folder && fs.existsSync(path.join(distEsmFolder, 'index.js'))) { + generatePackageJsonFile(folder); + } + + moduleNames.forEach((moduleFileName) => { + fs.mkdirSync(path.join(distModuleFolder, moduleFileName)); + + generatePackageJsonFile(folder, moduleFileName, moduleFilePath); + }) + } catch (error) { + error.message = `Exception while makeModule(${folder}).\n ${error.message}`; + throw (error); + } +} + +function generatePackageJsonFile(folder, moduleFileName, filePath = folder) { + const moduleName = moduleFileName || ''; + const absoluteModulePath = path.join(__dirname, config.npm.dist, folder, moduleName); + const moduleFilePath = (filePath ? filePath + '/' : '') + (moduleName || 'index'); + const relativePath = path.relative( + absoluteModulePath, + path.join(__dirname, config.npm.dist, 'esm', moduleFilePath + '.js'), + ); + + const relativeBase = '../'.repeat(relativePath.split('..').length - 1); + + fs.writeFileSync(path.join(absoluteModulePath, 'package.json'), JSON.stringify({ + sideEffects: false, + main: `${relativeBase}cjs/${moduleFilePath}.js`, + module: `${relativeBase}esm/${moduleFilePath}.js`, + typings: `${relativeBase}cjs/${moduleFilePath}.d.ts`, + }, null, 2)); +} + +function findJsModuleFileNamesInFolder(dir) { + return fs.readdirSync(dir).filter((file) => { + const filePath = path.join(dir, file); + + return !fs.statSync(filePath).isDirectory() + && file.includes('.js') + && !file.includes('index.js') + }, + ).map((filePath) => path.parse(filePath).name); +} diff --git a/packages/devextreme-vue/package.json b/packages/devextreme-vue/package.json index 7eab9560977b..5ea0d1094f19 100644 --- a/packages/devextreme-vue/package.json +++ b/packages/devextreme-vue/package.json @@ -6,8 +6,9 @@ "type": "git", "url": "https://github.com/DevExpress/devextreme-vue.git" }, - "main": "index.js", - "types": "index.d.ts", + "main": "./cjs/index.js", + "module": "./esm/index.js", + "types": "./cjs/index.d.ts", "scripts": { "clean": "gulp clean", "regenerate": "npm run clean && gulp generate", diff --git a/packages/devextreme-vue/tsconfig.esm.json b/packages/devextreme-vue/tsconfig.esm.json new file mode 100644 index 000000000000..fb8210fa87cb --- /dev/null +++ b/packages/devextreme-vue/tsconfig.esm.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "esnext", + "moduleResolution": "node", + "declaration": false + } +}