What WordPress needs from a JavaScript framework

JavaScript developers in the WordPress community are splitting into camps and taking up arms in the fight for the future of WordPress JavaScript development. Most of the arguments I’ve read have little to do with how the frameworks would work with WordPress, and instead focus on mostly irrelevant features of the frameworks themselves. Yes, there are many good (and bad) arguments for why each framework should be used in isolation, but WordPress isn’t popular for working on isolated projects. The power and popularity of the CMS is the theme and plugin ecosystem. Even if a team is developing custom themes and plugins from the ground up, the majority of developers are leveraging plugins and themes made by the community.

If a team is working in relative isolation, I would argue that the community direction doesn’t matter much. So long as the framework of choice can accomplish the specific business goals of the project, a team can choose React, Vue, Angular n, or whatever else they want. It’s an injustice to the larger community for developers to push their favorite framework rather than having an unbiased discussion about the most appropriate tool for the ecosystem.

My framework journey

I began in the Angular 2 space.  Typescript was cool, Angular 2 was exciting, and having Google’s backing meant a lot to me at the time. I wanted Angular 2 to the the framework of choice for The Symphony Agency, but it would have required too much overhead for the team. No one wanted to learn TypeScript and Angular, while great for applications, was too much for the range of use cases (mini view components to larger applications). I loved working with Angular 2 on experimental internal tools, and I wanted it to work out, but in the end, it wasn’t the right tool for the job.  It’s not you Angular… it’s me.

Despite making amazing development tools, I had an aversion to getting to know React.  However, I refused to let myself avoid it if I didn’t have a real argument. I began building things in React and quickly fell in love again. I began testing for what WordPress needs, with the intention of creating a full featured React theme. The first critical road block was the inability to render templates asynchronously returned from WordPress. There are valid arguments for why you wouldn’t want to do this, but being able to output components added in the editor is a key feature for WordPress. WordPress is a Content Management System, and therefor the content needs to be able to be managed from Admin. Without this feature, content returned from WordPress is limited to basic HTML.  What if I want a shortcode that outputs a React component?

Aside from the previous issue, React apps expect that functions and components are imported directly into the scope where they’re used. From what I’ve found, there is no concept of a global component registration. The explicit nature of React is a dream for application development and testing, but it introduces the need for ridiculous workarounds in an open extendable system like WordPress. If there are solutions that I’ve missed, I would love to see it shared below.

My last-ditch  effort was to check out that Vue thing. I didn’t want to go through the pain of learning another framework, but an hour of reading the docs had me interested. Vue was easy to learn and didn’t require a lot of JavaScript expertise, which is good for a growing team at an agency. A Vue component could be written in plain JavaScript without a build process, which was good for quick one off solutions on older sites (technically this can be done with the others, but who’s actually going to do that?) Template syntax was easy, component definitions were clear, project setup didn’t require any magic tooling, and overall it was flexible.

Note that while I enjoyed writing components in Vue (just as much as Angular and React), that’s not a good enough reason to make a choice.

What the WordPress community needs in a JavaScript framework and approach.

This is not an exhaustive list, but below I try to cover my major concerns. Each framework has items it does or does not handle well, so I’ll attempt to be unbiased.

Extendable without a build pipeline*

Extendability is paramount. WordPress core, themes, and plugins are built with this as a core focus. Without it, the community is missing out on, what I consider, the most important aspect of WordPress. A developer should be able to add features to plugin or theme without editing and rebuilding its’ source. Adding global components to be used in the template syntax makes this particularly easy for isolated components, and having references to Redux or Vuex would allow a plugin extension to add data changing features to a 3rd party product.

Display a component template from a database stored string*

WordPress is a Content Management System (CMS), and as a CMS it needs to be able to actually manage content. A developer needs to be able to allow their fancy new component to be output from WYSIWYG. This can currently be done by providing an ID to an element in all frameworks, but, as far as I can tell, can only be rendered as template syntax in Vue.

Automatically display a component within a template, or as an app

A plugin developer should be able to write a component that can exist independently as its’ own app, or within the template of another app. Most themes aren’t using a JavaScript framework, so a developer needs to be able to determine how the component/app will be initialized. Without the community coming together on a standard, I can’t think of a solution that would work in all situations (with current APIs).

