Skip to main content
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

1

Transpilation

Convert modern JavaScript (ES6+) to code compatible with older browsers
2

JSX transformation

Convert JSX syntax to standard JavaScript function calls
3

Module bundling

Combine multiple files into optimized bundles
4

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

npm run build
Creates optimized, minified files in the build/ directory for production.

What wp-scripts does

@wordpress/scripts handles:

JavaScript transformation

// 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

Browser DevTools

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

Build docs developers (and LLMs) love