mirror of
https://github.com/danielsogl/awesome-cordova-plugins.git
synced 2026-05-20 00:06:24 +08:00
feat: migrate from Webpack to esbuild for optimized builds
- Updated build process to use esbuild, enhancing performance and reducing bundle size. - Introduced custom esbuild plugins to replicate Webpack functionality, including removal of duplicate tslib helpers. - Replaced the previous build script for ES5 with a new optimized version using esbuild. - Added support for TypeScript in esbuild configuration, ensuring compatibility with existing code. - Removed Webpack-related dependencies and configurations from package.json and renovate.json. This transition aims to streamline the build process and improve overall efficiency.
This commit is contained in:
Generated
+677
-1088
File diff suppressed because it is too large
Load Diff
+2
-5
@@ -11,7 +11,7 @@
|
||||
"test:watch": "jest --watch",
|
||||
"build:core": "tsc -p tsconfig.core.json",
|
||||
"build:esm": "ts-node -P scripts/tsconfig.json scripts/tasks/build-esm",
|
||||
"build:es5": "ts-node -P scripts/tsconfig.json scripts/tasks/build-es5",
|
||||
"build:es5": "ts-node -P scripts/tsconfig.json scripts/tasks/build-es5-optimized",
|
||||
"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",
|
||||
"prebuild": "rimraf -rf dist",
|
||||
@@ -39,13 +39,13 @@
|
||||
"@types/lodash": "4.17.5",
|
||||
"@types/node": "20.14.10",
|
||||
"@types/rimraf": "4.0.5",
|
||||
"@types/webpack": "5.28.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.62.0",
|
||||
"@typescript-eslint/parser": "5.62.0",
|
||||
"async-promise-queue": "1.0.5",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"dgeni": "0.4.14",
|
||||
"dgeni-packages": "0.16.10",
|
||||
"esbuild": "^0.25.5",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-prettier": "10.1.5",
|
||||
"eslint-plugin-jsdoc": "50.6.17",
|
||||
@@ -65,12 +65,9 @@
|
||||
"rimraf": "5.0.5",
|
||||
"rollup": "4.41.0",
|
||||
"rxjs": "^7.8.2",
|
||||
"terser-webpack-plugin": "5.3.14",
|
||||
"ts-jest": "29.3.4",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.6.3",
|
||||
"unminified-webpack-plugin": "3.0.0",
|
||||
"webpack": "5.74.0",
|
||||
"winston": "3.17.0",
|
||||
"zone.js": "0.15.1"
|
||||
},
|
||||
|
||||
+5
-33
@@ -48,22 +48,13 @@
|
||||
"groupName": "linting and formatting",
|
||||
"automerge": true,
|
||||
"platformAutomerge": true,
|
||||
"matchPackageNames": [
|
||||
"/^eslint/",
|
||||
"/^prettier/",
|
||||
"/^husky/",
|
||||
"/^lint-staged/"
|
||||
]
|
||||
"matchPackageNames": ["/^eslint/", "/^prettier/", "/^husky/", "/^lint-staged/"]
|
||||
},
|
||||
{
|
||||
"groupName": "Angular",
|
||||
"allowedVersions": "<=12",
|
||||
"automerge": false,
|
||||
"matchPackageNames": [
|
||||
"/^@angular//",
|
||||
"/^@angular-devkit//",
|
||||
"/@schematics/angular/"
|
||||
]
|
||||
"matchPackageNames": ["/^@angular//", "/^@angular-devkit//", "/@schematics/angular/"]
|
||||
},
|
||||
{
|
||||
"matchPackageNames": ["zone.js"],
|
||||
@@ -80,13 +71,7 @@
|
||||
"groupName": "Build and bundling tools",
|
||||
"automerge": true,
|
||||
"platformAutomerge": true,
|
||||
"matchPackageNames": [
|
||||
"rollup",
|
||||
"webpack",
|
||||
"terser-webpack-plugin",
|
||||
"unminified-webpack-plugin",
|
||||
"rimraf"
|
||||
]
|
||||
"matchPackageNames": ["rollup", "rimraf"]
|
||||
},
|
||||
{
|
||||
"groupName": "Testing framework",
|
||||
@@ -98,26 +83,13 @@
|
||||
"groupName": "Documentation tools",
|
||||
"automerge": true,
|
||||
"platformAutomerge": true,
|
||||
"matchPackageNames": [
|
||||
"dgeni",
|
||||
"dgeni-packages",
|
||||
"gulp",
|
||||
"gulp-rename",
|
||||
"gulp-replace"
|
||||
]
|
||||
"matchPackageNames": ["dgeni", "dgeni-packages", "gulp", "gulp-rename", "gulp-replace"]
|
||||
},
|
||||
{
|
||||
"groupName": "Utility libraries",
|
||||
"automerge": true,
|
||||
"platformAutomerge": true,
|
||||
"matchPackageNames": [
|
||||
"lodash",
|
||||
"@types/lodash",
|
||||
"fs-extra",
|
||||
"@types/fs-extra",
|
||||
"minimist",
|
||||
"winston"
|
||||
]
|
||||
"matchPackageNames": ["lodash", "@types/lodash", "fs-extra", "@types/fs-extra", "minimist", "winston"]
|
||||
},
|
||||
{
|
||||
"matchManagers": ["npm"],
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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,
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
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,
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
// 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, '');
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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;
|
||||
@@ -0,0 +1,70 @@
|
||||
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();
|
||||
@@ -1,91 +0,0 @@
|
||||
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();
|
||||
@@ -8,6 +8,8 @@
|
||||
"noImplicitAny": true,
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"paths": {
|
||||
"@awesome-cordova-plugins/core": ["./dist/@awesome-cordova-plugins/core"]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user