From 36ce4e0ea1591a8c55028ea4a92dd70fae9f79a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A1ra=20El-Saig?= Date: Tue, 6 Feb 2024 17:36:29 +0100 Subject: [PATCH 1/3] Compile and minify JS scripts programmatically, use separate config for mjs files. --- .../config/babel.module.config.json | 21 ++++++ Lombiq.NodeJs.Extensions/package.json | 6 +- Lombiq.NodeJs.Extensions/pnpm-lock.yaml | 23 +++--- .../scripts/compile-scripts.js | 39 +++++++++++ Lombiq.NodeJs.Extensions/scripts/minify.js | 70 ------------------- Readme.md | 2 +- 6 files changed, 72 insertions(+), 89 deletions(-) create mode 100644 Lombiq.NodeJs.Extensions/config/babel.module.config.json create mode 100644 Lombiq.NodeJs.Extensions/scripts/compile-scripts.js delete mode 100644 Lombiq.NodeJs.Extensions/scripts/minify.js diff --git a/Lombiq.NodeJs.Extensions/config/babel.module.config.json b/Lombiq.NodeJs.Extensions/config/babel.module.config.json new file mode 100644 index 00000000..7d637229 --- /dev/null +++ b/Lombiq.NodeJs.Extensions/config/babel.module.config.json @@ -0,0 +1,21 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "browsers": [ + ">0.2%", + "not dead", + "not op_mini all" + ] + }, + "exclude": ["transform-async-to-generator", "transform-regenerator"], + "modules": false, + "loose": true + } + ] + ], + "sourceMaps": "inline", + "targets": "defaults" +} diff --git a/Lombiq.NodeJs.Extensions/package.json b/Lombiq.NodeJs.Extensions/package.json index 04f4731a..48bf2a1e 100644 --- a/Lombiq.NodeJs.Extensions/package.json +++ b/Lombiq.NodeJs.Extensions/package.json @@ -13,7 +13,7 @@ "copyfiles": "2.4.1", "eslint": "8.47.0", "if-env": "1.0.4", - "klaw": "4.1.0", + "glob": "10.3.10", "markdownlint": "0.30.0", "nodemon": "3.0.1", "npm-run-all": "4.1.5", @@ -71,9 +71,7 @@ "---": "------------------------------------------------- SCRIPTS ------------------------------------------------", "build:scripts": "SRC=$(node scripts/get-path js source) && if-env SRC=! && echo \"Skipping scripts\" && exit 0 || run-p --print-name --continue-on-error lint:scripts compile:scripts", "lint:scripts": "SRC=$(node scripts/get-path js source) && node scripts/lint-scripts \"$SRC\" || AREA=scripts STEP=linting pnpm error", - "compile:scripts": "SRC=$(node scripts/get-path js source) && if-env SRC=! && echo \"Skipping scripts\" && exit 0 || DEST=$(node scripts/get-path js target) run-s --print-name _compile:scripts _minify:scripts", - "_compile:scripts": "babel \"$SRC\" --out-dir \"$DEST\" --config-file \"${INIT_CWD}/config/babel.config.json\" || AREA=scripts STEP=compilation pnpm error", - "_minify:scripts": "node scripts/minify \"$DEST\" || AREA=scripts STEP=minifying pnpm error", + "compile:scripts": "SRC=$(node scripts/get-path js source) DEST=$(node scripts/get-path js target) && if-env SRC=! && echo \"Skipping scripts\" && exit 0 || node scripts/compile-scripts \"$SRC\" \"$DEST\" \"${INIT_CWD}/config/\" || AREA=scripts STEP=compilation pnpm error", "clean:scripts": "DEST=$(node scripts/get-path js target) && rimraf \"$DEST/**/*.*\"", "watch:scripts": "SRC=$(node scripts/get-path js source) && nodemon --watch \"$SRC\" --exec \"pnpm build:scripts\"", "----": "------------------------------------------------ MARKDOWN -----------------------------------------------", diff --git a/Lombiq.NodeJs.Extensions/pnpm-lock.yaml b/Lombiq.NodeJs.Extensions/pnpm-lock.yaml index 3b85458a..f35ebe87 100644 --- a/Lombiq.NodeJs.Extensions/pnpm-lock.yaml +++ b/Lombiq.NodeJs.Extensions/pnpm-lock.yaml @@ -32,12 +32,12 @@ dependencies: eslint: specifier: 8.47.0 version: 8.47.0 + glob: + specifier: 10.3.10 + version: 10.3.10 if-env: specifier: 1.0.4 version: 1.0.4 - klaw: - specifier: 4.1.0 - version: 4.1.0 markdownlint: specifier: 0.30.0 version: 0.30.0 @@ -3462,13 +3462,13 @@ packages: dependencies: is-glob: 4.0.3 - /glob@10.3.3: - resolution: {integrity: sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==} + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true dependencies: foreground-child: 3.1.1 - jackspeak: 2.3.0 + jackspeak: 2.3.6 minimatch: 9.0.3 minipass: 7.0.3 path-scurry: 1.10.1 @@ -3970,8 +3970,8 @@ packages: istanbul-lib-report: 3.0.1 dev: true - /jackspeak@2.3.0: - resolution: {integrity: sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==} + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} dependencies: '@isaacs/cliui': 8.0.2 @@ -4468,11 +4468,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /klaw@4.1.0: - resolution: {integrity: sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw==} - engines: {node: '>=14.14.0'} - dev: false - /kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -5809,7 +5804,7 @@ packages: engines: {node: '>=14'} hasBin: true dependencies: - glob: 10.3.3 + glob: 10.3.10 dev: false /run-parallel@1.2.0: diff --git a/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js b/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js new file mode 100644 index 00000000..435c0369 --- /dev/null +++ b/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js @@ -0,0 +1,39 @@ +const babel = require('@babel/core'); +const path = require('path'); +const process = require('process'); + +const { glob } = require('glob'); +const { minify } = require("terser"); +const { readFile, writeFile, mkdir } = require('fs').promises; + +const { handleErrorObjectAndExit } = require('./handle-error'); + +const [ sourcePath, destinationPath, configPath ] = process.argv.slice(2); + +function readJsonConfig(fileName) { + return readFile(path.join(configPath, fileName), 'utf8') + .then(text => JSON.parse(text)); +} + +async function compileScripts() { + const browserConfig = readJsonConfig('babel.config.json'); + const moduleConfig = readJsonConfig('babel.module.config.json'); + const scriptFiles = await glob('/**/*.{js,mjs}', { root: sourcePath, ignore: 'node_modules/**' }); + + await Promise.all(scriptFiles.map(async filePath => { + const config = filePath.toLowerCase().endsWith('.mjs') ? moduleConfig : browserConfig; + const result = await babel.transformFileAsync(filePath, config); + + const destinationFilePath = path.join(destinationPath, path.relative(sourcePath, filePath)) + await mkdir(path.dirname(destinationFilePath), { recursive: true }); + await writeFile(destinationFilePath, result.code); + + const minifiedPath = destinationFilePath.replace(/\.(m?js)$/, '.min.$1') + const sourceMapOptions = { content: 'inline', url : path.basename(minifiedPath) + '.map' }; + const minifiedCode = await minify(result.code, { sourceMap: sourceMapOptions }); + await writeFile(minifiedPath, minifiedCode.code); + await writeFile(minifiedPath + ".map", minifiedCode.map); + })); +} + +compileScripts().catch(handleErrorObjectAndExit); \ No newline at end of file diff --git a/Lombiq.NodeJs.Extensions/scripts/minify.js b/Lombiq.NodeJs.Extensions/scripts/minify.js deleted file mode 100644 index 4e6ebb56..00000000 --- a/Lombiq.NodeJs.Extensions/scripts/minify.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @summary A wrapper script to allow minification per file as opposed to minification into a single output file. - */ - -/* eslint-disable no-console -- Writing to the console is part of the functionality of this script. */ - -const path = require('path'); -const exec = require('child_process').exec; - -/* eslint-disable-next-line import/no-unresolved -- ESLint does not know where to find external modules; ignore. */ -const walk = require('klaw'); // #spell-check-ignore-line - -const { handleErrorObject, handleErrorObjectAndExit } = require('./handle-error'); - -// Get the target folder from the invocation. -const args = process.argv.slice(2); - -if (args.length !== 1) { - handleErrorObjectAndExit(new Error('Please provide the directory to process as the only argument.')); -} - -// Switch to the desired working directory. -process.chdir(args[0]); - -// We only walk inside this path so it doesn't matter if it's symlinked or not (no need for get-cwd.js). -const workingDir = process.cwd(); -console.debug(`Minifying files in "${workingDir}"...`); - -const fsItems = []; -// Walk the directory tree. -walk(workingDir) - .on('data', (item) => fsItems.push(item)) - .on('end', () => { - fsItems.forEach((item) => { - const isFile = item.stats.isFile(); - const filePath = item.path; - - // We only care for .js files. - if (!isFile || !filePath.endsWith('.js') || filePath.endsWith('.min.js')) return; - - const destination = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js'); - const sourceMapUrl = path.basename(destination) + '.map'; - - // Prefer the terser CLI for simplicity over the API. See https://github.com/terser/terser for details. - const command = [ - 'terser', - `"${filePath}"`, - `--output "${destination}"`, - '--compress', - '--mangle', - `--source-map "content=inline,url='${sourceMapUrl}'"`, - ].join(' '); - - exec(command, (err, stdout, stderr) => { - if (err) { - handleErrorObject({ - message: err, - path: filePath, - }); - } - else { - // Print the *entire* stdout and stderr (buffered). - stdout && console.log(`${filePath}: ${stdout}`); - stderr && console.log(`${filePath}: ${stderr}`); - } - }); - }); - - console.log('Done minifying.'); - }); diff --git a/Readme.md b/Readme.md index 59a9aecb..fc7ed720 100644 --- a/Readme.md +++ b/Readme.md @@ -23,7 +23,7 @@ Do you want to quickly try out this project and see it in action? Check it out, ## Prerequisites -1. To use this project, you will most of all need [Node.js](https://nodejs.org/) 16.9 or newer. We suggest installing the current LTS version which is higher than this minimum. +1. To use this project, you will most of all need [Node.js](https://nodejs.org/) 18 or newer. We suggest installing the current LTS version which is higher than this minimum. 2. Please follow our recommended setup guides for [Windows](Lombiq.NodeJs.Extensions/Docs/SetupWindows.md) or [Linux](Lombiq.NodeJs.Extensions/Docs/SetupLinux.md), as applicable. [PNPM](https://pnpm.io) 8 (for package management and script execution) is automatically enabled via `corepack` in the `EnablePnpm` MSBuild target, so you don't have to install it separately. Since PNPM 8 dropped support for Node.js 14 or older, those `node` versions won't work. From 3b47fde288766e6a8c39233d389bbdee423c6239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A1ra=20El-Saig?= Date: Sat, 17 Feb 2024 21:04:51 +0100 Subject: [PATCH 2/3] Update rimraf. --- Lombiq.NodeJs.Extensions/package.json | 2 +- Lombiq.NodeJs.Extensions/pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lombiq.NodeJs.Extensions/package.json b/Lombiq.NodeJs.Extensions/package.json index 48bf2a1e..b3ad3074 100644 --- a/Lombiq.NodeJs.Extensions/package.json +++ b/Lombiq.NodeJs.Extensions/package.json @@ -20,7 +20,7 @@ "postcss": "8.4.31", "postcss-cli": "10.1.0", "prettier": "3.0.3", - "rimraf": "5.0.1", + "rimraf": "5.0.5", "sass": "1.69.5", "stylelint": "15.11.0", "stylelint-config-standard-scss": "11.1.0", diff --git a/Lombiq.NodeJs.Extensions/pnpm-lock.yaml b/Lombiq.NodeJs.Extensions/pnpm-lock.yaml index f35ebe87..e49354c6 100644 --- a/Lombiq.NodeJs.Extensions/pnpm-lock.yaml +++ b/Lombiq.NodeJs.Extensions/pnpm-lock.yaml @@ -57,8 +57,8 @@ dependencies: specifier: 3.0.3 version: 3.0.3 rimraf: - specifier: 5.0.1 - version: 5.0.1 + specifier: 5.0.5 + version: 5.0.5 sass: specifier: 1.69.5 version: 1.69.5 @@ -5799,8 +5799,8 @@ packages: dependencies: glob: 7.2.3 - /rimraf@5.0.1: - resolution: {integrity: sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==} + /rimraf@5.0.5: + resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} engines: {node: '>=14'} hasBin: true dependencies: From 5ece858b335a5c149694989b293aa468b926269e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A1ra=20El-Saig?= Date: Wed, 21 Feb 2024 15:11:57 +0100 Subject: [PATCH 3/3] Update Lombiq.NodeJs.Extensions/scripts/compile-scripts.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Krisztián Németh --- Lombiq.NodeJs.Extensions/scripts/compile-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js b/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js index 435c0369..05b5826e 100644 --- a/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js +++ b/Lombiq.NodeJs.Extensions/scripts/compile-scripts.js @@ -36,4 +36,4 @@ async function compileScripts() { })); } -compileScripts().catch(handleErrorObjectAndExit); \ No newline at end of file +compileScripts().catch(handleErrorObjectAndExit);