The WordPress block editor is based around the idea that you can combine independent blocks together to write your post or build your page. Blocks can also use and interact with each other. This makes it very modular and flexible.
But the Block Editor does not embrace modularity for its behavior and output only, it is also built from the ground up as several reusable and independent modules or packages, that, combined together lead to the application and interface we all now. These modules are known as WordPress packages and are published and updated regularly on the npm package repository.
Right now these packages are built in the Block Editor Repository and used to power the block editor. Ultimately, these packages will be used to power any page in the WordPress Admin.
Modular architecture
Using a modular architecture has several benefits for all the actors involved:
Each package is an independent unit and has a well defined public API that is used to interact with other packages and third-party code. This makes it easier for Core Contributors to reason about the codebase. They can focus on a single package at a time, understand it and make updates while knowing exactly how these changes could impact all the other parts relying on the given package.
A module approach is also beneficial to the end-user. It allows to selectively load scripts on different WordPress Admin pages while keeping the bundle size contained. For instance, if we use the components package to power our plugin’s settings page, there’s no need to load the block-editor package on that page.
This architecture also allows third-party developers to reuse these packages inside and outside the WordPress context by using these packages as npm or WordPress script dependencies.
Types of packages
Almost everything in the Gutenberg repository is built into a package. We can split the packages into two different types:
Production packages
These are the packages that ship in WordPress itself as JavaScript scripts. These constitute the actual production code that runs on your browsers. As an example, there’s a components package serving as a reusable set of React components used to prototype and build interfaces quickly. There’s also an api-fetch package that can be used to call WordPress Rest APIs.
Third-party developers can use these production packages in two different ways:
If you’re building a JavaScript application, website, page that runs outside of the context of WordPress, you can consume these packages like any other JavaScript package in the npm registry.
npm install @wordpress/components
import { Button } from '@wordpress/components';
function MyApp() {
return (
<Button>Nice looking button</Button>
);
}
If you’re building a plugin that runs on WordPress, you’d probably prefer consuming the package that ships with WordPress itself. This allows multiple plugins to reuse the same packages and avoid code duplication. In WordPress, these packages are available as WordPress scripts with a handle following this format wp-package-name (e.g. wp-components). Once you add the script to your own WordPress plugin scripts dependencies, the package will be available on the wp global variable.
// myplugin.php
// Exemple of script registration dependending on the "components" and "element packages.
wp_register_script( 'myscript', 'pathtomyscript.js', array ('wp-components', "wp-element" ) );
// Using the package in your scripts
const { Button } = wp.components;
function MyApp() {
return (
<Button>Nice looking button</Button>
);
}
Some production packages provide stylesheets to function properly.
If you’re using the package as an npm dependency, the stylesheets will be available on the build-style folder of the package. Make sure to load this style file on your application.
If you’re working in the context of WordPress, you’ll have to enqueue these stylesheets or add them to your stylesheets dependencies. The stylesheet handles are the same as the script handles.
In the context of existing WordPress pages, if you omit to define the scripts or styles dependencies properly, your plugin might still work properly if these scripts and styles are already loaded there by WordPress or by other plugins, but it’s highly recommended to define all your dependencies exhaustively if you want to avoid potential breakage in future versions.
Packages with data stores
Some WordPress production packages define data stores to handle their state. These stores can also be used by third-party plugins and themes to retrieve data and to manipulate it (Refer to my previous post on the subject for more details here). The name of these data stores is also normalized following this format core/package-name (E.g. the @wordpress/block-editor package defines and uses the core/block-editor package).
If you’re using one of these stores to access and manipulate WordPress data in your plugins, don’t forget to add the corresponding WordPress script to your own script dependencies for your plugin to work properly. (For instance, if you’re retrieving data from the core/block-editor store, you should add the wp-block-editor package to your script dependencies like shown above).
Development packages
These are packages used in development mode to help developers with daily tasks to develop, build and ship JavaScript applications, WordPress plugins and themes. They include tools for linting your codebase, building it, testing it…
Going further
The WordPress packages are a gold mine and a huge time saver when it comes to building JavaScript application whether as a WordPress plugin or an independent application.
In the next weeks, I’ll try to write a series of posts to explain some of these packages in detail, how to reuse them in your own code. In the meantime, I encourage you to explore the documentation of the different packages on the block editor handbook.
With Gutenberg, we made the choice to use JavaScript heavily in order build the UI of the editor, not because we’re nerdy hipsters but essentially because it is the perfect fit to address the UI and UX challenges of a heavily interactive interface in the browser.
As a consequence, we’ll start to see a shift in the WordPress community. Plugin developers are required to use JavaScript more in order to extend the editor. Most blocks need to be developed using this technology. The modules Gutenberg provides (Components, data module, i18n, apiFetch…) will also encourage developers to extend other parts of WP-Admin in JavaScript. Instead of writing HTML/CSS screens from scratch and rendering them from the server, developers are able to bootstrap and prototype fully accessible new screens in WP-Admin by composing these components in a small number lines of code.
Learning process
But when we talk about JavaScript in general, we can think of two different approaches:
Using untranspiled ES5 code.
Leveraging build tools like babel, webpack… and write ESNext JavaScript code (ES2015 and more).
Most plugin authors are already writing ES5 code in their PHP rendered UIs or in their themes and the Gutenberg APIs can continue be used this way. But our role as Core Contributors should also be to educate people to get on the ESNext train as it can be a huge improvement in terms of productivity and development experience.
That said, learning ESNext and all the tools involved in the process can be a bit overwhelming if you’re coming from a PHP background without any prior heavy JavaScript experience. To help with the transition, the WordPress community started working and providing tools (Like Create Guten Block).
Using these tools can feel like “magic” though. It works but as a developer, you don’t really know what’s happening behind the scenes. Debugging code can be a challenge if you don’t understand how everything fits together.
For this particular reason, I created the WordPress JavaScript Plugin Starter. Unlike other starters thought, it’s written as a tutorial. Each commit of the repository is a step further in the setup and the README goes through each one of these steps and explains it.
Hopefully, At the end of the day, you’d be able to use the starter as a way to start a WordPress plugin but also master how this plugin works and how all the tools fit together to ship a production ready JavaScript plugins.
Manipulating Client Data in highly interactive screens in WordPress (essentially the editor page in WordPress pre 5.0.0) is not the easiest task to do for plugin authors. As much as WordPress provides a large number of functions to access and manipulate data server side, it fails at providing a consistent way to access and manipulate data on the client.
And by client side data, I refer to things like:
What’s the current post content in the editor? How can I update it programmatically?
What’s the currently selected tags/categories?
Is a given metabox visible or not?
How can I be notified if an image block is inserted into the editor of if the user switches the post status?
Client-data is also about accessing the WordPress REST API Data client-side:
How do I retrieve the latest posts?
How do I retrieve the current user’s object?
How can I create a new Category?
And it can also encompass plugins data. For example:
How do I store/update and access my own plugins client-side data?
How do I access and update the content of the Yoast metabox?
How do I retrieve the content of ACF metaboxes in a custom ACF plugin?
Often, to address these use-cases, we had to manipulate the DOM directly: Retrieve input’s values directly from the DOM or subscribe to DOM events to ensure we’re notified properly. This often leads to hacky code and code that breaks on WordPress/plugin updates because DOM access is not an official extensibility API.
Gutenberg JavaScript-heavy World
With Gutenberg’s release coming and as we add more and more JavaScript-powered UI to WordPress pages, the need for a consistent solution to manage client-side data is urgent, we can’t rely on DOM access anymore. To address this, Gutenberg introduces the Data Module.
Retrieving Data
One of the first use-cases of the Data module is to retrieve data defined by WordPress. To do so, you need to specify the namespace of the data to call a selector on this namespace.
Here’s how we retrieve the content of the post being edited in a Gutenberg Page.
var content = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'content' );
Notice that the data module API is available in the wp.data global variable. The namespace to access the editor’s data is core/editor. And in each namespace, you can use a list of selectors.
A selector is a simple JavaScript function used to retrieve client-side data. In the example above, the selector being called is getEditedPostAttribute. This selector accepts an argument corresponding to the post attribute to retrieve. If we need to retrieve the title of the post instead of its content, we can do:
var title = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'title' );
Protip: The list of the available selectors/namespaces is not documented properly on WordPress/Gutenberg yet. To see the full list of the core/editor‘s selectors, you can check the selectors file here.
You can also type wp.data.select( 'core/editor' ) in your browser’s console in any Gutenberg page to inspect the full list of the selectors available in this namespace.
Updating Data
So, selectors allow us to retrieve data and similarly, each namespace can defined actions to manipulate data (create/update/remove). For example, to update the title of the post being edited in Gutenberg, you can do:
wp.data.dispatch( 'core/editor' ).editPost( { title: 'My New Title' } );
An action is a function called to update the client-data defined in a given namespace.
Protip: To see the full list of the actions defined by the core/editor namespace, you can check the actions file here. You can also type wp.data.dispatch( 'core/editor' ) in your browser’s console in any Gutenberg page to inspect the full list of the actions available in this namespace.
Register a custom “namespace”
Plugins can also manage their client state using the data module. To achieve this, they need to register their selectors/actions in addition to a reducer to hold and update the state.
A reducer is a function describing the shape of the initial state and how the state value evolves in response to dispatched actions.
Protip: The Data module is built on-top of the redux library. Learning redux is not required to use it but taking a look at the Redux Docs and its glossary should help you master the data module.
As an example, Let’s register a custom store to keep track of a list of todo items:
// This is the reducer
function reducer( state = [], action ) {
if ( action.type === 'ADD_TODO' ) {
return state.concat( [ action.todo ] );
}
return state;
}
// These are some selectors
function getTodos( state ) {
return state;
}
function countTodos( state ) {
return state.length;
}
// These are the actions
function addTodo( text, done = false ) {
return {
type: 'ADD_TODO',
todo: { text: text, done: done };
};
}
// Now let's register our custom namespace
var myNamespace = 'my-todos-plugin';
wp.data.registerStore( myNamespace, {
reducer: reducer,
selectors: { getTodos: getTodos, countTodos: countTodos },
actions: { addTodo: addTodo }
} );
Now that the custom namespace is registered, we can consume this in our code, the same way we did for the core/editor’s store.
// Add a new todo item
wp.data.dispatch( 'my-todos-plugin' ).addTodo( 'Finish writing a blog post about the data module', false );
// Retrieve the list of todos
var countTodos = wp.data.select( 'my-todos-plugin' ).countTodos();
React to changes in the state
Another important use-case for WordPress Plugins often is to react to changes happening in Core Data or other plugins. To address this, the Data Module provides a subscribe function. This function allows registering listeners that get called each time the state is changed.
In the following example, we trigger some random behavior each time a new block is added to the editor:
var currentCount = wp.data.select( 'core/editor' ).getBlockCount();
wp.data.subscribe( function() {
var newCount = wp.data.select( 'core/editor' ).getBlockCount();
var hasNewBlocks = newCount > currentCount;
currentCount = newCount;
if ( hasNewBlocks ) {
// A new block has been added, do something
console.log( 'The new block count is :' + newCount );
}
} );
Declarative data needs
In addition to a new way to handle data client-side, as WordPress and plugins move towards more JavaScript UIs, the use of React and its wordpress abstraction wp.element is growing.
The WordPress element module allow you to describe UI using functions (or components) taking props and returning an HTML representation of the component.
A simple component displaying an h1 can be written like so:
// You can use JSX instead of wp.element.createElement
var el = wp.element.createElement;
function Title( props ) {
return el( 'h1', {}, props.title );
}
Very often, these UI components need data to work properly. In the example above, the Title component expects a title prop to display its content in an h1.
Let’s say we’d like to display title component using the title of the post being edited in Gutenberg, we can use the select function explained previously and do something like that:
But this approach has some downsides. The value of the title prop can change over time and we’d like to refresh our component once that happens. This means we need to use wp.data.subscribe and rerender each time the title changes.
Fortunately, to avoid having to write this logic for ourselves, The data module provides what in the React community is referred to as a Higher-order component. A Higher-order component is a function that wraps another component and feeds it with props.
Here’s how you provide the title as a prop using the data module:
Now when we render the EditorPostTitle component, it will be automatically refreshed each time the title value changes.
el( EditorPostTitle );
Similarly to how the withSelect Higher-order component provides props to components using selectors, the data module also provides a withDispatch Higher-order component to feed components with actions.
Let’s write an input that can be used to change the value of the Gutenberg’s post title.
Notice in this example how we’re composing both withSelect to retrieve the current title and withDispatch to provide a onChangeTitle callback the input Component can call to perform the updates.
Protip: Notice the compose function being used in the example, it’s an utility function that allow combining several Higher-order components together.
Until now, we were mostly dealing with synchronous selectors and actions but WordPress Data offers a way to handle asynchronous data as well.
To do so, we can attach a side-effect to each selector: A function that gets executed the first time a selector is called with a given set of arguments. This function can be responsible of performing an async API request and updating the state once the request succeeds. These side-effect functions are called resolvers.
For instance, we might be interested to fetch posts list to display them in a PostList component.
var el = wp.element.createElement;
// This a UI component showing a list of post titles given a posts prop.
function PostList( props ) {
return props.posts.map( function( post ) {
return el( 'div', { key: post.id }, post.title.rendered );
} );
}
var RecentPostList = wp.data.withSelect( function( select ) {
posts: select( 'core' ).getEntityRecords( 'postType', 'post' )
} );
Notice that in this example, the APIs being used are the same we were using before, but behind the scenes, a REST API is being executed the first time the getEntityRecords selector is called, to fetch the post list.
Here’s the exact flow:
The first time the getEntityRecords selector is called, the post list is empty. So the PostList component is rendered with an empty list of posts.
But behind the scenes the core data module also calls the resolver called getEntityRecords to perform the API Request for you.
When the API Request resolves, the state is updated with the received posts. This will automatically retrigger a rerender, thanks to the way withSelect works.
The PostList gets rerendered with the update list of posts.
Protip: If you’re interested in implementing this kind of side effects in your own plugins, make sure to take a look at the resolvers in the Data module docs.
WordPress Headless / Agnostic?
The Data Module is a generic JavaScript package to handle data, if you want to use in a WordPress client, or if you want to use any applications not related with WordPress, that’s also possible. Instead of using the wp.data global, you can just fetch the package from npm:
npm install @wordpress/data --save
Going further
The Data Module is still being enhanced, if you’re Interested in learning more about the Data Module or any other modules, make sure to join the #core-js channel of the WordPress Core slack and the weekly meetings happening each Tuesday at 13:00 UTC.
J’ai eu l’honneur de donner un nouveau talk sur Gutenberg au WP Tech Lyon. De nombreux talks ont été donnés sur Gutenberg, le pourquoi du comment, ce que ça change pour les utilisateurs mais peu de talks ont abordé les dessous de Gutenberg, son architecture et ce que ça apporte au développeur de thèmes de plugins et aux développeurs JavaScript en général.
Au cours de ce talk, nous avons suivi les différentes étapes pour le développement d’un plugin Gutenberg WordPress en utilisant les différents modules mis à notre disposition.
Le résultat est un plugin plutôt utile qui permet d’insérer des photos Unsplash.com directement depuis la sidebar de Gutenberg.
Drop It Plugin
Télécharger ce plugin depuis le repository WordPress.org et survoler son code source sur GitHub.
Un grand merci aux organisateurs et bénévoles, c’était vraiment un évènement très réussi. 👏🏻
J'ai aussi eu la chance d'animer un atelier sur l'extensibilité de Gutenberg dont voici les slides et le repository GitHub qui contient les exemples exposés.
What are the next battles we should take to improve WordPress technology and workflow? What should we do next?
I've been part of the WordPress community for more than a year now, which is really short in WordPress time, but I truly love this community and I hope to contribute for several more years. This year has been amazing in terms of Development and Workflow evolutions in the WordPress community, partly pushed by Gutenberg. Let's continue modernizing WordPress!
In this very subjective post, I'm going to list some of the battles worth considering for the future of WordPress. No battle is easy, but remember:
we're on a marathon not a sprint and no matter how far away the goal is, the only way to get there is by putting one foot in front of another every day.
Git and GitHub
Trac served WordPress very well, it centralizes all discussions and patches in one consistent place, but is it the right tool for a large Open Source project in 2018? Is it time to move to something else?
A new generation of developers works exclusively on Git and GitHub. Casual contributors won't invest time to learn a tool not used in any other place (I'm probably exaggerating a bit here) just to submit a small PR/patch. And often these casual developers evolve to become regular ones.
With Trac, the barrier for the first contribution is huge and projects like the REST API already showed that merging these feature projects into Core (which also means moving from GitHub based workflow into Trac) leads to a big decrease in terms of contributors and contributions.
Yes, this is not easy as Trac holds a big history of conversations and patches, we probably have several processes and scripts based on Trac, but it's definitely worth a battle, WordPress will benefit from the same dynamic/contributions around Gutenberg for all its components.
Deprecation strategy
This is going to be controversial. When it comes to backward compatibility, WordPress is unique. It's the only software where you can skip 9 major versions, update to the last version and your website still works (mostly). While this is huge in term of stability and confidence in the future, this philosophy of "always maintaining backward compatibility" has limits.
First, every version of WordPress comes with some "small" backward compatibility breakage but it's really hard to know where to draw the line. It's not clear which things we can never break in releases and what is an "acceptable" backward compatibility breakage.
Also, this obsession to always maintain backward compatibility is not serving the code base of WordPress. Each new version adds new APIs, duplicating and enhancing some existing APIs but not removing any old API (with some "acceptable" exceptions). This affects badly the performance and the size of WordPress. And gives this feeling of heaviness WordPress suffers from.
Can't we have the best of both worlds? A way to upgrade from old versions safely and a way for developers to deprecate and remove features, APIs from WordPress?
I'm certainly not the first one to propose something like this but I'm curious to know why can't we achieve this "coherent" deprecation strategy:
Plugins should explicitly declare WordPress versions support. There's already the "tested up until" field for Plugins. It should be blocking which means if you have a plugin that does not have a compatible version with the latest WordPress release, you can't upgrade unless you disable this plugin.
Upgrading to the latest version also updates the plugin that needs to be updated to work with this last version.
Transition periods where the old API and the new ones are available at the same time.
Tools and APIs to allow developers to declare "deprecated APIs" to warn plugin authors about the need to update their plugins.
Can we also consider "SemVer" for WordPress and Plugins?
Granted that this will be a fundamental change in WordPress's philosophy, but I think a change like that is necessary for the future of WordPress.
PHP version of course
I believe the work to achieve this has already started but yes we need to update the minimal PHP version required to run WordPress. This will not only improve the developer experience in WordPress Core but improve the security and performance of all WordPress websites.
I'm not heavily aware of the current efforts (as I'm not very engaged their as well). I know a field to require a minimal PHP version has been added to plugins, but we can do the same for WordPress releases. We can disable upgrades if we detect an incompatible PHP version.
I'm optimistic about this specific point, I believe we'll achieve this soon enough. But we should also work on the deprecating and upgrade strategy to allow us to continue doing this (updating the minimal version) in the future.
Stop arguing about Code Style and go standard
Developers in general (and WordPress ones confirming the rule) like to argue about code style and personal preferences. WordPress cares a lot about tabs and spaces around parenthesis and semi-colons… Why? Can't we stop caring and arguing about this, can we just follow a standard and stop talking about this? Let's focus on the code itself, let's add `prettier` to auto-format our code. We'd be consistent across our code and consistent with the outside community.
Languages like Rust, or Go successfully unified the code style using built-in tools and prettier is trying to achieve the same thing for JavaScript and PHP. Hundreds of open source projects are already using it.
WordPress code is not special.
Ifprettier is producing readable and consistent code for millions of developers, it can do so for WordPress developers as well.
Yes, this means huge commits to apply this the first time which may affect the history, but we already did this before using phpcs. Worth a battle!
GraphQL, why not?
Among developers, WordPress is often considered as "oldish technology". What if we change that? What if WordPress becomes this hype technology everyone talks about? For this to happen, the WordPress codebase need to be modernized. In addition to the PHP upgrade, the gradual switch to an SPA, WordPress can improve its "headless" capabilities by adopting `GraphQL`.
WordPress has been slow to adopt the REST API and it's not really a success as its usage has not seen this big increase we hoped for when merging into Core. REST APIs based applications can suffer from performance issues, especially if you want to query a lot of "related" data. How can we fix those?
In the last years, the web saw the rise of GraphQL. A Graph-based query language to provide data through an HTTP server. There are several advantages of this approach and developers in the WordPress community understood this. Plugins like WPGraphQL already do a great work exposing WordPress data though GraphQL with the extensibility expected from any WordPress feature. Can't we merge this (or an alternative) into Core to make it available to everyone?
As we move towards client-side UIs in WP-Admin aswell, this will help us a lot bringing consistency, performance and a good DevX (Declarative components) to our code-base.
Development Workflow
Another controversial point. WordPress has a relatively small group of Core
commiters allowed to commit patches proposed by anyone. This gives a huge responsibility to this
commiters when reviewing patches. This is good, it ensures that only high-quality (hopefully :P) patches get merged. But this has a perverse side-effect: In order to merge your patch, it has to be perfect which means often months of work for small features or bug fixes. I love iterations, I believe we can achieve way more by being a bit more flexible.
Let's merge unpolished features hidden behind feature flags.
Let's be less perfectionist. Better is the enemy of good.
Let's merge unpolished smaller patches. Reviewing several small patches is way more efficient and faster than reviewing one huge patch.
I admit this philosophy can create some unpolished code from time to time but I do believe we have the same problem with the current stricter approach without the benefits of faster iterations.
Documentation
WordPress has a lot of documentation but How hard it is to find what you're looking for? The fact that this documentation is often built in silos (featured plugins or separate teams) and then merged into WordPress.org leads to this situation. If you navigate through the documentation, there are at least three different "styles" of documentation pages you can go through.
I know the documentation team is spending a lot of time trying to improve the experience but often, it's hard to step back and think about the whole picture. I believe the only way to fix the documentation is to rethink it entirely from scratch. Some ideas include:
There are several types of documentation but all of them should merge into a unique experience:
Generated documentation (PHPDoc, JSDoc)
Developer documentation (often written in markdown)
End User documentation
Should we use WordPress to document WordPress? I don't think so, can't we build a WP documentation tool with the following features:
Support markdown.
Documentation as
code (live with the code).
Support i18n.
Coherent
themable stylesheets.
Usable separately by plugins and featured-plugins (which makes merging into Core consistent).
NPM Like plugins/themes registry (CLI based)
Plugins and Themes proposals, reviewals and updates are handled using a centralized SVN repository and a lot of processes (manual or semi-automated).
Themes submissions can take months, plugin submissions weeks. I believe this aspect of the WordPress community can be made more efficient. If we have to rethink the way the repository work today, how can we make it better. What can we automate? What should stay manual? Is the SVN repository a good solution to host plugins and themes in 2017?
Nowadays, most plugins and themes have separate Git repositories and use the SVN repository only to update and tag new versions, this makes the SVN repository useless. What if we build an NPM-like CLI with commands like.
wpr check To check the validity of the theme/plugin (code styles, tide check…)
wpr login To login (required to submit plugin/themes)
wpr publish To submit your plugin/theme to the repository
…
I would love to use such a tool ❤️
Conclusion
This is not an exhaustive list and it's very subjective and there are probably some existing projects addressing some of these issues. I'm just trying to think about the whole picture. And you, what battle do you think we should take?
A special thanks to all WordPress contributors (Documentation, A11y, Plugins, Themes, i18n, Development…) I'm very grateful to be part of this community, I've learned so much during this year among you all.
Developers and web agencies make extensive use of Custom Fields to add structured data to their Custom Post Types (and regular post types as well).
By leveraging the Meta Box API, plugins like ACF, CMB or Pods Framework address this concern. They all work similarly: you define fieldsets, a list of fields with different types and configuration where fields can be text, images, galleries, HTML editors, etc. Once you open the editor's page for the assigned post type, it's initialized with a list of Meta Boxes allowing you to fill the content of these fieldsets.
Gutenberg, the new WordPress Editor, aims to change the way we create content in WordPress. And without a surprise, this could have some impacts on these plugins. Legitimately, developers and users shared their concerns about the way this would impact their existing websites.
How does Gutenberg address this? Will these
MetaBoxes work in Gutenberg?
Short answer: mostly yes!
Long answer: due to the fact that the Meta Box API has no restrictions, plugin authors started using this API in all sort of ways, using selectors to reach DOM nodes displayed in the editor page, relying on DOM events not officially stated as official extensibility APIs etc., which means any change made to the editor's page can break existing Meta Boxes.
So the idea here is to try to limit the breakage as much as we can. Globally, the plugins listed above work in Gutenberg but some of their field types may break, in particular, the field types heavily relying on JavaScript DOM events and/or the TinyMCE API. If you experience a breakage for a specific field type, please open an issue.
Plugin authors might not have the time to update their plugins if there are incompatibilities, so Meta Boxes can also opt out of Gutenberg leading WordPress to fall back to the classic editor.
If you're a plugin author working with Meta Boxes I invite you to take a look at the handbook page describing how to test, convert and maintain these.
Aren't those Custom Fields Meta Boxes just blocks anyway?
The main goal of Gutenberg is not to replace the editor. This was commonly misunderstood, and thus it was hard to see why we'd want to emphasize blocks instead of just relying on existing APIs. But the real goal of Gutenberg is way bigger, it's trying to change the way we create content in WordPress in general around this unique concept of Block. The final user does not have to learn about all these concepts: Shortcodes, Widgets, Menus, TinyMCE, Meta Boxes to understand how to create and edit content in WordPress. It might seem natural to someone already familiar with WordPress but newcomers are struggling to juggle those and often prefer simpler alternatives offered by Wix, Squarespace, and others. (If not convinced, I encourage you to see this talk)
So how can these custom fields relate to blocks? If you think about it, a custom field is nothing more than a block saving its content
to post_meta andthat's already possible in Gutenberg.
And with the new Gutenberg Template Feature, you can provide a Post Type with a list of blocks that will be automatically added when the user creates a new post. Templates can also be "locked" which means the user can't add/remove new blocks or move existing blocks.
With the combination of the blocks saving to post meta and block templates we can pretty easily recreate what the custom fields plugins are offering: a way to structure the post's data.
Demonstration
To demonstrate this, I created a plugin called Gutenberg Custom Fields which offers the exact same experience the plugins listed above provide (an admin page to create and assign fields to a post type) using Gutenberg Native APIs.
Demo of Gutenberg Custom Fields
In fact, I think most of these plugins will certainly upgrade to these new APIs to provide a smooth upgrade path for their existing users.
If there’s one and only one feature that made WordPress gain 30% of the web’s market share, this feature would be Extensibility. What is WordPress without Yoast? What is WordPress without ACF? Without JetPack? WooCommerce? Without Akismet? Without Contact Form 7? What is WordPress without Hello Dolly? It’s nothing but another niche CMS with way less than its current market share.
So yes, Extensibility is key, and we can’t build the next generation of the WordPress Editor without making it extensible. What does “making it extensible” mean? Does this mean providing hooks and filters in JavaScript the same way we do in PHP? Does this mean allowing plugins to extend and tweak any UI component used by Gutenberg? Does this mean adding filters to the REST API? Does this mean Giving access to an Editor object to manipulate the editor’s content?
There’s no clear answer to all these questions. Extensibility is a very difficult problem and unless you build it with real use-cases in mind, you’re more likely to get it wrong. (and being stuck with it for a long time).
So let’s take a look a closer look at Extensibility in Gutenberg and what we can achieve as a third party plugin right now.
Creating blocks
As you may have heard, Gutenberg is about blocks (or content blocks) you combine to compose content. A block that can represent any visual element: A heading, a paragraph, an image, an embed, a table, a list, a form, a dynamic list of posts, …
You can think of blocks as shortcodes v2 with a better UI to add and modify them. Blocks can be static (just rendering some static HTML) or dynamic (changing over time and rendered server side).
If the editor is made up of blocks, the most natural way to extend it is by creating blocks.
1- Create a static block
So our first example will be to add a new static block we’ll call it “Alert” displaying an alert message, The alert can have three states (warning, error or success) and has a message.
This block could look like this (minus the control to switch the type, just to make it simpler):
// myblock.js
var el = wp.element.createElement,
registerBlockType = wp.blocks.registerBlockType;
registerBlockType( 'riad/alert', {
title: 'Alert Block',
icon: 'warning',
category: 'common',
attributes: {
type: {
type: 'string',
default: 'danger',
},
message: {
type: 'string',
source: 'html',
selector: 'div',
},
},
edit: function( props ) {
var className = props.className;
var type = props.attributes.type;
var message = props.attributes.message;
function updateMessage( event ) {
props.setAttributes( { message: event.target.value } );
}
return el(
'p',
{ className: className + ' alert-' + type },
el(
'textarea',
{ value: message, onChange: updateMessage }
)
);
},
save: function( props ) {
var type = props.attributes.type;
var message = props.attributes.message;
return el(
'p',
{ className: 'alert-' + type },
message
);
},
} );
A javascript file to register the block providing some general information (an icon, a category, and a title),
an edit function representing the visual state of the block in the editor and a save function representing the HTML output by this block,
A stylesheet adding some default styles to this block, extendable by themes,
And just a bunch of classic plugin hooks to tie everything together.
I won’t go too deep into the details here, if this is the way you want to extend Gutenberg, I encourage you to take a look at the Gutenberg Docs as this is heavily addressed.
2- Create a dynamic block
The second kind of blocks you can add to Gutenberg is the dynamic blocks. Let’s say we want to highlight the last published post in several other pages/posts. To do so we’ll create a dynamic block showing the title and a link to the latest post.
The edit function still shows a representation of the block in the editor’s context (this could be very different from the rendered version, it’s up to the block’s author)
The save function just
returns null because the rendering is performed server-side.
The server-side rendering is a function taking the block attributes as an argument and returning the markup (quite similar to shortcodes)
3- Saving to Post Meta
“Ok! now I get it, creating blocks is cool, it replaces static and dynamic shortcodes, but what about
metaboxes”
Metaboxes are used for everything in the current WordPress’s editor. One of these use-cases (the most frequent one) is adding a custom post meta.
Blocks address this use case quite nicely by allowing plugin authors to declare meta attributes, block attributes retrieved and saved to a post meta:
Done! we have a block saving a book title to a custom post meta.
Removing Blocks
Adding blocks is easy enough, but one of the concerns we hear a lot from agencies about is that Gutenberg gives a lot of power to their clients and they won’t be able to control what markup their users will produce using Gutenberg.
I do think this concern is irrelevant. Gutenberg offers exactly that: a way to have a controlled set of blocks. We can’t mess up with the post content as easily as in the current editor.
1- Black List
Either way, if you think a block is irrelevant for you or for a specific block type, just unregister it. For example, if I don’t like the verse block because I’m not a poet, I can just remove it like so:
Now that you got the principal, let’s do bigger modifications. What if we want to add a “caption” to the “code” block. To achieve this, we can “decorate”
the edit ,save and attributes like so:
With this technique, you can imagine enhancing any existing Block easily.
3- Transforming blocks
Gutenberg has a built-in transformations API allowing third-party plugins to create blocks and define how these blocks could be transformed to (or from) any other block including core blocks.
As an example, let’s add a transformation to the “alert” block we created above to allow turning it into a regular paragraph block
The transformations API is not documented yet because it’s still subject to change but it’s a powerful API, it allows way more than this. Some of the use-cases covered by this API are:
Paste transformations: Transforming pasted content into a specific block depending on the pasted content
Patterns transformations: Allow shortcuts: For example, typing `# ` in an empty paragraph creates a heading block, this behavior can be extended to any other prefix and block.
Drag and Drop transformations: Drag and dropping a PDF file into the editor creates a custom PDF block
Styling
1- Styling blocks
One of the most frequent questions we’re being asked is how Gutenberg affects existing themes and how can theme authors enhance the Gutenberg Experience.
Blocks come with unopinionated styles built-in. This makes basically any WordPress theme out there compatible with Gutenberg without any change.
However, to give them more personality themes could easily tweak the styling of any blocks and Gutenberg makes this easy by having a well-defined output markup for each block and a generated class name for most blocks.
Let’s say I want to give the
pullquote block a specific design in my theme, It’s just a matter of styling the `wp-block-pullquote` className
But what If I want to mimic a frontend styles and make the editor show blocks exactly how my theme would do it? To achieve this, just isolate the content’s specific styles in a stylesheet blocks.css loaded by both the frontend’s pages and the editor and load this stylesheet in the Gutenberg’s editor like so:
Themes can also extend Gutenberg using the “theme support” API. For now, two options are available: provide a color palette and enable wide alignments.
Several block types make use of “colors” and to ensure a
seemless experience across blocks, define a color palette like so:
When extending Gutenberg, the first question you need to ask yourself is: Could this be done within a block? In most cases, the answer to this question is YES. But this doesn’t mean Gutenberg won’t allow developers to extend other UI elements.
Let’s take a look at the different extension APIs being considered in Gutenberg.
1- Extending blocks
As I showed you earlier, it’s possible to modify existing blocks by unregistering and registering them with a modified version. In the future, registering core blocks by third-party plugins may be prohibited and a simpler API to extend blocks will be provided.
2- Slots
Internally, Gutenberg makes an extensive use of “Slots“. Slots are pluggable UI areas. In the future, Gutenberg will more likely expose those slots to third-party plugins to allow extending areas like the Sidebar and the header allowing use-cases like:
Adding a panel to the post settings sidebar.
Adding a button to the editor’s header.
Adding an item to the editor’s mode switcher
dropdown.
…
3- Decorators
While slots are great to enable adding items to the UI, they don’t allow to modify existing UI components. Gutenberg is built using reusable components and one way to extend the behavior of several UI elements of Gutenberg could be to modify these usable elements. Decorators are a generic pattern explored in Gutenberg allowing extensions to any component. Decorators can be used to allow the following use-cases:
Extend the `Editable` component to add “footnotes” to all text-based blocks
Extend the publish button and change it’s background if the post content is not HTML valid (or any other check)
Remove some components by extending them with “empty” components.
This is one of my favorite considered extension API, block templates. Block templates are a list of pre-filled blocks with placeholders, some of these blocks are “locked”, they can’t be moved or removed. Imagine a “product” custom post type defining a template with an image block, a text block for the description, a price block. And when a user decides to add a new product, the editor is already prefilled with these blocks. All
what‘s left is filling the placeholders. Isn’t this a great experience for Custom Post Types?
Conclusion
Building extensibility APIs is hard, and replicating the actions and filters we’re using in PHP plugins may not be the best option for longer-term viability. Relying on real use-cases and building generic patterns around them is what would lead to the best possible extensibility API for Gutenberg and the future of JavaScript-based WordPress plugins.
If you’re a plugin/theme developer, I encourage you to try the tips exposed in this post and share your extensibility use-cases with the Gutenberg team by replying to existing issues or creating new ones.
If you're already familiar with WordPress, you're probably used to its content editor based on TinyMCE. Creating content in WordPress did not really change for many years now. But with new competitors gaining more and more attraction like Medium, Ghost, Wix, Squarespace, WordPress decided to build a new Editor called Gutenberg (After Johannes Gutenberg, the inventor of the printing press).
Gutenberg is a big change, it's a completely new way of creating content. Instead of writing inside a unique rich text input, you add blocks of various types (paragraphs, images, videos, embeds, quotes, lists….) to compose your post's content.
The impact of this change on WordPress Users is not negligible. Content creators will have to learn about blocks, plugins authors will create custom blocks and templates, theme authors will style blocks… There are several posts out there talking about these changes and their impact on the users but very few talk about how Gutenberg is changing radically how we develop WordPress itself (aside from the frameworks battle,
VueJS VS React VS Preact)
1- Developing in Github
Usually WordPress development happens in WordPress Trac, through tickets and patches, while featured plugins usually happen in GitHub, with a separate repository for each Featured Plugin. This repository is removed once merged into Core. Gutenberg is being developed as a featured plugin on Github. While this is not the first time GitHub is being used to develop for WordPress, contributors are starting to question whether GitHub is more suitable for longer-term development and not only for featured plugins.
One of the last featured plugins merged into Core was the WP-API. Contributions to the project diminished a lot once the plugin was merged, and Trac has proven to be a huge barrier at entry for several developers already familiar with GitHub and its niceties.
2- Single Page Application?
WordPress is a classic PHP application where most of the UI rendering is done server-side. JavaScript is mostly used to some DOM interactions to server-side generated HTML.
While It's very unlikely that WordPress becomes a single page application tomorrow (or in the next months), Gutenberg renders its UI in the client (similarly to the Customizer or the media library). It's a Single Page Application built inside a regular WordPress Admin Page. In SPAs, the browser doesn’t reload for every click you make. Interactions feel fluid instead of abrupt. Notably, interactions can feel faster.
Gutenberg also leverages the REST API to fetch Data from the server. It's the first project in WordPress Core using the recently merged REST API. Several other will follow.
3- Modern JavaScript
Despite the fact that WordPress recommends PHP 7, it is still supporting PHP 5.2 and thus being written with PHP 5.2 compatible code. But unlike PHP, JavaScript transpiling is a thing, which means we can still write JavaScript code in the last versions (ES2015+ or more commonly called ESnext) and transpile it to ES5 code compatible with legacy browsers.
Gutenberg is leveraging this possibility and being written in ESnext + JSX which has a big impact on the JavaScript developer Experience. WordPress already has some JavaScript build setup based originally based on Browserify and updated recently to use WebPack (Thanks Adam). Gutenberg takes things further bringing babel compilation (using the babel-env preset) to this setup.
4- UI Framework
We can't talk about modern JavaScript without touching on the UI Framework discussion happening in WordPress. Backbone has been the framework of choice of WordPress for some years now, ever since its introduction with the Media Library. But it has proven hard to maintain and extend.
Pushed by the Gutenberg Project, WordPress contributors are exploring alternatives which include a Framework agnostic approach that could be summed up like this:
Picking a UI framework for WordPress Core. Gutenberg is using React for now, but this decision is not final yet.
Provide an abstraction layer allowing Plugin Authors to use the UI framework they are most comfortable with to extend WordPress UI
Good discussions around this have already happened and are still ongoing in the WordPress Core JS meetings, I encourage you to read the meeting recaps if you're interested in the subject.
5- Testing & Linting
Modern Javascript also brings with it its plethora of new tools.
For testing purposes, WordPress followed the jQuery path in using QUnit. While it's still possible to continue using QUnit with ESnext JavaScript code, the setup would be complex and new actors in the market are changing the way we write, run and debug tests making QUnit feel like the stone age of Unit Testing. One of these tools, Jest is being used by Gutenberg.
Linting and formatting are the other aspects of Modern Javascript Development seeing a lot of changes and updates recently. JSHint no longer support ESnext features properly and WordPress is moving to ESlint for this purpose. The Gutenberg Team and the Javascript Core Contributors also talked about using Prettier to format code, but opted to postpone for now. Using prettier could change the JavaScript Style Guidelines drastically.
6- Modularization
Gutenberg is also built with modularization in mind. Instead of writing a single big package, it's being split into smaller packages:
@wordpress/components: Generic UI components reusable outside of the Gutenberg context
@wordpress/i18n: Internationalization utilities
@wordpress/element: Abstraction on top of the UI framework
@wordpress/date: Date formatting and manipulation utilities
@wordpress/blocks: Module providing utilities for registering and building blocks
@wordpress/editor: Module representing the WordPress Editor's page
These modules are being built and proven in Gutenberg for both Gutenberg and WordPress. This approach has resulted in the new WordPress packages repository. The goals for this repository can be summed up as follows:
Provide WordPress reusable modules for use in several WordPress Core Components and Featured Plugins
Build autonomous packages reusable outside of the WordPress context
Engage better with the broad JavaScript community
Bring consistency across several parts of WordPress by reusing modules (The components module represents a WordPress pattern library)
Also one of the most important aspects of the modularization is the way it improves and eases contributing to WordPress. WordPress is a huge application with thousands of files, it's overwhelming for new contributors and it's very easy to get lost in all these files and components. Using a modular approach addresses this issue by splitting the application into smaller autonomous bits with a clear and well-defined API. It's easier for contributors to chime in and understand specific autonomous modules than it is in a unique huge application.
7- UI and styling
WordPress UI has not been significantly updated in years now. With Gutenberg, this could change. While it's not trying to be a complete UI refresh, it paves the way to other parts of WordPress by providing reusable UI elements to build a lighter, more "modern" UI.
Having a set of well defined UI components can help ensure accessibility stays a priority across all parts of WordPress. If one component is made accessible, this accessibility will then apply wherever the component is reused.
Gutenberg is also leveraging some simple SASS features (variables and mixins) bringing consistency to WordPress styles as well. For instance, if you take a look at WordPress's code base, you'll notice more than 50 shades of gray used and dozens of shades of blue. The same could be said for media queries thresholds. Gutenberg contributors have helped make this consistent by narrowing down a canonical list of colors, and refined list of fewer breakpoints.
Even Icons are being updated. Gutenberg is still using the WordPress Dashicons, but thanks to the recent changes to the browser support for WordPress, Gutenberg is now leveraging SVG icons instead of Icon Fonts.
8- Documentation
While documentation is not a solved problem yet in the project, Gutenberg is trying to bring new ideas to the table, such as Documentation in Code as well as the possibility to use and demo the code right inside the documentation itself. Gutenberg is currently using a self-made documentation tool similar to React Storybook but more customizable to match the WordPress Documentation Styling.
Conclusion
These are exciting times for WordPress with big changes coming to the WordPress Development Experience. We could reasonably argue that these changes are likely to demand some investment in the current WordPress developers, to help them learn new tools but "What bring us here, won't get us there". Most of these changes help modernize WordPress Development, they align with the broader Web development community, and all in all are likely to bring new contributors to WordPress, and lower the barrier to entry.
Do you know WordPress, this tool that powers 27% of the web? This big old CMS everyone loves to hate because It’s oldish, it’s PHP and it’s not an SPA? but in the same time, everyone uses because it’s so great at achieving the goal it’s designed for: creating content? Well! It’s time to stop criticizing and take a look at what’s happening in the WordPress community and what we’ll get for the next iteration of our beloved CMS? (more…)