jQuery compatibility

jQuery is all over the web, and especially on WordPress sites. Sometimes a developer can get away with this when it’s interacting with a component inside a framework, however if the framework decides to re-render a view and destroy a targeted element, jQuery functions lose their references to that element. The community needs an approach to increase compatibility.

WordPress developer experience*

It’s a hard to swallow truth for some, but most that categorize themselves themselves as WordPress developers aren’t great developers. It’s not to say that they don’t produce a great product, and it’s not that you have to be a JavaScript or PHP wizard to be great. However, the JavaScript world uses a lot of development approaches that are entirely foreign to many WordPress devs. A framework should be powerful enough for experience JavaScript developers to work their magic, but easy enough to understand for developers who are trying to get their feet wet. If a junior developer without a ton of JavaScript experience needs to jump in and start working with components in a pinch, they should be able to do so. For the community to settle on a common framework, it needs to be something that most developers can actually work with.

(THE FOLLOWING ARE SPA SPECIFIC)

Server Side Rendering

SSR for JS frameworks requires the ability to run JavaScript on the server. This is a big problem for shared hosting as it often requires installing V8 on the server. Without this, a theme would have to create alternate pages just for search engines to read. That approach isn’t an issue with standard posts and pages (easy to do), but SSR becomes important when the site has a lot of custom templates and dynamic content.

Dynamically define page/post templates passed via string*

For Single Page App (SPA) themes, a framework’s routing engine of choice needs to be able to handle dynamic templating of views. While it’s not possible, without getting hacky, to dynamically change the page template list in the page editor, the framework itself should be able to receive a template name or template type identifier(page, post, cpt, archive, 404 etc) and render the content appropriately. The routing engine should allow a developer to hook into the returned post content and determine what router view component to display.

Anchor to router conversion*

Menus are defined in WordPress, but the output will be full urls. A developer needs a solution to be able to intelligently convert appropriate links to router links instead. The routing engine should be flexible enough to dynamically adjust for this. Note that this is an issue whenever content is returned, not just with menus.

* Marks items that I’ve been able to solve with Vue, but are not necessarily limited to Vue.

Conclusion

Ultimately, I don’t care what framework the community settles on. As a developer I just want a tool that hits all the marks for allowing me to provide as much business value as possible. I enjoy Vue, React, and Angular, but currently Vue hits more marks than the others (noted with * above). In the end, extendability and compatibility with existing tooling is key. I hope the community is able to work out the issues and bring modern tooling to WordPress development.

If you have any concerns or solutions, leave a comment below.

 

How to write Node Modules

Why use Node modules?

While figuring out how to make some application work, it’s common to write helper functions and separate blocks of responsibility in the same file.  It’s tempting for new developers to continue trying to write out their application using the same patterns from their initial proof of concept. Unfortunately for organization sake this quickly makes the project convoluted and not maintainable. Node modules are a way to separate and organize your code.

When should you abstract code into a module?

  • You’re copying and pasting helper functions into different files.
  • Common complicated patterns are used repeatedly.
  • A 3rd party module implementation is over-complicating your logic.
  • You’re using a class or logic that isn’t explicitly tied to the code in the file.
  • The size or complexity of a file is becoming overwhelming.
  • You want to write tests
  • You care about your code and want it to be maintainable.

Splitting your code into modules isn’t just for the server side of things.  It’s also extremely useful when building a front-end application.  Building your projects with webpack requires intimate use of modules to stay organized.

Require vs Import

Require() is a function in Node that can import either an installed NPM module by module name, or an exported module using a file path.

Import is an ES6 feature for fetching exported functions, objects, and primitives from another file. Browser compatibility is limited at the time of reading this and requires Babel in your build pipeline. To use these natively in node, you’ll have to either run your server code through a build process, or enable harmony modules at run time. I like to use import when building front-end applications, but I stick with require in Node.

In these examples, I’m going to stick with require()

Building a module

Splitting code into a module is easy.

  1. Create a new file.
  2. Move code into the new file.
  3. Organize so that it can be exported as a single object
  4. set module.exports equal to whatever you want to export.

Here are examples of exporting a function, or an object. Note that you can only have one module.exports per file.

