diff --git a/assets/apps/customizer-controls/src/typography-extra/LocalGoogleFonts.js b/assets/apps/customizer-controls/src/typography-extra/LocalGoogleFonts.js index ac499ecadd..7f6ba54fcd 100644 --- a/assets/apps/customizer-controls/src/typography-extra/LocalGoogleFonts.js +++ b/assets/apps/customizer-controls/src/typography-extra/LocalGoogleFonts.js @@ -20,7 +20,7 @@ const initLocalGoogleFonts = () => { return; } - const toggleControl = + const localFontsToggle = new wp.customize.controlConstructor.neve_toggle_control( NeveReactCustomize.localGoogleFonts.key, { @@ -32,7 +32,24 @@ const initLocalGoogleFonts = () => { } ); - render(, section.container[0]); + const preloadFontsToggle = + new wp.customize.controlConstructor.neve_toggle_control( + NeveReactCustomize.preloadFonts.key, + { + section: section.id, + label: __('Preload fonts', 'neve'), + setting: NeveReactCustomize.preloadFonts.key, + priority: 6, + } + ); + + render( + <> + + + , + section.container[0] + ); }; export { initLocalGoogleFonts }; diff --git a/inc/core/settings/config.php b/inc/core/settings/config.php index b3b9b5db6a..ab5ba5369a 100644 --- a/inc/core/settings/config.php +++ b/inc/core/settings/config.php @@ -94,6 +94,7 @@ class Config { const MODS_POST_TYPE_VSPACING = 'content_vspacing'; const OPTION_LOCAL_GOOGLE_FONTS_HOSTING = 'nv_pro_enable_local_fonts'; + const MODS_PRELOAD_FONTS = 'neve_preload_fonts'; const OPTION_POSTS_PER_PAGE = 'posts_per_page'; const MODS_TPOGRAPHY_FONT_PAIRS = 'neve_font_pairs'; diff --git a/inc/customizer/loader.php b/inc/customizer/loader.php index 605ad804d2..46f03fe1d9 100644 --- a/inc/customizer/loader.php +++ b/inc/customizer/loader.php @@ -144,6 +144,9 @@ public function enqueue_customizer_controls() { 'learnMore' => apply_filters( 'neve_external_link', 'https://docs.themeisle.com/article/1349-how-to-load-neve-fonts-locally', esc_html__( 'Learn more', 'neve' ) ), 'key' => Config::OPTION_LOCAL_GOOGLE_FONTS_HOSTING, ), + 'preloadFonts' => array( + 'key' => Config::MODS_PRELOAD_FONTS, + ), 'fontPairs' => get_theme_mod( Config::MODS_TPOGRAPHY_FONT_PAIRS, Config::$typography_default_pairs ), 'allowedGlobalCustomColor' => Colors_Background::CUSTOM_COLOR_LIMIT, 'constants' => [ @@ -291,6 +294,14 @@ public function register_setting_local_gf( $wp_customize ) { 'default' => false, ] ); + + $wp_customize->add_setting( + Config::MODS_PRELOAD_FONTS, + [ + 'sanitize_callback' => 'neve_sanitize_checkbox', + 'default' => false, + ] + ); } /** diff --git a/inc/views/font_manager.php b/inc/views/font_manager.php index cc9d8b36d3..46769b35d3 100644 --- a/inc/views/font_manager.php +++ b/inc/views/font_manager.php @@ -93,6 +93,7 @@ public function init() { add_action( 'enqueue_block_editor_assets', array( $this, 'register_google_fonts' ), 200 ); add_action( 'enqueue_block_editor_assets', array( $this, 'do_editor_styles_google_fonts' ), 210 ); add_action( 'wp_print_styles', array( $this, 'load_external_fonts_locally' ), PHP_INT_MAX ); + add_filter( 'style_loader_tag', array( $this, 'add_rel_preload' ), 10, 2 ); } /** @@ -251,6 +252,46 @@ private function enqueue_google_font( $font, $weights = [], $skip_enqueue = fals wp_enqueue_style( 'neve-google-font-' . str_replace( ' ', '-', strtolower( $font ) ), $url, array(), NEVE_VERSION ); } + /** + * Add onload, rel and as attributes for Google Font stylesheets. + * Implements lazy loading with preload for better performance. + * + * @param string $html Current html code. + * @param string $handle Current script handle. + * + * @return string + */ + public function add_rel_preload( $html, $handle ) { + if ( is_admin() ) { + return $html; + } + + $preload_enabled = get_theme_mod( Config::MODS_PRELOAD_FONTS, false ); + + /** + * Filters whether fonts should be preloaded. + * + * @param bool $preload_enabled Whether fonts should be preloaded. Default value is false. + * + * @since 3.9.0 + */ + $should_preload = apply_filters( 'neve_preload_fonts', $preload_enabled ); + + if ( ! (bool) $should_preload ) { + return $html; + } + + // Only preload Google Font stylesheets + if ( strpos( $handle, 'neve-google-font-' ) === 0 ) { + // Lazy load with JS, but also add noscript in case no JS + $no_script = ''; + // Add onload, rel="preload", as="style", and put together with noscript + $html = str_replace( 'rel=\'stylesheet\'', 'rel="preload" as="style" onload="this.rel=\'stylesheet\';"', $html ) . $no_script; + } + + return $html; + } + /** * Load Google Fonts locally. *