Updates to Script Modules in 6.7

WordPress 6.7 introduces a new @wordpress/a11y script module and a 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. to pass script module data from the server to the client.

Continue reading

#6-7, #dev-notes, #dev-notes-6-7, #javascript, #script-loader

Proposal: Server to client data sharing for Script Modules

Abstract

Script Modules were introduced in WordPress 6.5. wp_add_inline_script is often used to initialize or make data available to Scripts. Feedback on Script Modules and explorations suggest this would be a useful feature for Script Modules, but nothing exists at this time. This post will describe the problem in detail and propose a solution. The proposed solution consists of three main points:

  • A new filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. runs for each Script Module that is enqueued or in the dependency graph. This filter allows arbitrary data to be associated with a given Script Module and added to the rendered page.
  • Script Module data is embedded in the page as JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. in a <script type="application/json"> 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.).
  • Script Modules are responsible for reading the data and performing their own initialization.
Read more: Proposal: Server to client data sharing for Script Modules

The feedback period will end 2024-05-24 (Friday, May 24). Please provide any feedback before then.

This post will use “scripts” to refer to WP Scripts and “modules” to refer to WP Script Modules.

Scripts or modules?

Most 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/. for WordPress is probably using scripts unless it was specifically compiled as a module. Modern JavaScript is often authored using import apiFetch from '@wordpress/api-fetch', which is module syntax. Until very recently, WordPress build tooling has always removed the module syntax and compiled a script.

Only the most recent WordPress version 6.5 introduced support for modules. WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. includes exactly two modules to expose functionality at this time: @wordpress/interactivity and @wordpress/interactivity-router. JavaScript that uses the Interactivity 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. is probably a module.

This post will talk about a common script dependency, wp-api-fetch. The @wordpress/api-fetch module mentioned in this post is hypothetical; it does not exist at this time.

A note about modules

It’s important to know a few things about scripts versus modules in the context of this post. A few key differences:

  • Scripts and their dependencies will be executed as the page is parsed even if a dependency is never directly used.
  • Script “exports” are attached to the window object, e.g. wp-api-fetch is available as window.wp.apiFetch.
  • Modules will execute after the page has finished parsing.
  • Module dependencies can be loaded on demand.
  • Modules have true encapsulation, using import and export to share values.
More about scripts and modules…

Scripts that are either enqueued or are dependencies of enqueued scripts will be added to the page as script tags, like <script src="path/to/script.js">. The browser will fetch and execute these scripts before it continues to parse the page. There are attributes like async and defer that can change how the browser executes scripts.

Modules that are enqueued will appear on the page as script tags of type module, like <script src="path/to/module.js" type="module">. Processing of modules is deferred, they will be executed after the whole document has been parsed. The async attribute will cause a module to execute in parallel as the document is parsed. WordPress Script Modules do not use async at this time.

Modules that are in the dependency graph of enqueued modules will appear in an importmap. This is a mapping of names to URLs so that a browser knows what module to fetch when it sees an import. It’s what associates the module used in a statement like import "a-module"; with a URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org { "imports": { "a-module": "path/to/a-module.js" } }.

The problem

Scripts often require some initialization or other data to work correctly in WordPress. The wp-api-fetch script is a good example, it requires a significant amount of configuration. For example, Core uses the following inline script to initialize wp-api-fetch so it can send requests to the appropriate place:

$scripts->add_inline_script(
	'wp-api-fetch',
	sprintf(
		'wp.apiFetch.use( wp.apiFetch.createRootURLMiddleware( "%s" ) );',
		sanitize_url( get_rest_url() )
	),
	'after'
);

This snippet uses PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher to create a string of JavaScript code with some data from PHP embedded. This will be included in a script tag that appears immediately after the script tag for wp-api-fetch, something like this:

<script src="path/to/wp-api-fetch.js"></script>
<script>
// The JavaScript code is printed here:
wp.apiFetch.use( wp.apiFetch.createRootURLMiddleware( "…/index.php?rest_route=/" ) );
// More code may follow from other calls to `wp_add_inline_script`…
</script>

Notice that the JavaScript depends on wp-api-fetch, it imperatively calls wp.apiFetch.use(…). That same approach with a hypothetical @wordpress/api-fetch module would look something like this:

<script type="importmap">
{ "imports": { "@wordpress/api-fetch": "…url/to/api-fetch-module.js" } }
</script>
<script type="module">
import apiFetch from '@wordpress/api-fetch';
wp.apiFetch.use( wp.apiFetch.createRootURLMiddleware( "…/index.php?rest_route=/" ) );
</script>