Importing the function into another file is also simple. use require(path) to return the exported variable.

Examples of exporting

Define functions and export their references in a single object.  This method makes it very easy to see exactly what is being exported.  It also gives you a way to rename the variables.

Define functions and variables in place within the exported object.

Export a class.

Passing dependencies

You will often find the need to pass options or references to existing objects into modules.  If you want to split configuration code that needs a reference to an existing object (like a reference to an app/server object), you can export a generator function.  Immediately invoke the result of the required file and pass in your dependencies.

Private scope

Exported functions have access to the scope of their defining file.  Ultility functions and variables can be hidden from the API by defining them out of the exported scope.

Query WP REST API Using Any Permalink URL

Problem

I’d started the journey of creating a fully async WordPress site using WP REST API at The Symphony Agency.  For interacting with posts and listing out a blog, the API seemed great.  However, I quickly ran into the issue of not being able to do URL based queries on any page, post or post type.  For an Asynchronous WordPress site to be able to cover all the bases, it needs to be able to take advantage of the WordPress permalink system, as well as provide front end linkages to all systems that would typically be available when writing templates in PHP.

I’d built a routing system that would send any request URL (from root) through the WP REST API to WordPress, and I needed WordPress to respond with enough of the query to give me information to determine:

  • Post type
  • Template
  • archive or single
  • 404
  • search
  • page
  • etc

Solution

After endless searching and hair pulling I came up with this extension to the WP REST API.

function route_handler($request)
{
    global $wp;
    global $wp_query;
    $parameters = $request->get_json_params();
    $url = $parameters["url"];
    $_SERVER['REQUEST_URI'] = $url;
    $wp->parse_request();
    $wp->query_posts();
    //Insert queries for more specific information
    //Modify or simplify the query results
    //Here I'm just returning the query results.
    return json_encode($wp_query);
}
add_action('rest_api_init', function () {
    register_rest_route('custom-theme/v1', '/route', array(
        'methods' => 'POST',
        'callback' => 'route_handler',
    ));
});

This method allows me to sent an asynchronous request via JSON with “url” as a key value pair, and have WordPress return the results as JSON.  With this, you simply need to send any url request for content, get the content, set the page’s url, and display it.  Other internal clicks to anchor tags should be built to send async requests through this method, using the default WordPress permalink structure.

Hope this helps!

Asynchronously loading Vue component template

Problem:

When developing a Vue application that interfaces with a CMS (WordPress in my case), you’ll run into the issue of displaying rendered html sent from the server in your components.  The normal way of rendering content in a component is to render strings into the template.

{{ yourVariable }}

String interpolation is great, but that doesn’t work if you want to render HTML or Vue components. Vue allows developers to define a component asynchronously with a promise, but the promise scope has no access to data or props.  Asynchronously defined components can’t get a string that is already in a parent component.

Solution

Define a child component in the parent component’s data, and use :is="" in the template.  This allows you to dynamically define the child component, and render it when the string is ready.  Templates need to be defined at component creation, but this allows you to delay creation and generate the component when the data is ready.

Here is an example of defining a component in the data object.

See the Pen Child component from data variable Example by John H Horton (@Johnhhorton) on CodePen.0

This example shows that a defined global component tag will be rendered from the template string.

See the Pen Global component from data variable Example by John H Horton (@Johnhhorton) on CodePen.0

This is an example of asynchronously defining the component.  Click ‘Result’ and wait 3 seconds.

See the Pen Global component from async data variable Example by John H Horton (@Johnhhorton) on CodePen.0

If you apply this method, you aren’t limited by what you do with content strings.  You can save components tags in your content, and render them when the content is loaded asynchronously

In a content heavy site you will have to use a content component a lot. Create a global content-component that handles this everywhere.

In my example, the content-component is creating a new component to render the content. The content-area component receives a content string via props. The child component is dynamically created using the content prop as its’ template.

See the Pen Content Component by John H Horton (@Johnhhorton) on CodePen.0

There are other ways to organize a content-component.  If you come up with a better version, let me know!

Edit:

Rheinard Korf provided a far more concise method using a computed property. Example below:

See the Pen Content Component by Rheinard Korf (@rheinardkorf) on CodePen.0