Client-side WebAssembly WordPress with no server

This early demo runs a full WordPress directly in the browser without a PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher server! While it isn’t fully stable yet, it is a major breakthrough that could transform learning, contributing, and using WordPress. This post explores the opportunities and explains in detail how it works. 

Your help is needed to realize the vision laid out below. None of the presented mockups and early explorations are currently reliably implemented. This project needs volunteers to stabilize the code and build revolutionary tools on top of it. If you’d like to be a part of it, please say so in the comments!

Learning WordPress in the browser

The code examples in the WordPress handbook could become runeditable, like in this early preview:

Furthermore, an in-browser IDEIDE Integrated Development Environment. A software package that provides a full suite of functionality to software developers/programmers. Normally an IDE includes a source code editor, code-build tools and debugging functionality. could lead new contributors through solving their first “Good first issue” without setting up a local development environment. Just like this early preview:

Finally, a guided code editor could become a primary teaching tool for new developers. They would click a “Build your first blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.” button on WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ and immediately start coding. This is what it could look like:

WordPress Developer tools

Testing code on different WordPress, PHP, and GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ versions currently require a tedious setup. With an in-browser WordPress IDE, it wouldn’t require any setup at all. As a developer, you would switch between the different versions by selecting different entries in a box:

Taking it further, the continuous integration pipeline could replay the failed tests right in the browser and provide a code editor to debug and fix the problem on the spot:

On a different note, the desktop and mobile apps could reuse WordPress code by running an actual WordPress instance – even when offline.

Finally, WordPress could potentially be scaled up by spinning up many tiny self-contained WASM instances directly on the edge servers.

Showcasing

Embedding a demo of your pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party, pattern, or theme directly on the website makes another great use case. One such demo lives on wpreadme.com, an in-browser WordPress readme.txt editor. Here’s what the plugin directory could look like:

Today, a WordPress server is required, and ideally, one WordPress per user to always present the same initial state.

The in-browser WordPress enables one private WordPress per user with no marginal server cost. Everyone can start logged-in as an adminadmin (and super admin) with no security risks.

Furthermore, importing an existing WordPress website into WASM runtime would create a staging website. Users could try themes and plugins on a copy of their site without affecting the live sites. Then, once the staging website looks good, they’d click a button and publish the changes.

How else would you use the in-browser WordPress? Please share your ideas in the comments so more use cases can be considered in the future.

How does the in-browser WordPress work?

The code lives in the GitHub repository.

In short:

  • PHP is compiled to WASM with Emscripten
  • WordPress is packaged into a data bundle
  • A service worker traps HTTPHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. requests and re-routes them to WordPress.

See more details below.

PHP is compiled to WASM with Emscripten

Firstly, PHP is compiled using an adjusted recipe from the php-wasm repo. It’s powered by Emscripten, a drop-in replacement for the C compiler. Unfortunately, MySQLMySQL MySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com/. currently cannot run as WASM. However, SQLite can, and WordPress supports SQLite via the wp-db-sqlite plugin.

Emscripten compilation yields two files: webworker-php.wasm, which is the assembly, and webworker-php.js, which downloads the assembly file, creates a virtual heap, and exposes named native functions conveniently wrapped to accept and return JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. data types.

You need to load the webworker-php.js in a webworker and add a tiny wrapper class:

const php = new PHPWrapper();
console.log(
    await php.run(`<?php echo "Hello world";`).stdout
);
// "Hello world"

See the Dockerfile, the compilation script, and the php-wasm playground.

WordPress is packaged into a data bundle

WebAssembly PHP runtime has its own filesystem and WordPress is shoehorned into it as a data bundle.

First, a fresh WordPress distribution is downloaded and patched with the wp-db-sqlite plugin. It’s about 66MB large, but an optimization pipeline makes that 46MB by minifying the PHP files and removing non-essential static assets. Getting down to just 12MB is possible, but it’s not easy.

Second, the WordPress installation process kicks in. A script serves our WordPress via the built-in PHP server and sends a special curl request to /wp-admin/install.php?step=2. Unfortunately, wp-cliWP-CLI WP-CLI is the Command Line Interface for WordPress, used to do administrative and development tasks in a programmatic way. The project page is http://wp-cli.org/ https://make.wordpress.org/cli/ is hard-wired to MySQL and not a good match here.

Lastly, Emscripten’s file_packager turns our WordPress copy into a data file named wp.data and a JavaScript loader named wp.js. Loading both the PHP runtime from webworker-php.js and the WordPress data bundle from wp.js allows you to run <?php require “wordpress/index.php”; right in the browser!