In this approach, the initialization module would fetch and execute the @wordpress/api-fetch module just to initialize it! That eliminates one of the important advantages of modules, their ability to load on-demand. 🤔 It looks like this imperative initialization isn’t a good fit for modules. Let’s see if there’s a better solution…

The proposal

Here are some requirements that arise from the naive implementation:

  • Modules should be fetched and initialized on demand.
  • Modules should be responsible for their own initialization when they’re executed.
  • Variables should be scoped to modules and not pollute the global namespace.
  • The data should introduce minimal overhead.

Add server data via filters

Filters provide a nice method to collect the data needed by modules. The WP_Script_Modules class introduces a new filter that runs for each module that is enqueued or present in the dependency graph. Adding or modifying data for a module looks like this:

add_filter(
	'scriptmoduledata_@wordpress/api-fetch',
	function ( $data ) {
		$data['rootURL'] =  sanitize_url( get_rest_url() )
		return $data;
	}
);

Multiple filters can be added to add or modify the data exposed to the script, and if no data is added, nothing will be serialized on the page for the client. It’s also worth mentioning that no JavaScript code is written in PHP, a nice improvement over wp_add_inline_script which requires valid JavaScript to be added.

A drawback to this approach is that all the data passed must pass through JSON. Data without a valid JSON representation is not supported by default.

Use an inert script tag to expose data on the client

The data is embedded it in the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. in a script tag:

<script id="scriptmoduledata_@wordpress/api-fetch" type="application/json">
{ "theData": "JSON Serializable data can be shared" }
</script>

This script tag is effectively ignored by the browser because of its type attribute. This approach is an example on MDN of how to embed data in HTML and it’s already used in WordPress to pass Interactivity API data to the client.

Because modules are always deferred, it should be safe to print these script tags at the bottom of the page. They should have limited impact on page load because the browser will not parse or execute the contents.

Modules read data from the script tag

This script tag doesn’t do anything on its own. The module is responsible for getting the data and performing its initialization when it executes:

if ( typeof document !== 'undefined' ) {
	const serializedData = document.getElementById(
		'scriptmoduledata_@wordpress/api-fetch'
	)?.textContent;
	if ( serializedData ) {
		let config = null;
		try {
			config = JSON.parse( serializedData );
		} catch {
			// there was a problem parsing the serialized data
		}
		performInitialization( config );
	}
}
function performInitialization( config ) {
	if ( config?.rootURL ) {
		registerMiddleware( createRootURLMiddleware( config.rootURL ) );
	}
	// etc.
}

This approach is used by @wordpress/interactivity to retrieve store data on the client.

Try it!

I’ve prototyped this proposal in the following PRs:

  • WordPress-develop PR 6433 applies the filters and adds the necessary filters to expose data to @wordpress/api-fetch. The proposal in this post is contained in this PR.
  • Gutenberg PR 60952 builds and registers the @wordpress/api-fetch module. This PR is helpful for testing, but is beyond the scope of this post.

Try it in the WordPress Playground here. If you run the following JavaScript in the inspector console —make sure you pick the JavaScript context, something like wp (scope:abc123)— you’ll see the @wordpress/api-fetch module log some initialization when it’s imported and then work as expected:

const { apiFetch } = await import( '@wordpress/api-fetch' );
await apiFetch( { path: '/wp/v2/block-types' } )
Screenshot of browser console showing the `@wordpress/api-fetch` module initializing on demand and being used to make a REST request.

Relevant links

Props @youknowriad, @cbravobernal, @bph, and @andronocean for review.

#javascript, #script-loader

Script Modules in 6.5

A new “Script Modules” interface has been introduced to support native JavaScript modules in WordPress. 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/. modules use import and export and are often referred to as ECMAScript Modules or “ESM”.

This post will refer to “scripts” and “modules” for Scripts and Script Modules concepts, respectively.

JavaScript modules are a coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. web technology with a number of benefits like import and export for proper scoping, forced strict mode, and deferred loading. It’s important for WordPress to support modules and encourage their use as the future of JavaScript development.

Script Modules 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.

The interface is modeled after the existing scripts interface and should feel familiar. Modules are identified by a unique identifier (ID), analogous to a script handle.

The registered module ID should be identical to the imported module name in JavaScript. For example, the @wordpress/interactivity module can be used in another module as:

import * as interactivity from '@wordpress/interactivity';

Registered modules have an array of module dependencies. Dependencies can be a simple string (the dependency module ID) or an associative array of the following form:

$dependencies = array(
	'id' => '@wordpress/interactivity',
	'import' => 'dynamic' // Optional.
);

