Webpack
A minimal, practical guide to your Webpack setup built on top of @wordpress/scripts.
This page explains the config, project conventions, path aliases, environment variables, and common usage patterns.
Overview
Your build is based on the official @wordpress/scripts webpack config and then extended with a few quality‑of‑life plugins:
@wordpress/scripts/config/webpack.config– baseline configuration used by Gutenberg projects.webpack-build-notifier– native OS notifications for build errors/warnings.clean-terminal-webpack-plugin– clears the terminal before each rebuild (watch mode).dotenv-webpack– loads variables from.env.localinto your build (client‑side access must be explicit).
Configuration
webpack.config.js
const Dotenv = require('dotenv-webpack');const path = require('path');const defaultConfig = require('@wordpress/scripts/config/webpack.config');const WebpackBuildNotifierPlugin = require('webpack-build-notifier');const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
module.exports = { ...defaultConfig,
resolve: { alias: { '@utilities': path.resolve(__dirname, 'blocks/utilities'), '@configuration': path.resolve(__dirname, 'blocks/configuration'), '@components': path.resolve(__dirname, 'blocks/components'), }, extensions: ['.js', '.jsx'], // Resolve these automatically in imports },
module: { ...defaultConfig.module, rules: [...defaultConfig.module.rules], },
plugins: [ ...defaultConfig.plugins, new WebpackBuildNotifierPlugin({ title: 'Base Theme', logo: path.resolve('./webpack_icons/favicon.png'), suppressSuccess: true, }), new CleanTerminalPlugin({ beforeCompile: true, message: 'New Build Started...', onlyInWatchMode: true, }), new Dotenv({ path: '.env.local' }), ],};Notes:
- We spread (
...) the WordPress defaults first and then override/extend specific sections. resolve.aliasmaps short import paths to your block folders (see below).extensionslets you omit.js/.jsxin imports.
Folder Aliases
These aliases simplify imports in your JSX files.
alias: { '@utilities': path.resolve(__dirname, 'blocks/utilities'), '@configuration': path.resolve(__dirname, 'blocks/configuration'), '@components': path.resolve(__dirname, 'blocks/components'),}Example usage
import { Image, ImageSettings, getDefaultImageAttributes,} from '@utilities/image/image';
import { Heading, defaultHeadingAttributes } from '@utilities/heading/heading';import { Subtitle, defaultSubtitleAttributes } from '@utilities/title/subtitle';
import { SpacerSettings, defaultSpacerAttributes, spacerClass,} from '@configuration/spacer/spacer';
import { defaultColorNameAttributes, ColorSettings,} from '@configuration/color/colors';
import { defaultAlignAttributes, alignClass, AlignSettings,} from '@configuration/align/align';This keeps imports short, consistent, and editor‑friendly.
Editor IntelliSense (optional but recommended)
To enable Go to definition and auto‑import in VS Code, add a jsconfig.json (or tsconfig.json if you use TypeScript) in your project root:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@utilities/*": ["blocks/utilities/*"], "@configuration/*": ["blocks/configuration/*"], "@components/*": ["blocks/components/*"] } }, "exclude": ["node_modules"]}Environment Variables
dotenv-webpack loads variables from .env.local at build time. Examples:
# ExampleAPI_BASE_URL=https://api.example.comFEATURE_FLAG_EXPERIMENTAL=trueIn code, access via process.env:
const api = process.env.API_BASE_URL;Important: Anything bundled client‑side is not private. Only expose values safe for the browser.
NPM Scripts
With @wordpress/scripts, you typically use:
{ "scripts": { "start": "wp-scripts start", // dev server / watch "build": "wp-scripts build", // production build "lint:js": "wp-scripts lint-js", "format": "wp-scripts format" }}start: watches files and rebuilds on change; terminal is cleared each cycle.build: creates optimized output for production.
How It Fits Together
- You write blocks under
blocks/…using the aliases for imports. - Running
start/builduses the WordPress webpack base plus your plugins. - Dotenv injects environment values.
- Outputs are generated per the defaults from
@wordpress/scripts(asset files, dependencies, etc.).
Common Recipes
Import without extensions
Thanks to resolve.extensions, these are equivalent:
import { Image } from '@utilities/image/image';// instead ofimport { Image } from '@utilities/image/image.jsx';Add another alias
resolve: { alias: { ..., '@hooks': path.resolve(__dirname, 'blocks/hooks') }}Limit noisy notifications
new WebpackBuildNotifierPlugin({ title: 'Base Theme', suppressSuccess: true, // only show warnings/errors suppressWarning: false,});Troubleshooting
-
Alias not resolved
Ensure the path exists and matches the project structure. Add ajsconfig.jsonto help VS Code. -
process.envis undefined
Confirm.env.localexists and thatnew Dotenv({ path: '.env.local' })is present. Restart the dev server after changes. -
Unexpected file extension errors
Make sureextensions: ['.js', '.jsx']includes all extensions you use (e.g., add'.ts', '.tsx'for TypeScript). -
No notifications on macOS/Linux/Windows
Some environments require enabling desktop notifications or allowing the terminal app to send them.
FAQ
Q: Can I add TypeScript?
Yes. Add ts-loader or use Babel preset TS, include '.ts', '.tsx' in resolve.extensions, and create a tsconfig.json.
Q: How do I analyze bundle size?
Install webpack-bundle-analyzer and add it to plugins in a conditional (only in production).
Q: Where do outputs go?
@wordpress/scripts manages output and asset manifests. If you need custom output rules, you can extend output but be careful not to break WordPress asset handling.
Summary
- Based on
@wordpress/scriptswith sensible extensions. - Aliases keep imports clean and maintainable.
- Dotenv powers environment‑specific values.
- Notifier + Clean Terminal improve DX.
That’s it — you’re set up for a smooth Gutenberg block development experience with Webpack.