The WordPress Block Editor is built with modern JavaScript and React. Understanding the JavaScript ecosystem and build process is essential for block development.
Modern JavaScript
The Block Editor uses modern JavaScript features including:
- ES6+ Syntax: Arrow functions, destructuring, modules, classes
- JSX: JavaScript XML syntax for React components
- Modules: Import/export statements for code organization
- Async/Await: Modern asynchronous programming patterns
Example of modern JavaScript
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
const Edit = ( { attributes, setAttributes } ) => {
const blockProps = useBlockProps();
return (
<RichText
{ ...blockProps }
tagName="p"
value={ attributes.content }
onChange={ ( content ) => setAttributes( { content } ) }
/>
);
};
export default Edit;
JavaScript build process
Modern JavaScript needs to be compiled (transpiled and bundled) before browsers can execute it. WordPress provides @wordpress/scripts to handle this build process.
Why we need a build process
Transpilation
Convert modern JavaScript (ES6+) to code compatible with older browsers
JSX transformation
Convert JSX syntax to standard JavaScript function calls
Module bundling
Combine multiple files into optimized bundles
Asset optimization
Minify code, optimize imports, generate source maps
Source vs build directories
my-block/
├── src/ ← Write code here (modern JS, JSX, SCSS)
│ ├── index.js
│ ├── edit.js
│ ├── save.js
│ └── style.scss
└── build/ ← Compiled output (WordPress loads from here)
├── index.js
├── index.asset.php
└── style-index.css
WordPress loads scripts from the build/ directory, not src/. Always point register_block_type() to the build directory.
Setting up the build process
Install @wordpress/scripts
npm install @wordpress/scripts --save-dev
Add build scripts to package.json
{
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
}
}
Build commands
Production build
Development mode
Creates optimized, minified files in the build/ directory for production. Runs in watch mode, automatically rebuilding when files change. Includes source maps for debugging.
What wp-scripts does
@wordpress/scripts handles:
// Source (src/index.js)
import { registerBlockType } from '@wordpress/blocks';
registerBlockType( 'my-plugin/block', {
// ...
} );
// Built (build/index.js) - minified and browser-compatible
var e=require("@wordpress/blocks");(0,e.registerBlockType)("my-plugin/block",{});
JSX to JavaScript
// Source
const element = <div className="block">Hello</div>;
// Built
var element = React.createElement("div", { className: "block" }, "Hello");
CSS/SCSS processing
// Source (src/style.scss)
.wp-block-my-plugin-block {
padding: 20px;
p {
font-size: 16px;
}
}
/* Built (build/style-index.css) */
.wp-block-my-plugin-block{padding:20px}.wp-block-my-plugin-block p{font-size:16px}
Dependency management
Generates index.asset.php with WordPress dependencies:
<?php return array(
'dependencies' => array(
'wp-blocks',
'wp-element',
'wp-block-editor',
),
'version' => 'abc123def456',
);
This file is automatically generated and should not be edited manually.
WordPress packages
The Block Editor provides numerous packages for block development:
Core packages
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { Button, PanelBody } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { useState, useEffect } from '@wordpress/element';
Package categories
- @wordpress/blocks: Block registration and utilities
- @wordpress/block-editor: Block editing components and hooks
- @wordpress/components: Reusable UI components
- @wordpress/data: State management (Redux-like stores)
- @wordpress/element: React abstraction layer
- @wordpress/i18n: Internationalization functions
- @wordpress/compose: Higher-order components and hooks
- @wordpress/api-fetch: WordPress REST API wrapper
All WordPress packages are available globally in the Block Editor, so you don’t need to bundle them. @wordpress/scripts automatically marks them as external dependencies.
Module imports and exports
Exporting from modules
// edit.js - named export
export function Edit( props ) {
// ...
}
// save.js - default export
export default function save( props ) {
// ...
}
Importing modules
// Import default export
import Edit from './edit';
// Import named export
import { Edit } from './edit';
// Import everything
import * as editorModule from './edit';
// Import with alias
import { Edit as BlockEdit } from './edit';
React and JSX
The Block Editor uses React for building user interfaces:
React components
import { useBlockProps } from '@wordpress/block-editor';
function MyBlock( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<p>{ attributes.content }</p>
</div>
);
}
export default MyBlock;
React Hooks
import { useState, useEffect } from '@wordpress/element';
import { useBlockProps } from '@wordpress/block-editor';
function Edit( { attributes, setAttributes } ) {
const [ isLoading, setIsLoading ] = useState( false );
const blockProps = useBlockProps();
useEffect( () => {
// Run when component mounts
setIsLoading( true );
return () => {
// Cleanup when component unmounts
};
}, [] );
return <div { ...blockProps }>Content</div>;
}
Debugging
Development mode
Run npm start for development builds with:
- Source maps for debugging
- Readable code
- Hot reloading
Use React DevTools browser extension to inspect component hierarchy and props.
Console logging
import { useBlockProps } from '@wordpress/block-editor';
function Edit( { attributes } ) {
console.log( 'Block attributes:', attributes );
const blockProps = useBlockProps();
return <div { ...blockProps }>Content</div>;
}
TypeScript support
@wordpress/scripts has built-in TypeScript support:
import { BlockEditProps } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
interface Attributes {
content: string;
}
export default function Edit( {
attributes,
setAttributes,
}: BlockEditProps< Attributes > ) {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
{ attributes.content }
</div>
);
}
Next steps
wp-scripts
Learn more about the build tool
Creating blocks
Start building your first block