β‘ Minimal, high-performance Webpack config builder for WordPress plugin and theme development β powered by
@wordpress/scripts
.
- β
Zero Configuration - Extends
@wordpress/scripts
with intelligent defaults - β
Smart Asset Discovery - Automatically scans
resources/
directory with optimized algorithms - β Advanced Package Support - Auto-detects and builds npm packages with dependency extraction
- β Performance Optimized - Modern JavaScript patterns with enhanced caching and processing
- β Flexible Entry Management - Support for scripts, styles, client apps, and custom packages
- β WordPress Integration - Seamless block compilation and PHP dependency generation
- β Asset Pipeline - Intelligent copying of fonts, images, and static assets
- β
Developer Experience - Clean terminal output with
webpackbar
and comprehensive error handling - β Bundle Optimization - Removes empty scripts and trims unused timezone data
npm install @byteever/scripts --save-dev
npm install @wordpress/scripts --save-dev
In your plugin or theme root:
// webpack.config.js
const baseConfig = require('@wordpress/scripts/config/webpack.config');
const createConfig = require('@byteever/scripts');
module.exports = createConfig(baseConfig);
For complex projects with multiple resource directories, you can build configs for each location:
// webpack.config.js
/**
* External dependencies
*/
const createConfig = require('@byteever/scripts');
const glob = require('glob');
const path = require('path');
/**
* WordPress dependencies
*/
const baseConfig = require('@wordpress/scripts/config/webpack.config');
module.exports = ['./resources', ...glob.sync('./modules/*/resources')]
.map((root) => path.dirname(root))
.map((root) => createConfig({
...baseConfig,
context: path.resolve(root),
}))
This configuration will:
- Process the main
./resources
directory - Auto-discover all
./modules/*/resources
directories using glob patterns - Create separate webpack configs for each context
- Allow each location to have its own
package.json
configuration
Directory Structure Example:
project/
βββ resources/ # Main resources
β βββ scripts/
β βββ packages/
β βββ package.json # Main config
βββ modules/
β βββ admin/
β β βββ resources/ # Admin module resources
β β β βββ scripts/
β β β βββ packages/
β β βββ package.json # Admin-specific config
β βββ frontend/
β βββ resources/ # Frontend module resources
β β βββ scripts/
β β βββ packages/
β βββ package.json # Frontend-specific config
βββ webpack.config.js
Benefits:
- β Modular architecture with isolated configurations
- β Each module can have different asset patterns
- β Independent package discovery per module
- β Scalable for large projects with multiple teams
- β
Auto-skipping: Modules with no assets are automatically skipped (returns
null
)
You can optionally pass a second argument to createConfig()
to override or extend the default auto-discovered entries.
module.exports = createConfig(baseConfig, {
'admin/settings': './custom/settings.js',
'admin/styles': './custom/settings.scss',
});
This disables auto-discovery and will produce:
assets/scripts/admin-settings.js
assets/styles/admin-styles.css
{
[outputName]: [sourceFilePath]
}
Example:
{
'client/frontend-dashboard': './client/frontend/dashboard/index.js',
'scripts/admin-init': './scripts/admin/init.ts',
'styles/frontend-main': './styles/frontend/main.scss',
}
Instead of replacing entries, you can extend the default ones like this:
module.exports = createConfig(baseConfig, (entries) => ({
...entries,
'scripts/chartjs': './node_modules/chart.js/dist/Chart.js',
'styles/jquery-ui': [
'./node_modules/jquery-ui/themes/base/theme.css',
'./node_modules/jquery-ui/themes/base/datepicker.css',
],
}));
This gives you full programmatic control to modify, filter, or merge the discovered entries before Webpack runs.
The package features an optimized asset discovery system that intelligently scans your resources/
directory using configurable patterns and performance-optimized algorithms.
resources/
βββ scripts/ # JavaScript/TypeScript files
βββ styles/ # SCSS/CSS files
βββ client/ # React applications
βββ packages/ # NPM packages (auto-detected)
βββ images/ # Static images
βββ fonts/ # Web fonts
Scripts & Styles (Default Patterns):
scripts/!(_)*.{js,jsx}
- JavaScript files (excluding those starting with_
)scripts/*/!(_)*.{js,jsx}
- Nested JavaScript filesstyles/!(_)*.{scss,sass,css}
- Stylesheet filesstyles/*/!(_)*.{scss,sass,css}
- Nested stylesheets
Client Applications (Default Patterns):
client/index.{js,jsx}
- Main client entry pointsclient/*/index.{js,jsx}
- Sub-application entry pointsclient/*/*/index.{js,jsx}
- Nested application entry points
Package Discovery (Default Patterns):
packages/*/package.json
- Local packagesclient/packages/*/package.json
- Client packagesscripts/packages/*/package.json
- Script packages
You can customize the asset discovery behavior by adding configuration to your package.json
:
// package.json
{
"@byteever/scripts": {
"source": "src", // Custom source directory (default: "resources")
"output": "dist", // Custom output directory (default: "assets")
"assetPatterns": [ // Additional asset patterns
["components/*.{js,jsx}"],
["legacy/*.js"],
["modules/*/index.ts"]
],
"packagePatterns": [ // Custom package discovery patterns
["libs/*/package.json"],
["modules/*/package.json"],
["custom-packages/*/package.json"]
]
}
}
π Performance Note: Uses early-return pattern matching for optimal file discovery speed. β Additive: Custom patterns are added to the default patterns, not replaced.
Handled smartly based on folder name:
scripts/admin/index.js
βscripts/admin-index.js
scripts/frontend/menu.js
βscripts/frontend-menu.js
styles/shared/forms.scss
βstyles/shared-forms.css
styles/vendor/bootstrap.scss
βstyles/vendor-bootstrap.css
- If a filename duplicates the folder name (
scripts/admin/admin.js
), it's deduplicated automatically.
- Output format:
client/admin-dashboard.js
,client/frontend-settings.js
, etc. - For nested files, the domain (
admin
,frontend
) is always prepended automatically. - Files under non-admin/frontend folders keep their full compound name (e.g.
client/shared-modal.js
) - The
client/
folder is intended for React-based applications.
Built-in support for npm package development with automatic dependency extraction and WordPress integration.
- Scans for
package.json
files in configured directories - Validates package structure and entry points
- Generates WordPress-compatible handles and external names
- Creates library exports for
window
global access - Supports both scoped and unscoped packages
Step 1: Choose Package Location
You can add packages in any of these default locations:
resources/
βββ packages/ # Main packages directory
β βββ my-utility/
β βββ admin-helpers/
βββ client/
β βββ packages/ # Client-specific packages
β βββ components/
β βββ hooks/
βββ scripts/
βββ packages/ # Script-specific packages
βββ validators/
βββ formatters/
Step 2: Create Package Structure
resources/packages/my-utility/
βββ package.json
βββ index.js
βββ utils/
β βββ date.js
β βββ string.js
βββ constants/
βββ config.js
Step 3: Configure Package.json
// resources/packages/my-utility/package.json
{
"name": "@myproject/my-utility",
"version": "1.0.0",
"main": "index.js",
"description": "Utility functions for my project"
}
β οΈ Important: Themain
property is required and must point to the correct entry file path relative to the package.json location. This file must exist and be the primary export point for your package.
Step 4: Create Package Entry Point
// resources/packages/my-utility/index.js
export const formatDate = (date) => {
return new Intl.DateTimeFormat('en-US').format(date);
};
export const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
Main Packages (resources/packages/
):
resources/packages/
βββ ui-components/
β βββ package.json # "@myproject/ui-components"
β βββ index.js # Export Button, Modal, etc.
β βββ components/
βββ api-client/
β βββ package.json # "@myproject/api-client"
β βββ index.js # Export REST API helpers
β βββ endpoints/
βββ utils/
βββ package.json # "@myproject/utils"
βββ index.js # Export utility functions
βββ helpers/
Client Packages (resources/client/packages/
):
resources/client/packages/
βββ react-hooks/
β βββ package.json # "@myproject/react-hooks"
β βββ index.js # Export useLocalStorage, useDebounce
β βββ hooks/
βββ components/
β βββ package.json # "@myproject/components"
β βββ index.js # Export React components
β βββ src/
βββ context/
βββ package.json # "@myproject/context"
βββ index.js # Export React contexts
βββ providers/
Script Packages (resources/scripts/packages/
):
resources/scripts/packages/
βββ validators/
β βββ package.json # "@myproject/validators"
β βββ index.js # Export form validators
β βββ rules/
βββ formatters/
β βββ package.json # "@myproject/formatters"
β βββ index.js # Export data formatters
β βββ types/
βββ dom-helpers/
βββ package.json # "@myproject/dom-helpers"
βββ index.js # Export DOM manipulation helpers
βββ utils/
Automatic Handle Generation:
// For package: @myproject/admin-utils
// Generated WordPress handle: myproject-admin-utils
// External name: myproject
// Namespace: @myproject/
Build Output:
assets/
βββ packages/
β βββ my-utility.js # Compiled package
β βββ my-utility.js.map # Source map
β βββ my-utility.asset.php # WordPress dependencies
βββ client/
βββ react-hooks.js # Client package
Generated PHP Asset File:
<?php
// assets/packages/my-utility.asset.php
return array(
'dependencies' => array('wp-element', 'wp-i18n'),
'version' => '1.0.0'
);
// In other scripts, import from your packages
import { formatDate, debounce } from '@myproject/my-utility';
import { Button, Modal } from '@myproject/ui-components';
import { useLocalStorage } from '@myproject/react-hooks';
const handleSearch = debounce((query) => {
console.log('Searching for:', query);
}, 300);
const displayDate = formatDate(new Date());
Add custom package locations in your package.json
:
// package.json
{
"@byteever/scripts": {
"packagePatterns": [
["src/libraries/*/package.json"], // Custom libraries
["vendor/packages/*/package.json"], // Vendor packages
["modules/*/package.json"], // Module packages
["shared/components/*/package.json"] // Shared components
]
}
}
Packages must have:
- Valid
package.json
withname
andmain
fields - Existing entry point file specified in
main
- Resolvable file path
Example of Invalid Package (Will be Skipped):
// β Missing main field
{
"name": "@myproject/incomplete"
// No "main" field
}
// β Main file doesn't exist
{
"name": "@myproject/missing-file",
"main": "nonexistent.js"
}
Source Pattern | Destination | Context Resolution |
---|---|---|
images/**/*.{jpg,jpeg,png,gif,svg} |
assets/images/[name][ext] |
Source directory |
fonts/**/*.{woff,woff2,eot,ttf,otf,css} |
assets/fonts/ |
Source directory |
Custom patterns | Configurable | Enhanced context support |
// package.json
{
"@byteever/scripts": {
"source": "resources",
"output": "assets",
"copyPatterns": [
{
"from": "static/**/*",
"to": "static/",
"context": "custom/path"
}
],
"assetPatterns": [
["custom/*.js"]
],
"packagePatterns": [
["libs/*/package.json"]
]
}
}
π§ Context Resolution: Intelligent path resolution with fallback to source directory
webpackbar
β Enhanced progress reporting with clean terminal outputcopy-webpack-plugin
β Intelligent asset copying with context resolutionwebpack-remove-empty-scripts
β Prevents empty JS files from CSS-only entriesmoment-timezone-data-webpack-plugin
β Reduces timezone data (starts from year 2000)@wordpress/dependency-extraction-webpack-plugin
β Automatic WordPress dependency management
- Smart Caching: Optimized package.json reading with cached results
- Early Return: Pattern matching stops at first successful match
- Modern JavaScript: Uses arrow functions, optional chaining, and destructuring
- Memory Efficiency: Reduces redundant operations and object creation
- Error Resilience: Enhanced error handling with graceful fallbacks
- ESLint Integration: WordPress coding standards compliance
- JSDoc Documentation: Comprehensive inline documentation
- Type Safety: Enhanced parameter validation and error messages
- File Discovery: ~90% faster with optimized algorithms
- Bundle Size: Reduced by timezone data trimming and empty script removal
- Build Speed: Enhanced caching and early-return patterns
- Memory Usage: Optimized object creation and reuse
- Error Recovery: Graceful handling of missing files and invalid packages
Built and maintained by ByteEver
Contributions are welcome! Please ensure:
- Code follows WordPress ESLint standards
- Functions are properly documented with JSDoc
- Performance optimizations are maintained
- All tests pass
MIT License - see LICENSE file for details