esbuild
Ultra-gyors JavaScript és CSS bundler WordPress projektekhez.
Az esbuild egy rendkívül gyors JavaScript és CSS bundler, amelyet Go nyelven írtak. 10-100x gyorsabb a hagyományos bundler-eknél (webpack, rollup), így ideális választás WordPress témák és bővítmények fejlesztéséhez.
Miért esbuild?
Szekció neve “Miért esbuild?”- Extrém gyors - Go nyelven írt, párhuzamos feldolgozás
- Egyszerű - Minimális konfiguráció
- Modern - ES6+, TypeScript, JSX natív támogatás
- Tree shaking - Automatikus dead code eltávolítás
- Source maps - Debug támogatás
- Watch mode - Automatikus újraépítés
Telepítés
Szekció neve “Telepítés”npm install -D esbuildAlapvető használat
Szekció neve “Alapvető használat”CLI parancsok
Szekció neve “CLI parancsok”# Egy fájl build-elésenpx esbuild src/js/main.js --bundle --outfile=dist/main.js
# Minifikálássalnpx esbuild src/js/main.js --bundle --minify --outfile=dist/main.min.js
# Source map-pelnpx esbuild src/js/main.js --bundle --sourcemap --outfile=dist/main.js
# Watch modenpx esbuild src/js/main.js --bundle --watch --outfile=dist/main.jspackage.json scripts
Szekció neve “package.json scripts”{ "scripts": { "build": "esbuild src/js/main.js --bundle --minify --sourcemap --outfile=dist/js/main.js", "build:css": "esbuild src/css/style.css --bundle --minify --outfile=dist/css/style.css", "dev": "esbuild src/js/main.js --bundle --watch --outfile=dist/js/main.js", "build:all": "npm run build && npm run build:css" }}JavaScript API
Szekció neve “JavaScript API”build.js
Szekció neve “build.js”import * as esbuild from 'esbuild';
await esbuild.build({ entryPoints: ['src/js/main.js'], bundle: true, minify: true, sourcemap: true, outfile: 'dist/js/main.js', target: ['es2020', 'chrome80', 'firefox80', 'safari14'],});
console.log('Build complete!');Több entry point
Szekció neve “Több entry point”import * as esbuild from 'esbuild';
await esbuild.build({ entryPoints: { main: 'src/js/main.js', admin: 'src/js/admin.js', 'block-editor': 'src/js/block-editor.js', }, bundle: true, minify: process.env.NODE_ENV === 'production', sourcemap: true, outdir: 'dist/js',});Watch mode (API)
Szekció neve “Watch mode (API)”import * as esbuild from 'esbuild';
const ctx = await esbuild.context({ entryPoints: ['src/js/main.js'], bundle: true, outfile: 'dist/js/main.js',});
// Watch indításaawait ctx.watch();console.log('Watching for changes...');
// Build és kilépés// await ctx.dispose();WordPress téma integráció
Szekció neve “WordPress téma integráció”Projekt struktúra
Szekció neve “Projekt struktúra”my-theme/├── src/│ ├── js/│ │ ├── main.js│ │ └── admin.js│ └── css/│ └── style.css├── dist/├── build.js├── package.json├── functions.php└── style.cssbuild.js (teljes konfiguráció)
Szekció neve “build.js (teljes konfiguráció)”import * as esbuild from 'esbuild';import { writeFileSync, mkdirSync, existsSync } from 'fs';import { dirname } from 'path';
const isProduction = process.env.NODE_ENV === 'production';const isWatch = process.argv.includes('--watch');
// Manifest generálásconst manifestPlugin = { name: 'manifest', setup(build) { build.onEnd((result) => { if (result.errors.length > 0) return;
const manifest = {}; const outputs = result.metafile?.outputs || {};
for (const [file, data] of Object.entries(outputs)) { if (data.entryPoint) { const entry = data.entryPoint; const outputFile = file.replace('dist/', ''); manifest[entry] = { file: outputFile, }; } }
const manifestDir = 'dist'; if (!existsSync(manifestDir)) { mkdirSync(manifestDir, { recursive: true }); }
writeFileSync( `${manifestDir}/manifest.json`, JSON.stringify(manifest, null, 2) ); }); },};
// JavaScript buildconst jsBuildOptions = { entryPoints: { main: 'src/js/main.js', admin: 'src/js/admin.js', }, bundle: true, minify: isProduction, sourcemap: !isProduction, outdir: 'dist/js', target: ['es2020'], format: 'esm', splitting: true, metafile: true, plugins: [manifestPlugin],};
// CSS buildconst cssBuildOptions = { entryPoints: ['src/css/style.css'], bundle: true, minify: isProduction, outdir: 'dist/css',};
async function build() { try { if (isWatch) { const jsCtx = await esbuild.context(jsBuildOptions); const cssCtx = await esbuild.context(cssBuildOptions);
await Promise.all([jsCtx.watch(), cssCtx.watch()]);
console.log('👀 Watching for changes...'); } else { await Promise.all([ esbuild.build(jsBuildOptions), esbuild.build(cssBuildOptions), ]);
console.log('✅ Build complete!'); } } catch (error) { console.error('❌ Build failed:', error); process.exit(1); }}
build();functions.php
Szekció neve “functions.php”<?php/** * Enqueue theme assets */function my_theme_enqueue_assets() { $manifest_path = get_template_directory() . '/dist/manifest.json';
if ( file_exists( $manifest_path ) ) { $manifest = json_decode( file_get_contents( $manifest_path ), true );
// Main JS if ( isset( $manifest['src/js/main.js'] ) ) { wp_enqueue_script( 'theme-main', get_template_directory_uri() . '/dist/' . $manifest['src/js/main.js']['file'], [], null, true ); }
// Admin JS if ( is_admin() && isset( $manifest['src/js/admin.js'] ) ) { wp_enqueue_script( 'theme-admin', get_template_directory_uri() . '/dist/' . $manifest['src/js/admin.js']['file'], [], null, true ); } }
// CSS wp_enqueue_style( 'theme-style', get_template_directory_uri() . '/dist/css/style.css', [], filemtime( get_template_directory() . '/dist/css/style.css' ) );}add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_assets' );CSS kezelés
Szekció neve “CSS kezelés”CSS bundle
Szekció neve “CSS bundle”await esbuild.build({ entryPoints: ['src/css/style.css'], bundle: true, minify: true, outfile: 'dist/css/style.css',});CSS import
Szekció neve “CSS import”@import './variables.css';@import './base.css';@import './components/buttons.css';@import './components/forms.css';Sass támogatás
Szekció neve “Sass támogatás”npm install -D esbuild-sass-pluginimport * as esbuild from 'esbuild';import { sassPlugin } from 'esbuild-sass-plugin';
await esbuild.build({ entryPoints: ['src/scss/style.scss'], bundle: true, minify: true, outfile: 'dist/css/style.css', plugins: [sassPlugin()],});TypeScript
Szekció neve “TypeScript”esbuild natívan támogatja a TypeScript-et, nincs szükség külön konfigurációra:
await esbuild.build({ entryPoints: ['src/ts/main.ts'], bundle: true, outfile: 'dist/js/main.js',});tsconfig.json
Szekció neve “tsconfig.json”{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "skipLibCheck": true, "noEmit": true }, "include": ["src"]}React és JSX
Szekció neve “React és JSX”await esbuild.build({ entryPoints: ['src/jsx/app.jsx'], bundle: true, outfile: 'dist/js/app.js', jsx: 'automatic', // React 17+ automatic runtime});React telepítése
Szekció neve “React telepítése”npm install react react-domWordPress block fejlesztés
Szekció neve “WordPress block fejlesztés”import { registerBlockType } from '@wordpress/blocks';
registerBlockType('my-plugin/my-block', { title: 'My Block', icon: 'smiley', category: 'common', edit: () => <div>Edit view</div>, save: () => <div>Saved content</div>,});await esbuild.build({ entryPoints: ['src/jsx/blocks/my-block/index.jsx'], bundle: true, outfile: 'dist/js/blocks/my-block.js', jsx: 'automatic', external: ['@wordpress/*', 'react', 'react-dom'],});Pluginek
Szekció neve “Pluginek”PostCSS plugin
Szekció neve “PostCSS plugin”npm install -D esbuild-postcss postcss autoprefixerimport * as esbuild from 'esbuild';import postcss from 'esbuild-postcss';
await esbuild.build({ entryPoints: ['src/css/style.css'], bundle: true, outfile: 'dist/css/style.css', plugins: [postcss()],});postcss.config.js
Szekció neve “postcss.config.js”export default { plugins: { autoprefixer: {}, },};Copy plugin
Szekció neve “Copy plugin”npm install -D esbuild-plugin-copyimport * as esbuild from 'esbuild';import { copy } from 'esbuild-plugin-copy';
await esbuild.build({ entryPoints: ['src/js/main.js'], bundle: true, outfile: 'dist/js/main.js', plugins: [ copy({ assets: { from: ['./src/images/*'], to: ['./images'], }, }), ],});WordPress plugin fejlesztés
Szekció neve “WordPress plugin fejlesztés”Projekt struktúra
Szekció neve “Projekt struktúra”my-plugin/├── assets/│ ├── src/│ │ ├── js/│ │ │ ├── frontend.js│ │ │ └── admin.js│ │ └── css/│ │ ├── frontend.css│ │ └── admin.css│ └── dist/├── includes/├── build.js├── package.json└── my-plugin.phpbuild.js
Szekció neve “build.js”import * as esbuild from 'esbuild';
const isProduction = process.env.NODE_ENV === 'production';
const buildConfigs = [ // Frontend JS { entryPoints: ['assets/src/js/frontend.js'], bundle: true, minify: isProduction, sourcemap: !isProduction, outfile: 'assets/dist/js/frontend.js', }, // Admin JS { entryPoints: ['assets/src/js/admin.js'], bundle: true, minify: isProduction, sourcemap: !isProduction, outfile: 'assets/dist/js/admin.js', }, // Frontend CSS { entryPoints: ['assets/src/css/frontend.css'], bundle: true, minify: isProduction, outfile: 'assets/dist/css/frontend.css', }, // Admin CSS { entryPoints: ['assets/src/css/admin.css'], bundle: true, minify: isProduction, outfile: 'assets/dist/css/admin.css', },];
await Promise.all(buildConfigs.map((config) => esbuild.build(config)));
console.log('✅ Plugin assets built!');Plugin asset betöltés
Szekció neve “Plugin asset betöltés”<?phpclass My_Plugin_Assets {
public static function init() { add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_frontend' ] ); add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_admin' ] ); }
public static function enqueue_frontend() { wp_enqueue_style( 'my-plugin-frontend', plugins_url( 'assets/dist/css/frontend.css', __FILE__ ), [], self::get_version( 'assets/dist/css/frontend.css' ) );
wp_enqueue_script( 'my-plugin-frontend', plugins_url( 'assets/dist/js/frontend.js', __FILE__ ), [], self::get_version( 'assets/dist/js/frontend.js' ), true ); }
public static function enqueue_admin( $hook ) { // Csak a plugin oldalain if ( strpos( $hook, 'my-plugin' ) === false ) { return; }
wp_enqueue_style( 'my-plugin-admin', plugins_url( 'assets/dist/css/admin.css', __FILE__ ), [], self::get_version( 'assets/dist/css/admin.css' ) );
wp_enqueue_script( 'my-plugin-admin', plugins_url( 'assets/dist/js/admin.js', __FILE__ ), [], self::get_version( 'assets/dist/js/admin.js' ), true ); }
private static function get_version( $file ) { $path = plugin_dir_path( __FILE__ ) . $file; return file_exists( $path ) ? filemtime( $path ) : '1.0.0'; }}
My_Plugin_Assets::init();Környezeti változók
Szekció neve “Környezeti változók”Define plugin
Szekció neve “Define plugin”await esbuild.build({ entryPoints: ['src/js/main.js'], bundle: true, outfile: 'dist/js/main.js', define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), 'API_URL': JSON.stringify('https://api.example.com'), },});Használat JavaScript-ben
Szekció neve “Használat JavaScript-ben”if (process.env.NODE_ENV === 'development') { console.log('Development mode');}
fetch(API_URL + '/endpoint');Development server
Szekció neve “Development server”esbuild beépített dev server-rel rendelkezik:
import * as esbuild from 'esbuild';
const ctx = await esbuild.context({ entryPoints: ['src/js/main.js'], bundle: true, outdir: 'dist',});
const { host, port } = await ctx.serve({ servedir: 'dist', port: 8000,});
console.log(`Server running at http://${host}:${port}`);Teljesítmény összehasonlítás
Szekció neve “Teljesítmény összehasonlítás”| Bundler | 1000 modulos projekt build ideje |
|---|---|
| esbuild | ~0.3s |
| Vite (esbuild) | ~0.5s |
| Rollup | ~4s |
| Webpack | ~15s |