The array form optionally includes an import key with the value 'static' (default) or 'dynamic'. Dependencies that may not be needed or should only be loaded under some circumstances should use 'import' => 'dynamic'.

Note that these dependencies are module dependencies, not script dependencies. Script handles should not be listed as module dependencies.

The following functions are the most relevant parts of the interface for developers working with modules:

  • wp_register_script_module( string $id, string $src, array $deps = array(), $version = false ): Registers the module.
  • wp_enqueue_script_module( string $id, string $src = '', array $deps = array(), $version = false ): Marks the module to be enqueued. An optional $src argument can be provided to enqueue and register the module.
  • wp_deregister_script_module( string $id ): Deregisters the module.
  • wp_dequeue_script_module( string $id ): Unmarks the module so it is not enqueued.

Important notes

It’s strongly recommended that developers currently utilizing JavaScript modules in their extensions migrate to the Script Modules API. This will standardize behavior, bring a number of benefits, and prevent some of the following potential issues:

  • Any code that is currently using import maps may run into compatibility issues because multiple import maps are not currently supported.
  • If a module appears before an import map, an error will be triggered that causes the import map to be ignored. This would break some critical functionality that the Script Modules API relies on.

It’s important to migrate to the new API to prevent these issues. If it’s unfeasible to migrate, moving modules script to the footer may mitigate some of the potential issues.

Available modules

Two core modules are provided with 6.5.

@wordpress/interactivity is the interface for building interactive frontends with the Interactivity API.

@wordpress/interactivity-router defines an Interactivity API store with the core/router namespace, exposing relevant state and actions for client-side navigation.

There are no other core modules available at this time. The JavaScript packages available as scripts before 6.5 are not available as modules. For example, the @wordpress/api-fetch package corresponds to the wp-api-fetch script and is not available in WordPress as a module.

Working with Script Modules

The most relevant functions for working with modules are wp_register_script_module to register and wp_enqueue_script_module to enqueue modules. For example:

// Registers a module, it can now appear as a dependency or be enqueued.
wp_register_script_module(
	'@my-plugin/shared',
	plugin_dir_url( __FILE__ ) . 'shared.js'
);

// Registers and enqueues a module.
wp_enqueue_script_module(
	'@my-plugin/entry',
	plugin_dir_url( __FILE__ ) . 'entry.js',
	array( '@my-plugin/shared' )
);

// Enqueues a previously registered module.
wp_enqueue_script_module( '@my-plugin/a-registered-module' );

In this example, the @my-plugin/shared module will be available to the @my-plugin/entry module:

// "@my-plugin/entry" module at …/entry.js
import * as shared from '@my-plugin/shared';
shared.doSomethingInteresting();

Blocks

WordPress 6.5 introduces a new viewScriptModule block metadata field that will handle module registration and enqueue automatically analogous to viewScript. A full dev note about viewScriptModule can be read here.

Module registration

Developers familiar with modern JavaScript development will recognize the module system and may wonder, “Do I have to register all my modules with WordPress in order to use them?” The short answer is no, but the recommended approach is to register all the modules.

JavaScript modules can import be imported by URLs. It’s common to see imports like import { utility } from './utilities.js' in modern applications. Because the Script Modules API is built on top of native JavaScript modules, it’s possible for modules to import relative paths in WordPress. However, the recommended approach is to register modules and use the registered ID to import the module. This has a few benefits:

  • Registered modules are available globally. There’s no need to worry about the module URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org.
  • Registered modules have versions. The Script Modules API transparently handles associating a module ID with the correct URL and version.
  • Risk of module duplication is reduced. If a module is imported through different URLs, the browser may fetch and execute multiple copies of what is ostensibly the same module.
  • Dependencies that are imported statically will be preloaded when the module is enqueued. This allows the browser to fetch them in parallel.

Relative imports to unregistered modules may be useful for prototyping and exploration, but the best practice for production code is to register modules with the Script Modules API.

Limitations

Modules and scripts are not compatible at this time. Modules cannot depend on scripts and scripts cannot depend on modules. This means that modules cannot depend on scripts like wp-i18n, wp-api-fetch, etc.

There is a workaround to use scripts from modules. Script functionality is shared by adding variables to the window scope, for example wp-api-fetch can be accessed via window.wp.apiFetch. To use scripts from modules at this time, developers must:

  • Ensure that the script is enqueued: wp_enqueue_script( ‘wp-api-fetch’ )
  • Access the script through the global scope: const { apiFetch } = window.wp

