Skip to content

Latest commit

 

History

History
122 lines (84 loc) · 6.24 KB

5.1-wordpress-assets.md

File metadata and controls

122 lines (84 loc) · 6.24 KB

WordPress Assets

WordPress provides registration and enqueue APIs to load JavaScript and CSS that allow programatic and conditional interaction with static assets.

These APIs allow for dependency management, version-based busting of browser-cached assets and hooks for printing data from PHP for JavaScript to read from the global window object.

Never directly enqueue assets

  • Always register assets globally*
  • Enqueue assets conditionally

*with the exception of scripts where the source is extra-sensitive or local development assets that should be wrapped in conditional logic such that they're not registered in production environments.

Never directly call wp_enqueue_script() or wp_enqueue_style() without first using wp_register_script() or wp_register_style() -- this allows for programmatic override and substitution by other codebases.

Registering globally even when enqueues are conditionally-scoped helps detect and prevents race conditions of assets sharing the same handle in our products or third-party developers trying to debug their products while ours are running.

Break each parameter for wp_register_script() and wp_register_style() onto new lines

Benefits:

  • Easier to read, as these registrations often overrun 80 characters
  • Comment-out lines as you debug
  • More easily track changes in version control
// ❌ Don't put every parameter on a single line
\wp_register_script( 'web-admin-widget', WEB_BUILD_URL . '/index.js', apply_filters('nfd_web_admin_widget_dependencies', array('wp-element', 'wp-components', 'wp-dom-ready', 'wp-data')), $version, true );

// ✅ Break each onto a new line
$dependencies = apply_filters('nfd_web_admin_widget_dependencies', array('wp-element', 'wp-components', 'wp-dom-ready', 'wp-data'));

\wp_register_script( 
    'web-admin-widget', 
    WEB_BUILD_URL . '/index.js', 
    $dependencies, 
    $version, 
    true 
);

Naming dependency handle slugs

  • All company projects' dependency slugs should be prefixed nfd-*, even if they're third-party dependencies. i.e. nfd-react-router-dom
  • This is a global namespace. Be defensive, clear and courteous.
  • Do not postfix *-js, *-css, *-script or *-style. WordPress adds postfixes when printing assets in the DOM.
  • Keep parity between filename and dependency string While the nfd- prefix need not apply to filename (though it's fine if it does), please parity between filenames and the dependency slug -- don't name a file app.js and register nfd-module-admin-experience.
  • Never use dynamic slugs via WordPress Filters or inconsistient variables. These slugs should always be static.

Supply WordPress filter hooks for dependency assets

For the array of dependencies provided to registration functions, please wrap all arrays -- even empty ones -- with apply_filters() and a snake-case equivalent of the kebab-case slug and a postfix of _dependencies -- this allows other codebases to extend dependencies that get loaded with an asset (i.e. a brand-specific stylesheet whenever a brand-agnostic module asset is loaded)

First preference is given to 3rd-party vendor assets shipped in WordPress Core

In general, we prefer the use of assets that ship with WordPress instead of bundling other equivalents to reduce cumulative disk space and leverage assets already browser-cached by users.

Use environment-aware asset loading and configuration

Using wp_get_environment_type() to scope registrations and enqueue declarations for local, staging and production. Passing the value of wp_get_environment_type() through to scripts during runtime is also a great way to use one value across PHP and JavaScript.

Examples

  • Scope a localhost development server only to local
  • Use local to exclude analytics logic from capturing local development.
  • Use staging and local to switch a version to time() for cache-bustinng.
  • Use production to switch to minified assets.

Beware bundled dependencies in other codebases

WordPress does little to prevent the collision of assets. Please prefix third-party vendor code with nfd to avoid conflicts.

Instead of react-router-dom, use nfd-react-router-dom.

Provide a version string for caching

All mission-critical assets should be tied to the codebase's semver version, busting on every release.

Vendor code and more static assets can be locked to a specific version.

Note: the use of filetime() is not considered a reliable way to cache-bust assets.

Pass data to script at runtime

In addition to making API calls in JavaScript, it's easy to pass data directly into the DOM for a script to take advantage of. Sometimes a new API endpoint is overkill, it's undesirable to have a public endpoint for a sensitive operation or you want the response to an endpoint available immediately.

WordPress uses wp_add_inline_script to print inline scripts before or after the <script> tag for an enqueued asset.

wp_add_inline_script(
    'web-admin-widget',
    'console.log("web-admin-widget is running", window.web)',
    'before'
);

However, this is a great opportunity to pass data through to the application.

wp_add_inline_script(
    'web-admin-widget',
    'var Newfold =' . wp_json_encode( array( 'adminUrl' => admin_url(), 'userId' => get_current_user_id() ) ) . ';';
    'before'
);

Finally, this is a good time to point out that you can interact with Core and Custom REST Endpoints in PHP.

$request    = new WP_REST_Request( 'GET', '/web/v1/widget' );
$response   = rest_do_request( $request );
$server     = rest_get_server();
$data       = $server->response_to_data( $response, false );
wp_add_inline_script(
    'web-admin-widget',
    'var Newfold.apiResponse =' . wp_json_encode( $data ) . ';';
    'before'
);

Conditional checks and debugging

wp_script_is() and wp_style_is() are great for scoping logic and local development debugging for checking for registration or whether an asset is enqueued.

Query Monitor also lists actions firing where scripts and styles are enqueued, but also a complete reference of enqueued scripts and styles, their dependencies and the origin codebase where it was enqueued.