diff --git a/wp-admin/includes/admin-filters.php b/wp-admin/includes/admin-filters.php
index c8643749fb..06a973b0bb 100644
--- a/wp-admin/includes/admin-filters.php
+++ b/wp-admin/includes/admin-filters.php
@@ -43,6 +43,9 @@ add_action( 'admin_head', 'wp_color_scheme_settings' );
add_action( 'admin_head', 'wp_site_icon' );
add_action( 'admin_head', '_ipad_meta' );
+// Prerendering.
+add_filter( 'admin_head', 'wp_resource_hints' );
+
add_action( 'admin_print_scripts-post.php', 'wp_page_reload_on_back_button_js' );
add_action( 'admin_print_scripts-post-new.php', 'wp_page_reload_on_back_button_js' );
diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php
index 70da2f2e2a..fe716165fa 100644
--- a/wp-includes/default-filters.php
+++ b/wp-includes/default-filters.php
@@ -239,6 +239,7 @@ add_action( 'wp_head', 'wp_print_styles', 8 );
add_action( 'wp_head', 'wp_print_head_scripts', 9 );
add_action( 'wp_head', 'wp_generator' );
add_action( 'wp_head', 'rel_canonical' );
+add_action( 'wp_head', 'wp_resource_hints' );
add_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );
add_action( 'wp_head', 'wp_site_icon', 99 );
add_action( 'wp_footer', 'wp_print_footer_scripts', 20 );
diff --git a/wp-includes/general-template.php b/wp-includes/general-template.php
index db0dfafa74..222f248252 100644
--- a/wp-includes/general-template.php
+++ b/wp-includes/general-template.php
@@ -2787,6 +2787,97 @@ function wp_site_icon() {
}
}
+/**
+ * Prints resource hints to browsers for pre-fetching, pre-rendering and pre-connecting to web sites.
+ *
+ * Gives hints to browsers to prefetch specific pages or render them in the background,
+ * to perform DNS lookups or to begin the connection handshake (DNS, TCP, TLS) in the background.
+ *
+ * These performance improving indicators work by using ``.
+ *
+ * @since 4.6.0
+ */
+function wp_resource_hints() {
+ $hints = array(
+ 'dns-prefetch' => wp_resource_hints_scripts_styles(),
+ 'preconnect' => array( 's.w.org' ),
+ 'prefetch' => array(),
+ 'prerender' => array(),
+ );
+
+ foreach ( $hints as $relation_type => $urls ) {
+ /**
+ * Filters domains and URLs for resource hints.
+ *
+ * @since 4.6.0
+ *
+ * @param array $urls URLs to print for resource hints.
+ * @param string $relation_type The relation type the URLs are printed for, e.g. 'preconnect' or 'prerender'.
+ */
+ $urls = apply_filters( 'wp_resource_hints', $urls, $relation_type );
+ $urls = array_unique( $urls );
+
+ foreach ( $urls as $url ) {
+ $url = esc_url( $url, array( 'http', 'https' ) );
+
+ if ( in_array( $relation_type, array( 'preconnect', 'dns-prefetch' ) ) ) {
+ $parsed = parse_url( $url );
+
+ if ( ! empty( $parsed['scheme'] ) ) {
+ $url = $parsed['scheme'] . '://' . $parsed['host'];
+ } else {
+ $url = $parsed['host'];
+ }
+ }
+
+ printf( "\r\n", $relation_type, $url );
+ }
+ }
+}
+
+/**
+ * Adds dns-prefetch for all scripts and styles enqueued from external hosts.
+ *
+ * @since 4.6.0
+ */
+function wp_resource_hints_scripts_styles() {
+ global $wp_scripts, $wp_styles;
+
+ $unique_hosts = array();
+
+ if ( is_object( $wp_scripts ) && ! empty( $wp_scripts->registered ) ) {
+ foreach ( $wp_scripts->registered as $registered_script ) {
+ $src = $registered_script->src;
+ // Make sure the URL has a scheme, otherwise parse_url() could fail to pass the host.
+ if ( '//' == substr( $src, 0, 2 ) ) {
+ $src = set_url_scheme( $src );
+ }
+
+ $this_host = parse_url( $src, PHP_URL_HOST );
+ if ( ! empty( $this_host ) && ! in_array( $this_host, $unique_hosts ) && $this_host !== $_SERVER['SERVER_NAME'] ) {
+ $unique_hosts[] = $this_host;
+ }
+ }
+ }
+
+ if ( is_object( $wp_styles ) && ! empty( $wp_styles->registered ) ) {
+ foreach ( $wp_styles->registered as $registered_style ) {
+ $src = $registered_style->src;
+ // Make sure the URL has a scheme, otherwise parse_url() could fail to pass the host.
+ if ( '//' == substr( $src, 0, 2 ) ) {
+ $src = set_url_scheme( $src );
+ }
+
+ $this_host = parse_url( $src, PHP_URL_HOST );
+ if ( ! empty( $this_host ) && ! in_array( $this_host, $unique_hosts ) && $this_host !== $_SERVER['SERVER_NAME'] ) {
+ $unique_hosts[] = $this_host;
+ }
+ }
+ }
+
+ return $unique_hosts;
+}
+
/**
* Whether the user should have a WYSIWIG editor.
*
diff --git a/wp-includes/version.php b/wp-includes/version.php
index a4876342e2..003f705644 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
-$wp_version = '4.6-alpha-37919';
+$wp_version = '4.6-alpha-37920';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.