Revert "feat: migrate from Webpack to esbuild for optimized builds"

This reverts commit f47561fd7c.
This commit is contained in:
Daniel Sogl
2025-06-10 17:15:53 +02:00
parent 216e553f63
commit 963d4a2f3e
10 changed files with 1328 additions and 953 deletions
+1229 -754
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -11,7 +11,7 @@
"test:watch": "jest --watch", "test:watch": "jest --watch",
"build:core": "tsc -p tsconfig.core.json", "build:core": "tsc -p tsconfig.core.json",
"build:esm": "ts-node -P scripts/tsconfig.json scripts/tasks/build-esm", "build:esm": "ts-node -P scripts/tsconfig.json scripts/tasks/build-esm",
"build:es5": "ts-node -P scripts/tsconfig.json scripts/tasks/build-es5-optimized", "build:es5": "ts-node -P scripts/tsconfig.json scripts/tasks/build-es5",
"build:ngx": "ts-node -P scripts/tsconfig.json scripts/tasks/build-ngx", "build:ngx": "ts-node -P scripts/tsconfig.json scripts/tasks/build-ngx",
"build": "npm run build:core && npm run build:esm && npm run build:ngx && npm run build:es5", "build": "npm run build:core && npm run build:esm && npm run build:ngx && npm run build:es5",
"prebuild": "rimraf -rf dist", "prebuild": "rimraf -rf dist",
@@ -40,11 +40,11 @@
"@types/node": "20.14.10", "@types/node": "20.14.10",
"@typescript-eslint/eslint-plugin": "^8.33.1", "@typescript-eslint/eslint-plugin": "^8.33.1",
"@typescript-eslint/parser": "^8.33.1", "@typescript-eslint/parser": "^8.33.1",
"@types/webpack": "5.28.5",
"async-promise-queue": "1.0.5", "async-promise-queue": "1.0.5",
"cz-conventional-changelog": "3.3.0", "cz-conventional-changelog": "3.3.0",
"dgeni": "0.4.14", "dgeni": "0.4.14",
"dgeni-packages": "0.16.10", "dgeni-packages": "0.16.10",
"esbuild": "^0.25.5",
"eslint": "^9.28.0", "eslint": "^9.28.0",
"eslint-config-prettier": "^10.1.5", "eslint-config-prettier": "^10.1.5",
"eslint-plugin-jsdoc": "^50.7.1", "eslint-plugin-jsdoc": "^50.7.1",
@@ -64,9 +64,12 @@
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"rollup": "^4.42.0", "rollup": "^4.42.0",
"rxjs": "^7.8.2", "rxjs": "^7.8.2",
"terser-webpack-plugin": "5.3.14",
"ts-jest": "29.3.4", "ts-jest": "29.3.4",
"ts-node": "10.9.2", "ts-node": "10.9.2",
"typescript": "5.6.3", "typescript": "5.6.3",
"unminified-webpack-plugin": "3.0.0",
"webpack": "5.74.0",
"winston": "3.17.0", "winston": "3.17.0",
"zone.js": "0.15.1" "zone.js": "0.15.1"
}, },
+1 -1
View File
@@ -77,7 +77,7 @@
"groupName": "Build and bundling tools", "groupName": "Build and bundling tools",
"automerge": true, "automerge": true,
"platformAutomerge": true, "platformAutomerge": true,
"matchPackageNames": ["rollup", "rimraf"] "matchPackageNames": ["rollup", "webpack", "terser-webpack-plugin", "unminified-webpack-plugin", "rimraf"]
}, },
{ {
"groupName": "Testing framework", "groupName": "Testing framework",
-36
View File
@@ -1,36 +0,0 @@
// Custom esbuild plugins to replace webpack functionality
/**
* Plugin to remove duplicate tslib helpers that TypeScript might emit
* Works with both .js and .ts files for comprehensive coverage
*/
const removeTslibHelpersPlugin = {
name: 'remove-tslib-helpers',
setup(build) {
// Handle both JavaScript and TypeScript files
build.onLoad({ filter: /\.(js|ts)$/ }, async (args) => {
const fs = require('fs');
const path = require('path');
const contents = await fs.promises.readFile(args.path, 'utf8');
// Remove the __extends method that is added automatically by typescript
const transformedContents = contents.replace(
/var\s__extends\s=\s\(this\s&&[\sa-z\._\(\)\|{}=:\[\]&,;?]+}\)\(\);/i,
''
);
// Determine the correct loader based on file extension
const ext = path.extname(args.path);
const loader = ext === '.ts' ? 'ts' : 'js';
return {
contents: transformedContents,
loader: loader,
};
});
},
};
module.exports = {
removeTslibHelpersPlugin,
};
-61
View File
@@ -1,61 +0,0 @@
const { resolve } = require('path');
const { removeTslibHelpersPlugin } = require('./esbuild-plugins');
const ROOT = resolve(__dirname, '../../');
const DIST = resolve(ROOT, 'dist');
/**
* Base esbuild configuration for TypeScript projects
* Based on esbuild TypeScript documentation: https://esbuild.github.io/content-types/#typescript
*/
const baseConfig = {
platform: 'browser',
target: 'es2015',
format: 'iife',
bundle: true,
sourcemap: true,
treeShaking: true,
// TypeScript support - esbuild handles .ts files natively
loader: { '.ts': 'ts' },
// Resolve TypeScript and JavaScript files
resolveExtensions: ['.ts', '.js'],
// Define environment variables
define: {
'process.env.NODE_ENV': '"production"',
},
// Inject tslib helpers globally
inject: [resolve(ROOT, 'scripts/build/tslib-provider.js')],
// Custom plugins for webpack compatibility
plugins: [removeTslibHelpersPlugin],
// Path aliases for module resolution
alias: {
'@awesome-cordova-plugins/core': resolve(DIST, '@awesome-cordova-plugins/core/index.js'),
},
banner: {
js: '/* Awesome Cordova Plugins - https://github.com/danielsogl/awesome-cordova-plugins */',
},
};
/**
* Configuration for minified production bundle
*/
const minifiedConfig = {
...baseConfig,
minify: true,
outfile: resolve(DIST, 'awesome-cordova-plugins.min.js'),
};
/**
* Configuration for unminified development bundle
*/
const unminifiedConfig = {
...baseConfig,
minify: false,
outfile: resolve(DIST, 'awesome-cordova-plugins.js'),
};
module.exports = {
baseConfig,
minifiedConfig,
unminifiedConfig,
};
+2
View File
@@ -0,0 +1,2 @@
// removes the __extends method that is added automatically by typescript
module.exports = (source) => source.replace(/var\s__extends\s=\s\(this\s&&[\sa-z\._\(\)\|{}=:\[\]&,;?]+}\)\(\);/i, '');
-27
View File
@@ -1,27 +0,0 @@
// This file provides tslib helpers to esbuild, replacing webpack's ProvidePlugin
var tslib = require('tslib');
// Export all tslib helpers to global scope
global.__extends = tslib.__extends;
global.__assign = tslib.__assign;
global.__rest = tslib.__rest;
global.__decorate = tslib.__decorate;
global.__param = tslib.__param;
global.__metadata = tslib.__metadata;
global.__awaiter = tslib.__awaiter;
global.__generator = tslib.__generator;
global.__exportStar = tslib.__exportStar;
global.__values = tslib.__values;
global.__read = tslib.__read;
global.__spread = tslib.__spread;
global.__spreadArrays = tslib.__spreadArrays;
global.__spreadArray = tslib.__spreadArray;
global.__await = tslib.__await;
global.__asyncGenerator = tslib.__asyncGenerator;
global.__asyncDelegator = tslib.__asyncDelegator;
global.__asyncValues = tslib.__asyncValues;
global.__makeTemplateObject = tslib.__makeTemplateObject;
global.__importStar = tslib.__importStar;
global.__importDefault = tslib.__importDefault;
global.__classPrivateFieldGet = tslib.__classPrivateFieldGet;
global.__classPrivateFieldSet = tslib.__classPrivateFieldSet;
-70
View File
@@ -1,70 +0,0 @@
import { readJSONSync, writeFileSync } from 'fs-extra';
import { resolve } from 'path';
import { build } from 'esbuild';
import { minifiedConfig, unminifiedConfig } from '../build/esbuild.config';
import { ROOT } from '../build/helpers';
import { EMIT_PATH, InjectableClassEntry } from '../build/transformers/extract-injectables';
import { Logger } from '../logger';
const DIST = resolve(ROOT, 'dist');
const INDEX_PATH = resolve(DIST, 'index.ts');
const INJECTABLE_CLASSES = readJSONSync(EMIT_PATH).map((item: InjectableClassEntry) => {
// Convert file paths to TypeScript source files instead of compiled JS
item.file =
'./' +
item.file
.split(/[\/\\]+/)
.slice(-4, -1)
.join('/')
.replace('/dist/', '/src/'); // Point to source TypeScript files
return item;
});
function getPluginImport(entry: InjectableClassEntry) {
return `import { ${entry.className} } from '${entry.file}';`;
}
function createIndexFile() {
let fileContent = '';
fileContent += INJECTABLE_CLASSES.map(getPluginImport).join('\n');
fileContent += `\n\n// Global IonicNative object for browser usage\ndeclare global {\n interface Window {\n IonicNative: any;\n }\n}\n\n`;
fileContent += `window.IonicNative = {\n`;
fileContent += INJECTABLE_CLASSES.map((e) => e.className).join(',\n');
fileContent += '\n};\n\n';
fileContent += `// Bootstrap and Angular 1 integration\n`;
fileContent += `import './@awesome-cordova-plugins/core/bootstrap';\n`;
fileContent += `import { initAngular1 } from './@awesome-cordova-plugins/core/ng1';\n`;
fileContent += `\n// Check if platform is ready and initialize Angular 1 support\n`;
fileContent += `initAngular1(window.IonicNative);`;
writeFileSync(INDEX_PATH, fileContent, { encoding: 'utf-8' });
}
async function compile() {
Logger.profile('build-es5-optimized');
try {
// Build both minified and unminified versions in parallel
await Promise.all([
build({
...minifiedConfig,
entryPoints: [INDEX_PATH],
}),
build({
...unminifiedConfig,
entryPoints: [INDEX_PATH],
}),
]);
Logger.profile('build-es5-optimized');
Logger.info('Compiled ES5 bundles with esbuild native TypeScript support successfully.');
} catch (error) {
Logger.profile('build-es5-optimized');
Logger.error('Error occurred while compiling with esbuild:', error);
throw error;
}
}
createIndexFile();
compile();
+91
View File
@@ -0,0 +1,91 @@
import { readJSONSync, writeFileSync } from 'fs-extra';
import { resolve } from 'path';
import * as TerserPlugin from 'terser-webpack-plugin';
import * as unminifiedPlugin from 'unminified-webpack-plugin';
import { Configuration, DefinePlugin, ProvidePlugin, webpack } from 'webpack';
import { ROOT } from '../build/helpers';
import { cleanEmittedData, EMIT_PATH, InjectableClassEntry } from '../build/transformers/extract-injectables';
import { Logger } from '../logger';
const DIST = resolve(ROOT, 'dist');
const INDEX_PATH = resolve(DIST, 'index.js');
const INJECTABLE_CLASSES = readJSONSync(EMIT_PATH).map((item: InjectableClassEntry) => {
item.file =
'./' +
item.file
.split(/[\/\\]+/)
.slice(-4, -1)
.join('/');
return item;
});
const webpackConfig: Configuration = {
mode: 'production',
entry: INDEX_PATH,
devtool: 'source-map',
target: 'web',
output: {
path: DIST,
filename: 'awesome-cordova-plugins.min.js',
},
resolve: {
modules: ['node_modules'],
extensions: ['.js'],
alias: {
'@awesome-cordova-plugins/core': resolve(DIST, '@awesome-cordova-plugins/core/index.js'),
},
},
module: {
rules: [
{
test: /\.js$/,
use: resolve(ROOT, 'scripts/build/remove-tslib-helpers.js'),
},
],
},
plugins: [
new ProvidePlugin({
__extends: ['tslib', '__extends'],
}),
new DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new unminifiedPlugin(),
],
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
function getPluginImport(entry: InjectableClassEntry) {
return `import { ${entry.className} } from '${entry.file}';`;
}
function createIndexFile() {
let fileContent = '';
fileContent += INJECTABLE_CLASSES.map(getPluginImport).join('\n');
fileContent += `\nwindow.IonicNative = {\n`;
fileContent += INJECTABLE_CLASSES.map((e) => e.className).join(',\n');
fileContent += '\n};\n';
fileContent += `require('./@awesome-cordova-plugins/core/bootstrap').checkReady();\n`;
fileContent += `require('./@awesome-cordova-plugins/core/ng1').initAngular1(window.IonicNative);`;
writeFileSync(INDEX_PATH, fileContent, { encoding: 'utf-8' });
}
function compile() {
Logger.profile('build-es5');
webpack(webpackConfig, (err, stats) => {
Logger.profile('build-es5');
if (err) Logger.error('Error occurred while compiling with Webpack', err);
else {
Logger.info('Compiled ES5 file with Webpack successfully.');
}
cleanEmittedData();
});
}
createIndexFile();
compile();
-2
View File
@@ -8,8 +8,6 @@
"noImplicitAny": true, "noImplicitAny": true,
"module": "es2015", "module": "es2015",
"moduleResolution": "node", "moduleResolution": "node",
"isolatedModules": true,
"esModuleInterop": true,
"paths": { "paths": {
"@awesome-cordova-plugins/core": ["./dist/@awesome-cordova-plugins/core"] "@awesome-cordova-plugins/core": ["./dist/@awesome-cordova-plugins/core"]
}, },