A service worker reroutes the HTTP to WordPress

WordPress reads request information from $_SERVER, $_GET, $_COOKIE and so on. Normally these variables are populated by ApacheApache Apache is the most widely used web server software. Developed and maintained by Apache Software Foundation. Apache is an Open Source software available for free., NginxNGINX NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability. In addition to its HTTP server capabilities, NGINX can also function as a proxy server for email (IMAP, POP3, and SMTP) and a reverse proxy and load balancer for HTTP, TCP, and UDP servers. https://www.nginx.com/., or another web server. However, in this case, there isn’t one.

Instead, the superglobal variables are populated “manually”:

function request(path, method, body, cookies) {
    return php.run(`<?php
        $_POST   = json_parse('${JSON.stringify(body)}');
        $_COOKIE = json_parse('${JSON.stringify(cookies)}');
        $_SERVER['REQUEST_URI'] 	= $path;
        $_SERVER['REQUEST_METHOD']  = "${method}";
        require "wordpress/index.php";
    `);
}

That takes care of the request, but capturing the complete HTTP response is still necessary. The PHP outputs information in only two ways: stdout and stderr. The response body comes out via stdout, but the HTTP status code and headers don’t. They need to be manually streamed to stderr where the JavaScript app can capture them:

register_shutdown_function(function() use() {
    $stdErr = fopen('php://stderr', 'w');
    fwrite($stdErr, json_encode(['status_code', http_response_code()]) . "\n");
    fwrite($stdErr, json_encode(['session_id', session_id()]) . "\n");
    fwrite($stdErr, json_encode(['headers', headers_list()]) . "\n");
}

The final request handler is similar to this:

function request(path, method, body, cookies) {
    const { stdout, stderr, exitCode } = php.run(`<?php
        $_POST   = json_parse('${JSON.stringify(body)}');
        // ... Populate other superglobals...
 
        register_shutdown_function(function() use() {
            $stdErr = fopen('php://stderr', 'w');
            fwrite($stdErr, json_encode(['status_code', http_response_code()]) . "\n");
            // Output other information
        }
 
        require "wordpress/index.php";
    `);
 
    const { statusCode, headers, body } =
        rawOutputToResponse({ stdout, stderr, exitCode });
    return { statusCode, headers, body };
}

The actual code is much more involved, but it’s based on the same idea.

Node.js is supported, too

Running WordPress in different JSJS JavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. runtimes is a matter of connecting these major building blocks with runtime-specific plumbing. Today there is an in-browser version and a node.js version. Here’s how they differ:

In-browser version

WordPress is rendered in an iframeiframe iFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the user’s browser. by a minimal index.htmlHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. once both workers are loaded.

Node.js version

  • Emscripten compiles PHP for the Node.js runtime.
  • A Node.js script loads the WebAssembly PHP and mounts a local WordPress directory inside the PHP filesystem.
  • The same Node.js script starts a web server. It serves most requests as static files, except the .php ones, which it routes to WordPress.

WordPress is served on localhost:8888.

Running an in-browser WordPress IDE with Stackblitz

Stackblitz is the in-browser IDE that makes Svelte docs interactive:

It could do the same for WordPress docs; see this early preview.


Stackblitz doesn’t need a specialized backend. It runs Node.js, npm, and webpack right in the browser via WebAssembly. Other than hosting and delivering a few megabytes of data, Stackblitz has no marginal costs. This idea is called Web Containers.

Learning WordPress and writing code used to be separated. Now they can be one and the same. From runnable code snippets to new, svelte-like docs formats, WebContainers + WebAssembly WordPress is an educational game-changer.

WordPress runs in Stackblitz via a Node.js server

The minimal WordPress plugin dev setup on Stackblitz consists of:

  • A node.js WordPress server (via an npm package)
  • A plugin directory mounted inside of mu-plugins
  • A wp-scripts setup to watch and bundle the JavaScript files

@gziolo went a step further and prepared a version with an editable Gutenberg block generated via create-block. All it took was running the npx @wordpress/create-block example-static command as shown in the create-block documentation, and restarting the dev server with npm run start:

However, a Node.js WordPress server on Stackblitz is sluggish

Rendering a single wp-admin page takes a second locally but up to 40 seconds on Stackblitz. That’s much longer than most developers are willing to wait. Here’s why that happens:

A local Node.js WordPress server works like this:

  • WordPress runs on WebAssembly PHP
  • WebAssembly PHP runs on a native Node.js

However, a Stackblitz Node.js WordPress server has an extra layer:

  • WordPress runs on WebAssembly PHP
  • WebAssembly PHP runs on WebAssembly Node.js
  • WebAssembly Node.js runs on a native Chrome

It’s like a box in a box: A WebAssembly runtime in Chrome runs Node.js that has its own WebAssembly runtime. WordPress runs on the latter, not on the former, and that indirection causes a massive slowdown.

Luckily, the browser can run WebAssembly natively without an intermediate Node.js layer.

An in-browser WASM WordPress is really fast

Here’s a Stackblitz WordPress setup using the webworker WordPress version:

It is much faster! Unfortunately, the speed comes at the expense of simplicity.

Stackblitz requires a service worker just like the in-browser WASM WordPress. However, you can only have one per domain. Therefore, the WordPress files in this example are hosted on a Netlify domain.

Then, the Stackblitz files can’t be directly mounted into the in-browser PHP filesystem. The changes need to be synchronized manually. In this example, a node.js file watcher notifies the PHP webworker about the updates via WebSockets and onmessage/postMessage. There are bugs, but all are fixable.

Known issues

WASM WordPress issues:

  • The in-browser WordPress builds sometimes crash the Chrome tab, see the GitHub issue. Firefox, Safari, and node.js are much more stable.

Stackblitz integration issues:

  • The in-browser Stackblitz setup doesn’t watch subdirectories.
  • WordPress exceeds Stackblitz size limits unless imported as a node_module.
  • Stackblitz corrupts a predefined binary .sqlite database file. A base64-encoded version is shipped instead.
  • Stackblitz doesn’t pass a server-side set-cookie headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. to the browser. That’s a bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority.. Workaround: the express.js server handles the cookies internally.

Next steps

Your help is needed to fully realize the vision laid above. None of the presented mockups and early explorations is currently reliably implemented. This project needs contributors to stabilize the code and build revolutionary tools on top of it – see the issues list on GitHub. If you’d like to be a part of it, please say so in the comments!

Resources

Props to @bph, @annezazu, and @gziolo for their thorough help with reviewing and editing this post.

#core, #editor, #proposal

A new system for simply and reliably updating HTML attributes

This call for feedback will be open until September 9th.

Let’s introduce a reliable tool WordPress could use to adjust the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. markup. The current practice of using basic replacements seems fine at a first glance but is easy to break. The system proposed here will help avoid these common pitfalls.

Consider this example of adding a style HTML attribute in the cover block:

preg_replace( '/class=\".*?\"/', '${0} style="' . $styles . '"', $html );

It assumes a specific HTML structure:

  • There is a class attribute
  • The style attribute isn’t already defined, as browsers ignore the repeated attributes.
  • There is no other attribute ending with the string class="", such as data-replace-class="…" or title='how to set the class="" attribute'
  • The existing class attribute uses double quotes and no single quotes or no quotes.
  • Regular HTML does not contain the class="" substring, for example in a post describing how to use the class attribute in an HTML document.

These assumptions are typically true, but only until they’re not. For example, applying a padding produces a markup such as below where the browsers ignore the second style attribute:

<!-- Formatting applied for clarity -->
<div
    class="wp-block-cover"
    style="background-image:url(/img.png);"
    style="padding-top:4px">

The original preg_replace could be patched, but eventually another assumption would break. The deeper, fundamental problem is that string replacements are not the right tool for updating HTML. They’re used out of necessity as WordPress does not provide any better tools. Well, let’s change it!

Let’s introduce a dedicated tool for reliably updating the HTML markup. It’s called WP_HTML_Walker:

$w = new WP_HTML_Walker( '<div></div>' );
$w->next_tag();
$w->set_attribute( 'style', $styles );
$updated_html = (string) $w
// <div style="display: block"></div>

Simple string replacements don’t account for nuances in HTML

The problem of updating HTML attributes frequently appears in block-related work. Recently @dmsnell and I (@zieladam) investigated how HTML attributes are typically updated in the WordPress codebase while exploring adding a CSS class to all Gutenberg blocks. We found the typical approach is to use string replacements similar to the one covered above.

Here are a few examples already in CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. where we run into these nuanced problems:

The Site Logo block attempts to remove the href attribute:

// Remove the link.
preg_replace( '#<a.*?>(.*?)</a>#i', '\1', $custom_logo );

However, it also unintentionally removes all the attributes, including class and style.

The gallery block adds a CSSCSS Cascading Style Sheets. class:

preg_replace('/' . preg_quote( 'class="', '/' ) . '/', 'class="' . $class . ' ', $content, 1);

However, if there’s no existing class attribute, it will skip over the tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) without adding the required class. The same technique is used in the duotone feature, and the block supports API.

