From 5f21c7e8c857fbb8b8204e4a9e263e566514c600 Mon Sep 17 00:00:00 2001 From: Paul Berberian Date: Wed, 3 Apr 2024 11:53:51 +0200 Subject: [PATCH] Proposal: remove the need to rely on webpack for es5 worker generation For purposes where we need to generate a bundle (the demo, the worker files, the RxPlayer bundle builds), we're progressively removing our reliance on webpack toward esbuild. It began with the demo page originally for performance reasons, but we found out that the esbuild behavior and API was much simpler to understand than webpack's, and so we ended up also prefering to rely on it for our worker build. Considering that we since the v4 only rely on TypeScript with no bundling step for our "regular" build (and our home-made scripts in the `./scripts` directory), we thus ended up having no reliance on webpack for most of our builds. However at #1400, we noticed that we might also need to provide an ES5 version of our worker file (at least for the PlayStation 4), and I found that having ES5 support through esbuild is not straightforward (https://github.com/evanw/esbuild/issues/297). Historically, [babeljs](https://babeljs.io/) was used to translate to ES5 - and that's the one I know, so I tried using it on the bundle made by esbuild. However it turns out that there's no resource for how to use babel like this - not integrated as a bundler's plugin (here we just wanted to translate an ES2017 already-made bundle to es5) so I just gave up and relied on webpack for specifically that ES5 build. However this both added some perceptible delay in our build, and we now relied on two different bundlers in our `npm run build` main build script, which made me un-comfortable in terms of maintainance and understanding of how our build step worked. So I re-looked around and read about [`swc`](https://swc.rs/), which seems to be some kind of babel competitor with some credibility (though they advertises themselves as a """platform""", I would have preferred a clearer term but ok), with some differences, including speed, but what is most interesting here is that it can just be run as a standalone transpiler (what I mean: not embedded in a bundler). By using it, I've been able to remove reliance on webpack (and babel) in our regular build steps (produced by `npm run build`) which should be realistically used by 99.9999% of applications (approximately!). The only exception where both webpack and babel are still used is to produce our bundles attached to each release notes (they expose the RxPlayer through `window`, like our grandfathers did) - which I guess are rarely relied upon. Still, we should probably remove reliance on webpack there in the future. Swc is maintained apparently by volunteers, and is less known than babeljs, so there's still that. Also, the bundler and transpiler JavaScript landscape is __VERY__ active (even in JavaScript terms) right now with projects like [rolldown](https://rolldown.rs/) and [oxc](https://oxc-project.github.io/) so sadly it may be not the last update of this part of our build process. --- package-lock.json | 401 +++++++++++++++++++++++++++++++------ package.json | 1 + scripts/bundle_worker.mjs | 299 +++++++++++++-------------- scripts/generate_build.mjs | 9 +- 4 files changed, 481 insertions(+), 229 deletions(-) diff --git a/package-lock.json b/package-lock.json index b2fb88728a..b761425e77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@babel/preset-env": "7.23.6", "@babel/preset-react": "7.23.3", "@canalplus/readme.doc": "0.5.0", + "@swc/core": "^1.4.11", "@types/chai": "4.3.11", "@types/jest": "29.5.11", "@types/mocha": "10.0.6", @@ -3473,6 +3474,219 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "dev": true }, + "node_modules/@swc/core": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz", + "integrity": "sha512-WKEakMZxkVwRdgMN4AMJ9K5nysY8g8npgQPczmjBeNK5In7QEAZAJwnyccrWwJZU0XjVeHn2uj+XbOKdDW17rg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.2", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.4.11", + "@swc/core-darwin-x64": "1.4.11", + "@swc/core-linux-arm-gnueabihf": "1.4.11", + "@swc/core-linux-arm64-gnu": "1.4.11", + "@swc/core-linux-arm64-musl": "1.4.11", + "@swc/core-linux-x64-gnu": "1.4.11", + "@swc/core-linux-x64-musl": "1.4.11", + "@swc/core-win32-arm64-msvc": "1.4.11", + "@swc/core-win32-ia32-msvc": "1.4.11", + "@swc/core-win32-x64-msvc": "1.4.11" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz", + "integrity": "sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz", + "integrity": "sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz", + "integrity": "sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz", + "integrity": "sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz", + "integrity": "sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.11.tgz", + "integrity": "sha512-WA1iGXZ2HpqM1OR9VCQZJ8sQ1KP2or9O4bO8vWZo6HZJIeoQSo7aa9waaCLRpkZvkng1ct/TF/l6ymqSNFXIzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz", + "integrity": "sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz", + "integrity": "sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz", + "integrity": "sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz", + "integrity": "sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "node_modules/@swc/types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", + "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -5322,26 +5536,6 @@ "node": ">= 0.6" } }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -7089,26 +7283,6 @@ "node": ">= 0.8" } }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/express/node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -12745,10 +12919,24 @@ "dev": true }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safe-regex-test": { "version": "1.0.0", @@ -17193,6 +17381,111 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "dev": true }, + "@swc/core": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz", + "integrity": "sha512-WKEakMZxkVwRdgMN4AMJ9K5nysY8g8npgQPczmjBeNK5In7QEAZAJwnyccrWwJZU0XjVeHn2uj+XbOKdDW17rg==", + "dev": true, + "requires": { + "@swc/core-darwin-arm64": "1.4.11", + "@swc/core-darwin-x64": "1.4.11", + "@swc/core-linux-arm-gnueabihf": "1.4.11", + "@swc/core-linux-arm64-gnu": "1.4.11", + "@swc/core-linux-arm64-musl": "1.4.11", + "@swc/core-linux-x64-gnu": "1.4.11", + "@swc/core-linux-x64-musl": "1.4.11", + "@swc/core-win32-arm64-msvc": "1.4.11", + "@swc/core-win32-ia32-msvc": "1.4.11", + "@swc/core-win32-x64-msvc": "1.4.11", + "@swc/counter": "^0.1.2", + "@swc/types": "^0.1.5" + } + }, + "@swc/core-darwin-arm64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz", + "integrity": "sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-x64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz", + "integrity": "sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz", + "integrity": "sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz", + "integrity": "sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz", + "integrity": "sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.11.tgz", + "integrity": "sha512-WA1iGXZ2HpqM1OR9VCQZJ8sQ1KP2or9O4bO8vWZo6HZJIeoQSo7aa9waaCLRpkZvkng1ct/TF/l6ymqSNFXIzQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz", + "integrity": "sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==", + "dev": true, + "optional": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz", + "integrity": "sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==", + "dev": true, + "optional": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz", + "integrity": "sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==", + "dev": true, + "optional": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz", + "integrity": "sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==", + "dev": true, + "optional": true + }, + "@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "@swc/types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", + "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "dev": true, + "requires": { + "@swc/counter": "^0.1.3" + } + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -18636,14 +18929,6 @@ "dev": true, "requires": { "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } } }, "content-type": { @@ -19958,12 +20243,6 @@ "ee-first": "1.1.1" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -24099,9 +24378,9 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "safe-regex-test": { diff --git a/package.json b/package.json index 014b9ffb1f..dcb00e9cc8 100644 --- a/package.json +++ b/package.json @@ -198,6 +198,7 @@ "@babel/preset-env": "7.23.6", "@babel/preset-react": "7.23.3", "@canalplus/readme.doc": "0.5.0", + "@swc/core": "^1.4.11", "@types/chai": "4.3.11", "@types/jest": "29.5.11", "@types/mocha": "10.0.6", diff --git a/scripts/bundle_worker.mjs b/scripts/bundle_worker.mjs index 45e0fd1e51..d74b7eacce 100755 --- a/scripts/bundle_worker.mjs +++ b/scripts/bundle_worker.mjs @@ -11,11 +11,11 @@ * right options. */ +import * as fs from "fs"; import * as path from "path"; import { pathToFileURL } from "url"; import esbuild from "esbuild"; -import TerserPlugin from "terser-webpack-plugin"; -import webpack from "webpack"; +import swc from "@swc/core"; import rootDirectory from "./utils/project_root_directory.mjs"; import getHumanReadableHours from "./utils/get_human_readable_hours.mjs"; @@ -30,17 +30,13 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) { const shouldMinify = argv.includes("-m") || argv.includes("--minify"); const production = argv.includes("-p") || argv.includes("--production-mode"); const silent = argv.includes("-s") || argv.includes("--silent"); + const buildEs5 = argv.includes("-5") || argv.includes("--es5"); buildWorker({ watch: shouldWatch, minify: shouldMinify, production, silent, - }); - buildWorkerEs5({ - watch: shouldWatch, - minify: shouldMinify, - production, - silent, + es5: buildEs5, }); } @@ -53,41 +49,40 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) { * @param {boolean} [options.watch] - If `true`, the RxPlayer's files involve * will be watched and the code re-built each time one of them changes. * @param {boolean} [options.silent] - If `true`, we won't output logs. - * @param {boolean} [options.outfile] - Destination of the produced bundle. + * @param {boolean} [options.es5] - If `true`, an ES5 bundle will also be + * produced. + * @param {string} [options.outfile] - Destination of the produced bundle. * `dist/worker.js` by default. + * @param {string} [options.es5Outfile] - Destination of the produced ES5 + * bundle (only if [options.es5] has been set to `true`). + * `dist/worker.es5.js` by default. * @returns {Promise} */ -export default function buildWorker(options) { +export default async function buildWorker(options) { const minify = !!options.minify; const watch = !!options.watch; const isDevMode = !options.production; const isSilent = options.silent; const outfile = options.outfile ?? path.join(rootDirectory, "dist/worker.js"); + const es5Outfile = options.es5Outfile ?? path.join(rootDirectory, "dist/worker.es5.js"); - /** Declare a plugin to anounce when a build begins and ends */ - const consolePlugin = { - name: "onEnd", + const esbuildStepsPlugin = { + name: "worker-steps", setup(build) { - build.onStart(() => { - console.log( - `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + - "New Worker file build started", - ); - }); + build.onStart(() => logWarning("New Worker file build started")); build.onEnd((result) => { + if (watch && options.es5) { + buildAndAnnounceEs5Bundle(); + } if (result.errors.length > 0 || result.warnings.length > 0) { const { errors, warnings } = result; - console.log( - `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + - `Worker file re-built with ${errors.length} error(s) and ` + + logWarning( + `Worker file re-built with ${errors.length} error(s) and ` + ` ${warnings.length} warning(s) `, ); return; } - console.log( - `\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` + - `Worker file updated at ${outfile}!`, - ); + logSuccess(`Worker file updated at ${outfile}!`); }); }, }; @@ -95,160 +90,142 @@ export default function buildWorker(options) { const meth = watch ? "context" : "build"; // Create a context for incremental builds - return esbuild[meth]({ - entryPoints: [path.join(rootDirectory, "src/worker_entry_point.ts")], - bundle: true, - target: "es2017", - minify, - outfile, - plugins: isSilent ? [] : [consolePlugin], - define: { - "process.env.NODE_ENV": JSON.stringify(isDevMode ? "development" : "production"), - __ENVIRONMENT__: JSON.stringify({ - PRODUCTION: 0, - DEV: 1, - CURRENT_ENV: isDevMode ? 1 : 0, - }), - __LOGGER_LEVEL__: JSON.stringify({ CURRENT_LEVEL: "NONE" }), - }, - }) - .then((context) => { - if (watch) { - return context.watch(); - } - }) - .catch((err) => { + try { + const context = await esbuild[meth]({ + entryPoints: [path.join(rootDirectory, "src/worker_entry_point.ts")], + bundle: true, + target: "es2017", + minify, + outfile, + plugins: [esbuildStepsPlugin], + define: { + "process.env.NODE_ENV": JSON.stringify(isDevMode ? "development" : "production"), + __ENVIRONMENT__: JSON.stringify({ + PRODUCTION: 0, + DEV: 1, + CURRENT_ENV: isDevMode ? 1 : 0, + }), + __LOGGER_LEVEL__: JSON.stringify({ CURRENT_LEVEL: "NONE" }), + }, + }); + if (watch) { + return context.watch(); + } else if (options.es5) { + await buildAndAnnounceEs5Bundle(); + } + } catch (err) { + logError(`Worker file build failed:`, err); + throw err; + } + + async function buildAndAnnounceEs5Bundle() { + try { + await transpileWorkerToEs5({ + infile: outfile, + outfile: es5Outfile, + minify, + }); if (!isSilent) { - console.error( - `\x1b[31m[${getHumanReadableHours()}]\x1b[0m Worker file build failed:`, - err, - ); + logSuccess(`ES5 Worker file updated at ${es5Outfile}!`); } + } catch (err) { + logError(`ES5 Worker file build failed: ${err}`); throw err; - }); -} + } + } -export function buildWorkerEs5(options) { - const shouldMinify = !!options.minify; - const watch = !!options.watch; - const isDevMode = !options.production; - const isSilent = options.silent; - const outfile = options.outfile ?? path.join(rootDirectory, "dist/worker.es5.js"); - const outputPath = path.dirname(outfile); - const filename = path.basename(outfile); + function logSuccess(msg) { + if (!isSilent) { + console.log(`\x1b[32m[${getHumanReadableHours()}]\x1b[0m`, msg); + } + } - const plugins = [ - new webpack.DefinePlugin({ - __ENVIRONMENT__: { - PRODUCTION: 0, - DEV: 1, - CURRENT_ENV: isDevMode ? 1 : 0, - }, - __LOGGER_LEVEL__: JSON.stringify({ CURRENT_LEVEL: "NONE" }), - }), - ]; + function logWarning(msg) { + if (!isSilent) { + console.log(`\x1b[33m[${getHumanReadableHours()}]\x1b[0m`, msg); + } + } - if (!isSilent) { - console.log( - `\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` + - "New ES5 Worker file build started", - ); + function logError(msg) { + if (!isSilent) { + console.log(`\x1b[31m[${getHumanReadableHours()}]\x1b[0m`, msg); + } } +} - const compiler = webpack({ - mode: isDevMode ? "development" : "production", - entry: [path.join(rootDirectory, "src/worker_entry_point.ts")], - output: { - path: outputPath, - filename, - environment: { - arrowFunction: false, - asyncFunction: false, - bigIntLiteral: false, - const: false, - destructuring: false, - dynamicImport: false, - dynamicImportInWorker: false, - forOf: false, - globalThis: false, - module: false, - optionalChaining: false, - templateLiteral: false, - }, - }, - optimization: { - minimize: shouldMinify, - minimizer: shouldMinify ? [new TerserPlugin()] : [], - }, - performance: { - maxEntrypointSize: shouldMinify ? 600000 : 2500000, - maxAssetSize: shouldMinify ? 600000 : 2500000, - }, - resolve: { - extensions: [".ts", ".tsx", ".js", ".jsx", ".json"], - }, - module: { - rules: [ - { - test: /\.tsx?$/, - use: [ - { - loader: "babel-loader", - options: { - cacheDirectory: true, - presets: [["@babel/env", { loose: true, modules: false }]], - plugins: [["@babel/plugin-transform-runtime"]], - }, - }, - { loader: "ts-loader" }, - ], - }, - ], - }, - plugins, +/** + * Simple promisified `fs.readFile` API. + * @param {string} filePath + * @param {string|null} encoding + * @returns {*} - Read data, the type depends on the `encoding` parameters (see + * `fs.readFile` documentation). + */ +function readFile(filePath, encoding) { + return new Promise((res, rej) => { + fs.readFile(filePath, { encoding }, function (err, data) { + if (err) { + rej(err); + } + res(data); + }); }); +} +/** + * Simple promisified `fs.writeFile` API. + * @param {string} filePath + * @param {string} content + * @returns {Promise} + */ +function writeFile(filePath, content) { return new Promise((res, rej) => { - if (watch) { - compiler.watch({}, (err) => { - if (err) { - if (!isSilent) { - console.error( - `\x1b[31m[${getHumanReadableHours()}]\x1b[0m ES5 Worker file build failed:`, - err, - ); - } - rej(err); - } else if (!isSilent) { - console.log( - `\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` + - `ES5 Worker file updated at ${outfile}!`, - ); - } - res(); - }); - return; - } - compiler.run((err) => { + fs.writeFile(filePath, content, (err) => { if (err) { - if (!isSilent) { - console.error( - `\x1b[31m[${getHumanReadableHours()}]\x1b[0m ES5 Worker file build failed:`, - err, - ); - } rej(err); - } else if (!isSilent) { - console.log( - `\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` + - `ES5 Worker file written at ${outfile}!`, - ); } res(); }); }); } +async function transpileWorkerToEs5(options) { + const infile = options.infile; + const outfile = options.outfile; + const fileData = await readFile(infile, "utf-8"); + const minify = options.minify; + const output = await swc.transform(fileData, { + jsc: { + parser: { + syntax: "ecmascript", + jsx: false, + dynamicImport: false, + privateMethod: false, + functionBind: false, + exportDefaultFrom: false, + exportNamespaceFrom: false, + decorators: false, + decoratorsBeforeExport: false, + topLevelAwait: false, + importMeta: false, + }, + minify: { + compress: { + unused: true, + }, + mangle: true, + }, + transform: null, + target: "es5", + loose: false, + externalHelpers: false, + // Requires v1.2.50 or upper and requires target to be es2016 or upper. + keepClassNames: false, + }, + minify, + }); + await writeFile(outfile, output.code); +} + /** * Display through `console.log` an helping message relative to how to run this * script. diff --git a/scripts/generate_build.mjs b/scripts/generate_build.mjs index 20819abca5..7de6f1ded9 100755 --- a/scripts/generate_build.mjs +++ b/scripts/generate_build.mjs @@ -24,7 +24,7 @@ import * as path from "path"; import { fileURLToPath, pathToFileURL } from "url"; import { rimraf } from "rimraf"; import generateEmbeds from "./generate_embeds.mjs"; -import buildWorker, { buildWorkerEs5 } from "./bundle_worker.mjs"; +import buildWorker from "./bundle_worker.mjs"; const currentDirectory = path.dirname(fileURLToPath(import.meta.url)); @@ -84,12 +84,7 @@ async function generateBuild(options = {}) { minify: !devMode, production: !devMode, silent: true, - }), - buildWorkerEs5({ - watch: false, - minify: !devMode, - production: !devMode, - silent: true, + es5: true, }), ]);