There are a number of downsides to this workaround, but it can be an effective solution. Follow Core Trac ticket #60647 for work on script and module interoperability.

Compatibility

JavaScript modules have excellent support in most browsers today. In addition, the Script Modules API includes a polyfill for browsers with lacking or incomplete support to make the number of supported browsers even greater.

Technical details

A full explanation of how the Script Modules API works is beyond the scope of this note, but this section will provide a brief overview.

The Script Modules API will track registered and enqueued modules. For each enqueued module, a <script type="module"> 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.) will be added to load and execute the module.

A <script type="importmap"> tag will be added. The import map tells the browser how to map module IDs to URLs so that when it sees an import for '@wordpress/interactivity', it knows that the module should be fetched from the URL /wp-includes/js/dist/interactivity.min.js?ver=xyz. The import map includes all the dependencies of all enqueued modules, and all the dependencies of those dependencies, etc. The import map will not include dependencies of all the registered modules, only those that may be required on the page as dependencies, and it will not include the enqueued modules unless they are in the dependency graph of other enqueued modules.

A <link rel="modulepreload"> will be added for all static dependencies. Static dependencies are all dependencies that are not defined as array( 'id' => '…', 'import' => 'dynamic' ). This is an optimization hint for browsers, read more about it here.

Relevant links

Props

#6-5, #dev-notes, #dev-notes-6-5, #script-loader

Attributes for Resource Hints in 4.7

WordPress 4.6 added support for Resource Hints, a W3CW3C The World Wide Web Consortium (W3C) is an international community where Member organizations, a full-time staff, and the public work together to develop Web standards.https://www.w3.org/. specification that “defines the dns-prefetch, preconnect, prefetch, and prerender relationships of the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. Link Element (<link>)”. These can be used to assist the browser in the decision process of which origins it should connect to, and which resources it should fetch and preprocess to improve page performance.

With WordPress 4.7, you’re now able to pass specific HTML attributes to these resource hints to make even better use of them. Namely, the as, crossorigin, pr, and type attributes can now be defined when using the wp_resource_hints filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.. See #38121 for more information.

Here’s an example of how one can use this new feature:

function makewp_example_resource_hints_attributes( $hints, $relation_type ) {
	if ( 'prefetch' === $relation_type ) {
		$hints[] = array(
			'crossorigin' => 'use-credentials',
			'as'          => 'style',
			'pr'          => 0.5,
			'href'        => 'https://example.com/foo.css',
		);
	}

	return $hints;
}

add_filter( 'wp_resource_hints', 'makewp_example_resource_hints_attributes', 10, 2 );

While crossorigin can be used to set the CORS settings for a resource, pr indicates the expected probability that the specified resource hint will be used. The official W3C specification has more information about these attributes.

Note: preload is not yet supported by wp_resource_hints(), mainly because of a lack of browser support and benefit for coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.. This will continue to be reevaluated as browser support evolves for these emerging features.

#4-7, #dev-notes, #script-loader

Introducing admin_print_footer_scripts-$hook_suffix in 4.6

The admin_print_footer_scripts action hook is the last chance to localize adminadmin (and super admin) scripts; but it is a generic one. If you ever wanted to do something for specific admin pages only, you would either have to hook into another dynamic action, or hook into admin_print_footer_scripts and check the $hook_suffix (which is not even passed, but that’s not an issue) yourself. The problem with the former is that there might be happening a lot between the chosen action and when your script gets enqueued (admin_print_footer_scripts); and maybe you need to be aware of what has happened. The problem with the latter is that you would have to register possibly a lot of functions, maybe check the current admin page inside several of these, and eventually bail most of the times. That’s why WordPress 4.6 brings the dynamic footer action admin_print_footer_scripts-$hook_suffix. See [37279].

The following pre-4.6 code

add_action( 'admin_print_footer_scripts', function() {
    global $hook_suffix;

    if ( 'some_admin_page' !== $hook_suffix ) {
        return;
    }

    // Whatever it is that you want to do...
} );

can now be simplified like this:

add_action( 'admin_print_footer_scripts-some_admin_page', function() {
    // Whatever it is that you want to do...
} );

This change brings more consistency between wp-admin/admin-footer.php and wp-admin/admin-header.php, which already fires the generic admin_print_scripts and the dynamic admin_print_scripts-$hook_suffix actions.

For more background on the change, see #34334.

#4-6, #dev-notes, #plugins, #script-loader

Resource Hints in 4.6