As a side note, it’s easy to lean on the existing pattern of using more complicated functions such as preg_replace(). Calling preg_quote() in this example isn’t appropriate and the entire regular expression pattern does nothing more than a basic str_replace().

The block-supports APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. attempts to find the first HTML tag:

preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );

However, it also matches non-tags like text hearts and mathematical expressions (<3, f(x) = {x, x<5; -1, x>=5}), DOCTYPE declarations, and HTML comments.

The media library adds the srcset attribute:

preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $attr . ' />', $image );

However, a > character inside a tag attribute (e.g. title="why tacos > burritos")  would break the srcset functionality and potentially introduce a vector for injection attacks.

The list goes on, and it’s not just blocks.

Here’s an example from shortcodes:

if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {

Media Embeds:

if ( preg_match_all( '#<(?P<tag>' . $tags . ')[^<]*?(?:>[\s\S]*?<\/(?P=tag)>|\s*\/>)#', $content, $matches ) ) {

Media Galleries:

preg_match_all( '#src=([\'"])(.+?)\1#is', $gallery, $src, PREG_SET_ORDER );

Twentynineteen:

preg_replace( '/<a\s.*?>/', $link, $item_output, 1 );

And many, many other places. The point is, this is how WordPress does it today.

Many features demand a more reliable way of updating HTML attributes. Block theming code, in particular, tends to modify block markup to apply visual styling:

The only way to reliably update HTML attributes is to follow the HTML specification. However, doing that from scratch every time a CSS class is added would only cloud the entire codebase with HTML parsing nuances and distract from the work being done. That’s why @dmsnell, @gziolo, and I (@zieladam) want to move this complexity into Core. It would be exposed as a tailored and restricted API that’s easy to use, hard to mess up, and easy to find.

The new system tokenizes HTML

WP_HTML_Walker (Pull Request 43268) recognizes HTML tags and updates their attributes. It’s reliable because it implements the same official HTML specification as WebKit, Chrome, Firefox, and other major browser engines.

Unlike full-fledged HTML parsers, the walker avoids handling malformed markup, semantic problems, and building a document tree. Any problems that are present on the input are passed on to the browser. The walker doesn’t fix HTML just as it won’t break HTML.

The tradeoff is that it only offers a simplified API to modify HTML attributes. If you want to replace an img tag with a full-fledged figure layout, this API won’t offer that functionality. Similarly, the walker won’t help you replace all the child nodes of a particular div with a completely new markup. This system is focused on finding specific HTML tags and adding, removing, or updating the attributes on those tags.

Remove the href attribute from an anchor tag:

$w = new WP_HTML_Walker( $html );
$w->next_tag( 'a' );
$w->remove_attribute( 'href' );

Add a style attribute to the first tag in the document:

$w = new WP_HTML_Walker( $html );
$w->next_tag();
$w->set_attribute( 'style', 'display: none' );

Add a CSS class to the first tag having the wp-block-media-text__content class:

$w = new WP_HTML_Walker( $html );
$w->next_tag(array(
    'class_name' => 'wp-block-media-text__content'
));
$w->add_class( 'wp-foo-bar' );

Add the srcset attribute to all image tags:

$w = new WP_HTML_Walker( $html );
while ( $w->next_tag() ) {
    if (
        isset( $w->get_attribute( 'src' ) ) &&
        ! isset( $w->get_attribute( 'srcset' )
    ) {
        $srcset = build_srcset( $w->get_attribute( 'src' ) );
        $w->set_attribute( 'srcset', $srcset );
    }
}

Processing HTML using this Core API could help avoid a broad array of mistakes that appear due to the oversimplification presented by the array of ad-hoc solutions. A common interface for operations on block markup would alleviate competition between changes. You can check the refactoring PR to see how this new API could improve code readability in the existing core blocks.

Why build a new API instead of using DOMDocument?

Using DOMDocument was extensively discussed. It’s not installed on every host so a polyfill would still be necessary. And even if it was available everywhere, it’s based on libxml2 designed to parse XML. Libxml2 does not implement the WHATWG HTML parsing spec, does not support HTML5, and brings with it a variety of parsing failures and quirks.

Like many DOM libraries, DOMDocument is a heavy interface that rewrites entire documents after several stages of transformation. In contrast, the walker exposes a focused interface closer to what string functions offer. For the kind of modifications occurring in WordPress this is a more natural and convenient approach.

If this resonates with you then please speak out before September 9th

This post will be open for feedback for the next three weeks until September 9th. After that @dmsnell, @gziolo, and @zieladam would like to merge the new API into the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party to power adding CSS classes to Gutenberg blocks, block layout improvements, and changes in CSS style variations.

Also see the WP_HTML_Walker Pull Request.

Props to Dennis Snell (@dmsnell), Grzegorz Ziółkowski (@gziolo), Andrei Draganescu (@andraganescu), Carolina Nymark (@poena), and Ramon Dodd (@ramonopoly) for their reviews and help in putting this proposal together.
#core, #editor, #gutenberg, #proposal

Proposal: Stop merging experimental APIs from Gutenberg to WordPress Core

This call for feedback will be open for the next four weeks until September 7th.

I propose a way of harmonizing the process of merging new APIs from the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party to the WordPress coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.. Right now, the two projects have very different policies, confusing contributors and sparking lively discussions on every major WordPress release. 

Today, experimental APIs are merged to Core and sometimes removed later

To date, 280 experimental APIs were merged from the Gutenberg plugin to WordPress Core. That’s problematic, and here’s why.

WordPress values backward compatibility. Upgrading to a new version should not break the plugins and themes, so WordPress public APIs these plugins and themes depend on are maintained across major versions. As the WordPress handbook states:

Historically, WordPress has been known for preserving backward compatibility across versions. 

The Gutenberg plugin values agility. It’s the safe space where new experiments are planted and grow into stable features without the same stability constraints. It is okay to ship a prototype, learn from it, and then start over again. New functions under active development often include the __experimental prefix in their name to indicate they may change at any point and shouldn’t be relied upon. Removing the obsolete code also makes the JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. bundle smaller and reduces the editor loading time. As the Gutenberg plugin handbook states:

Experimental and unstable APIs are temporary values exported from a module whose existence is either pending future revision or provides an immediate means to an end.

In the Gutenberg plugin, it’s fine to remove these experimental APIs. In WordPress, it’s not. Unfortunately, many have already been released with major WordPress versions.

Tomorrow, experimental APIs could be restricted to the Gutenberg plugin and never merged to Core

Let’s remove the experimental prefix before merging new APIs into WordPress Core.

This way:

  • Core can deliver the expected level of Backwards Compatibility
  • The Gutenberg plugin can retain the freedom to remove the experimental APIs as needed
  • The experimental APIs would get audits
  • It would make the release easier

Wouldn’t stabilizing every APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. before the release slow down new features?

The goal isn’t to stabilize. It’s to avoid adding public experimental APIs to WordPress core. Here’s two alternatives to stabilizing:

What if a stable feature depends on an experimental feature?

Then it isn’t actually stable. Let’s stabilize the dependencies first (or make them private).

What about the existing experimental APIs?

Most of those already merged to Core would get a stable alias. It would preserve BC and shouldn’t noticeably affect the bundle size. Some will need a different treatment; let’s discuss that case-by-case.

What if an existing experimental API already in Core needs to be removed?

Does it? If so, let’s consider that on a case-by-case basis. There are established Core practices like contacting plugin authors, writing make Core posts, preferring soft deprecations, and so on. I don’t expect to see many instances of this.

What if a future stable Gutenberg plugin API really needs to be removed after it’s released in Core?

Yes, it will happen. Let’s acknowledge and embrace it. Some good reasons were mentioned in the GitHub discussion, and the future will surprise us with many new ones. Again, let’s follow the established Core practices. For example, deprecated.php shows that removing a function body is sometimes okay as long as the name keeps working.

What are the downsides?

I can see three:

  • Some Gutenberg plugin features will get merged into the Core later that they currently would be. The total amount of the development work won’t change, but the merging timeline will. That could be a good thing. Using the Gutenberg plugin is the intended way of accessing the upcoming features early.
  • Refactoring Gutenberg plugin APIs will be difficult once they get shipped with Core. In reality, that’s already the case.
  • Risk: Surgically removing all the Gutenberg plugin work spanning multiple WordPress releases from pre-release merges may become too complex. It would halt the merges entirely. If this risk does materialize, the merge guidelines will need to be adjusted again.

If you see any other downsides, please speak out!

What alternatives have been considered?

  • Keep not acting on the problem.
  • Use the same Backwards Compatibility policy for both WordPress and the Gutenberg plugin – which would make both projects worse off.
  • Find a way to ship the experimental APIs with Core as “internal” and unavailable to plugin authors – which has been explored without a successful resolution.

Unfortunately, neither is viable, as explained in more detail in the GitHub discussion.

If this resonates with you, speak out before September 7th!

Policies don’t contribute to the Gutenberg plugin. People do. This proposal will only work if we, the contributors, believe it’s the right thing to do.

Please share your thoughts under this post or in the GitHub discussion – even if it’s just “I like it.” All opinions are welcome, especially if you are not convinced about this proposal.

This call for feedback will be open until September 7th.

Props to Birgit Pauli-Haack (@bph), Grzegorz Ziółkowski (@gziolo), and Hector Prieto (@priethor) for their help in putting this proposal together.

#editor #gutenberg #core #proposal

Proposal: Better REST API handling in JavaScript

This call for feedback will be open for the next two weeks until July 18th.

I propose extending the useEntityRecord hook to support editing and deleting WordPress data. It should make building features and plugins on top of WordPress REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. easier.

The hook is a part of @wordpress/core-data, a JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. package providing tools for interacting with the WordPress REST API. You may know coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.-data from Redux selectors, actions, and ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. like  getEntityRecord, saveEntityRecords, useSelect.

Today, useEntityRecord enables easy access to data

The useEntityRecord hook enables fetching data with just a single line of code:

import { useEntityRecord } from '@wordpress/core-data';
 
// Inside of a React Component:
function PageTitle() {
    const { record, hasResolved } = 
        useEntityRecord( 'postType', 'page', 15);
    return hasResolved ? record.title : 'Loading...';
}

It was introduced to the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ repository in PR #38782 and will land in WordPress core in 6.1, the next major releasemajor release A release, identified by the first two numbers (3.6), which is the focus of a full release cycle and feature development. WordPress uses decimaling count for major release versions, so 2.8, 2.9, 3.0, and 3.1 are sequential and comparable in scope..

For comparison, achieving the same result without useEntityRecords requires much more knowledge about the Gutenberg internals:

import { useSelect } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';

// Inside of a React Component:
function PageTitle() {
	const { page, hasResolved } = useSelect(
		( select ) => {
			const selectorArgs = ['postType', 'page', 15];
			return {
				page: select( coreDataStore )
					.getEntityRecord( ...selectorArgs ),
				hasResolved: select( coreDataStore )
					.hasFinishedResolution(
						'getEntityRecord',
						selectorArgs
					),
			};
		},
		[]
	);
	return hasResolved ? page.title : 'Loading...';
}

Tomorrow, useEntityRecord could ease editing data

In PR #39595, I proposed taking useEntityRecord one step further to make editing WordPress data equally easy:

const { record, edit, editedRecord, hasEdits, save } =
	useEntityRecord( 'postType', 'page', pageId );

// edit({ title: “My new title” });
// save();

// After React re-render:
// console.log( record.title );
// "My new title"

In comparison, this is how it’s done today:

const {
	editEntityRecord,
	saveEditedEntityRecord,
} = useDispatch( coreStore );

const { record, editedRecord, hasEdits, isSaving, saveError } =
	useSelect(
		( select ) => {
			const args = [ kind, type, id ];

			return {
				editedRecord: select( coreStore )
					.getEditedEntityRecord( ...args ),
				hasEdits: select( coreStore )
					.hasEditsForEntityRecord( ...args ),
				isSaving: select( coreStore )
					.isSavingEntityRecord( ...args ),
				saveError: select( coreStore )
					.getLastEntitySaveError( ...args ),
			};
		},
		[ kind, type, id ]
	);

// editEntityRecord(kind, type, id, { title: “My new title” });
// saveEditedEntityRecord(kind, type, id);

// After React re-render:
// console.log( record.title );
// "My new title"

I combed through the WP Directory and found existing plugins that could already benefit from this pattern.

If this resonates with you, speak out before July 18th!

Introducing new APIs means having to maintain them indefinitely. Therefore, I would like to confirm this proposal offers an attractive solution to a real problem. This post attempts to do just that, and I would love to hear from you! All opinions are welcome, especially if:

  • Your JavaScript code interacts with the WordPress REST API
  • You’re maintaining code that leans on wordpress/core-data
  • You’ve struggled to learn how to use it
  • This new APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. would be helpful for you
  • You’re not convinced there’s a need to introduce such an API

I’m also interested in all the code samples related to editing and saving entity records that you are willing to share. It would be a great way to validate and exercise the proposed API.

This call for feedback will be open for the next two weeks until Jul 18, 2022.

Props to Anne McCarthy (@annezazu) and Grzegorz Ziółkowski (@gziolo) for their help in putting this proposal together.

#editor, #gutenberg, #proposal

Proposal to Start a News blog on developer.WordPress.org

Staying on top of the new features coming to the WordPress open-source project is one of the main barriers expressed by developers.

The Make CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blogblog (versus network, site) has a heavy emphasis on meeting notes for the various core teams, rather than highlighting new features. This makes it difficult for developers who are not contributors or who just occasionally contribute to find the relevant information among the team-related posts. 

To achieve one of the big-picture goals for 2022 (“Create a developer-focused communications site“), this is a proposal for creating a Developer News blog. The content focuses on updates for developers, extenders creating plugins and themes, and those who work with WordPress at an agency or as freelancers. 

Preliminary Timeline

  • Proposal and request for comment period: February 25 – March 18, 2022
  • Coordinate with Design and MetaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. Teams for theme (the News theme would be spectacular) 
  • Brainstorm meeting with team representatives: End of March
  • Content creation and first post: early April 2022 
  • Start-up phase: Through mid-July
  • Review and expansion to regular topics for developers: Fall 2022

Problem to be Solved 

The current developer.wordpress.org holds a ton of comprehensive documentation with examples, tutorials, getting started guides, and more. That being said, there are various improvements that could be made to make the site much more impactful. Some of these areas for improvement are outlined below. 

What’s missing: 

  • There is no changelog to signal various changes including when pages are updated or when new APIs appear or existing ones are augmented with new filters, hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same., and configuration. 
  • There is no mechanism to subscribe to updates. A blog would provide this feature. 
  • Outside #core-editor meetings and GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. https://github.com/, there is no single place to keep up with  ongoing discussions. For example, to learn about the new styling engine, a developer needs to visit three sites: Discussion, Tracking Issues, and the first PR.

Start-Up Phase

As a first step, the Developer News can tackle the above pain points by:

  • Surfacing updates to documentation, 
  • Highlighting new tutorials, and, 
  • Providing a way for developers to subscribe to stay up to date 

The Developer News blog can also be added to the Planet WordPress feed, so post titles also appear in the WordPress News WidgetWidget A WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. in the WP Adminadmin (and super admin) Dashboard. 

This initiative requires cross-team collaboration among contributors from the Documentation, Core (core-css, core-js, core-editor etc.), Training, and Support teams. 

These teams could use an existing WP SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/. channel for synchronous meetings, such as #docs or #core. During the meeting, team reps and other contributors can make editorial suggestions for topics and links that could be included in the next edition of an update post.

An editorial calendar can be an early agenda item for the meetings. 

After the initial start-up phase, the blog would be extended to regular topical posts relevant to developers. 

Possible Ideas for Future Expansion

  • Summaries from GitHub Discussions 
  • Excerpts from meeting discussions for distribution to a wider audience of developers
  • A post consisting of a summary of multiple dev updates 
  • Useful questions/solutions found on StackOverflow/StackExchange 
  • Reviews of existing documentation to identify gaps 

A possible future expansion would include a regular revision process to update content with new information and changelog recording. 

I recommend that contributors to this initiative comply with the Make Core Post and Comment Guidelines. Should the editorial group decide to also include highlights of example plugins or themes, all products must adhere to the Community Team’s guidelines regarding GPLGPL GNU General Public License. Also see copyright license. compliance of the products, including premium products. 

As mentioned above, these are just some initial steps to get processes and contributors in place. Reader comments and discussion in the Slack channel will surface opportunities for further enhancements. 

What do you think? How could this proposal be improved?
Please share  your comments, your thoughts, and content ideas. If you’d like to contribute to the Developer News, mention this also in the comments. The comment period on this proposal will end on March 18, 2022. 

Props to Dion Hulse (@dd32), Destiny Fox Kanno (@piyopiyofox), Tara King (@sparklinerobots), Anne McCarthy (@annezazu), Tonya Mork (@hellofromtonya), Daisy Olsen (@daisyo), Dan Soschin (@dansoschin), and Anjana Vasan (@anjanavasan) for fruitful collaborating on this proposal. 
Props to Mary Baum (@marybaum) and Jean-Baptist Audras (@audrasjb) for final review

#core-dev-blog, #developer-news, #proposal

Proposal for a Performance team

Note: a follow up post was published with information about next steps for this proposal.

We (the undersigned) believe that WordPress needs an official Performance team responsible for coordinating efforts to increase the performance (speed) of WordPress.

This proposal outlines why we believe that this is necessary, how we envision such a team might function, and some potential initial areas of focus. It is authored by contributors from Yoast and Google.

What problems are we trying to solve?

Users expect and prefer fast experiences (consciously or otherwise). Research shows that fast websites can provide a better user experience, increase engagement, benefit SEO, increase conversion, and be more economically and ecologically friendly.

References:

The benefits of improving performance driving investment across the web [ref]. This further raises users’ expectations, and thus may comparatively ‘harm’ slow(er) things.

Compared to other platforms (e.g., Wix, Shopify, Squarespace), WordPress is falling behind. Other platforms are on average faster – and becoming increasingly faster – than WordPress websites (see The HTTP Archive’s Core Web Vitals report), and are actively investing in (and marketing) coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. performance-as-a-feature [1, 2].

We can see the impact of this investment in the widening gap between the proportion of WordPress sites which achieve ‘good’ Core Web Vitals scores, vs other platforms.

Performance graph for CMSs on desktop clients.
Performance graph for CMSs on mobile clients.

This gap continues to widen, despite the availability of many performance plugins and performance-focused themes. This suggests that there’s a discovery and/or education problem, or an updating/staleness problem – neither of which the pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party ecosystem solves for. 

In order to meet the increasing needs and expectations of site owners and end-users, WordPress needs to be actively investing in performance in WordPress Core and beyond (e.g., core code, themes & plugins requirements, setup and onboarding processes, adminadmin (and super admin)/editing experiences, education for content creators).

We believe that:

  • Performance is a fundamental part of user experience, and WordPress should aim to deliver a good user experience.
  • Achieving reasonable performance levels shouldn’t be plugin territory, but part of core (aka, “performance by default”), because;
    • All WordPress users (of all types) need a well lit path to good performance.
    • Average end-users can’t be expected to be performance experts.
    • Achieving high levels of performance requires technical considerations to be ‘built-in’ across the whole stack; and as this is often not the case with themes/plugins, performance solutions are limited to ‘brute-forcing’ performance solutions over non-performant behaviour (e.g., output buffering).
    • The plugin ecosystem doesn’t help users who don’t know that they need help, or who are poorly served by the plugin ecosystem.
  • Users determining which CMS to choose are / will be increasingly influenced by performance (and the associated UXUX User experience/SEO/conversion factors), and we’ll lose ground to faster platforms.
  • ‘Democratizing publishing’ requires that published content be discoverable; which will be less likely to occur via search engines (which influence or account for the majority of new content discovery) for slow(er) sites.

Web Vitals metrics provide a standardized and accepted mechanism for evaluating performance.

Plugin territory

Whilst we argue that some (perhaps most) performance considerations should be part of core, there are definitely areas that should remain firmly in ‘plugin territory’. For example, the following areas should be handled by plugins:

  • Integrations with specific CDNs
  • Template transformation processes (e.g., AMP)
  • Any non-standardized performance technology
  • Any experimental standards (e.g., browser APIs / capabilities with limited adoption)

These distinctions will need exploring and lines will need drawing (and maintaining) as part of the team’s activity.

Why a team?

Performance is already a focus in Trac and a label in the Gutenberg GitHub repository; but these alone don’t attract enough attention to the issues, nor unify efforts and priorities. Experienced and active contributors are not necessarily performance experts.

A team gives more visibility to the effort: contributors that are not interested in working on Core as a whole can be attracted by working on performance specifically. It also opens up contributing to new types of contributors, like performance or data analysts.

A performance team could also attract contributions from different groups; browsers, hosting, SEO companies, etc.

Resources and efforts

In practical terms, the creation of a performance team requires the following:

  • A performance tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) on Make websites
  • A performance channel in SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/.
  • A meeting every two weeks; time to be determined
  • Two team representatives for administrative purposes: they will be responsible for: 
    • Giving a quarterly report to the project leadership
    • Assigning roles in the website
  • A team lead/product owner. They will be responsible to create a mission statement for the team, highlight the areas to tackle, outline the scope and the roadmap for the improvements that need to be made.
  • Representation in (and influence on) other Make verticals and processes (e.g., themes, plugins, etc)

Next steps

Next steps should be discussed and determined as part of the process of exploring and responding to this proposal.

In the case that there are no objections, the next major steps are likely to be:

  • Set up Slack channel and meeting schedule, and make.wordpress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ infrastructure.
  • Benchmark performance and define ongoing/future measurement & success criteria
  • Identify priority projects for CWV improvements with high-level timelines
  • Assign responsibilities for the projects identified

Props

Thanks to the following for this involvement in outlining this proposal.

@francina, @adamsilverstein, @tweetythierry, @joostdevalk, @jonoaldersonwp, @flixos90, @aristath (in no particular order)

#performance, #proposal, #team