Resource Hints is a rather new W3C specification that “defines the dns-prefetch, preconnect, prefetch, and prerender relationships of the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. Link Element (<link>)”. These can be used to assist the browser in the decision process of which origins it should connect to, and which resources it should fetch and preprocess to improve page performance.

Introduced with [37920], WordPress now has a simple 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. to register and use resource hints. The relevant ticketticket Created for both bug reports and feature development on the bug tracker. is #34292

By default, wp_resource_hints() prints hints for s.w.org (the 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/ CDN) and for all scripts and styles which are enqueued from external hosts.

Developers can use the wp_resource_hints filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. to add custom domains and URLs for dns-prefetch, preconnectprefetch or prerender. One needs to be careful to not add too many resource hints as they could quite easily negatively impact performance, especially on mobile, but the filter works like this:

function makewp_example_resource_hints( $hints, $relation_type ) {
	if ( 'dns-prefetch' === $relation_type ) {
		$hints[] = '//make.wordpress.org';
	} else if ( 'prerender' === $relation_type ) {
		$hints[] = 'https://make.wordpress.org/great-again';
	}

	return $hints;
}

add_filter( 'wp_resource_hints', 'makewp_example_resource_hints', 10, 2 );

#4-6, #dev-notes, #script-loader

Enhanced Script Loader in WordPress 4.5

This post summarizes some of the changes to the script loader and script/style dependencies in WordPress 4.5.

Individual stylesheets instead of wp-admin.min.css

Ticketticket Created for both bug reports and feature development on the bug tracker.: #35229

Currently, WordPress generates and ships relatively large 235KB wp-admin.min.css and wp-admin-rtl.min.css files which are created from source files which we also ship.
With WordPress 4.5 we stop generating these files and instead rely upon load-styles.php to combine them. This removes the requirement from shipping for commits such as [35896] 510KB of CSSCSS Cascading Style Sheets.. Instead, we only have to ship the 4 dashboard.css files which are around 72KB.

For 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 authors nothing should change because the script loader takes care of the new dependency for the wp-admin handle. Also, wp-admin.* files are still generated for compatibility purposes, however, they only include the @import() lines.

Breaking Change: If your plugin or theme is still using the deprecated media functionality please note that in [36869] the style handle was changed from media to media-deprecated.

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. ETag 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. for load-scripts.php and load-styles.php

Ticket: #28722

Both loaders for script and style concatenation are now sending an ETag header which includes the value of $wp_version. This improves performance since browsers won’t re-download the scripts and styles when they send the HTTP_IF_NONE_MATCH header and there was no change in $wp_version. ⚡️

wp_add_inline_script()

Ticket: #14853

For quite some time wp_add_inline_style() has been available to add extra CSS styles to a registered stylesheet. Now there’s an equivalent function to do the same for inline 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/.. wp_add_inline_script() can be used to add extra scripts either before or after a registered script using the optional third $position argument.

For example, the following code can be used to easily add Typekit’s JavaScript to your theme:

function mytheme_enqueue_typekit() {
   wp_enqueue_script( 'mytheme-typekit', 'https://use.typekit.net/<typekit-id>.js', array(), '1.0' );
   wp_add_inline_script( 'mytheme-typekit', 'try{Typekit.load({ async: true });}catch(e){}' );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_typekit' );

Which results in:

<script type='text/javascript' src='https://use.typekit.net/<typekit-id>.js?ver=1.0'></script>
<script type='text/javascript'>
try{Typekit.load({ async: true });}catch(e){}
</script>

Scripts/Styles with “alias” handles

Ticket: #35643, #25247, #35229

Alias handles are handles without a $src parameter. Those can be used to group dependencies, like core is doing for jQuery[36550] changes how those handles are loaded, more specifically, they are no longer skipped early in WP_Dependencies.

Now, inline styles and scripts attached to alias handles will do something important — get printed out. This change was required by the switch to an alias handle for wp-admin to provide backwards compatibility for plugins which are adding inline styles to the wp-admin handle.

Support for scripts with dependencies in different groups

Ticket: #35873, #35873

Scripts can be registered in two groups: head or footer. Previously, dependencies of registered scripts were moved to the header, even when the script that depends on them is loaded in the footer. This was fixed in [36871]. The changeset includes some expressive tests to demonstrate how complex dependencies, like “grandchild” dependencies, can be enqueued.

Last, but not least, WP_Dependencies, WP_Styles, and WP_Scripts are now fully documented. 📘

Thanks to @abiralneupane, @atimmer, @dd32, @gitlost, @ocean90, @sebastian.pisula, @sergej.mueller, @stephenharris, and @swissspidy for their contributions!

#4-5, #dev-notes, #script-loader