Last active
December 21, 2024 19:55
-
-
Save doiftrue/d975646f41f218499866968a1a7dbf62 to your computer and use it in GitHub Desktop.
WP_Theme_Scripts_Styles - simple class to enqueue scripts and styles using config array.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
Theme_Scripts_Styles::init( theme_scripts_styles_callback(...), [ 'defer_all_scripts' => true ] ); | |
/** | |
* @see Theme_Scripts_Styles | |
* | |
* @return array{scripts:array, styles:array} | |
*/ | |
function theme_scripts_styles_callback(): array { | |
$styles = [ | |
'dashicons' => [ | |
'url' => site_url( $GLOBALS['wp_styles']->query('dashicons')->src ), | |
'ver' => $GLOBALS['wp_version'], | |
//'deps' => [ 'theme-styles' ], | |
'preload' => true, | |
], | |
'fonts' => [ | |
'url' => THEME_URL . ( $f = '/assets/fonts/roboto.font.css' ), | |
'ver' => filemtime( THEME_DIR . $f ), | |
'preload' => true, | |
], | |
'theme-styles' => [ | |
'url' => THEME_URL . ( $f = '/assets/styles/styles.min.css' ), | |
'ver' => filemtime( THEME_DIR . $f ), | |
'deps' => [ 'dashicons', 'fonts' ], // после dashicons | |
'preload' => true, | |
], | |
]; | |
$scripts = [ | |
'jquery' => [ | |
'url' => site_url( $GLOBALS['wp_scripts']->query('jquery-core')->src ), | |
'ver' => $GLOBALS['wp_scripts']->query('jquery-core')->ver, | |
], | |
'theme-scripts-libs' => [ | |
'url' => THEME_URL . ( $f = '/assets/js/scripts-libs.min.js' ), | |
'ver' => filemtime( THEME_DIR . $f ), | |
], | |
'alpine' => [ | |
'url' => THEME_URL . ( $f = '/assets/js/libs/alpinejs/alpine.min.js' ), | |
'ver' => filemtime( THEME_DIR . $f ), | |
'defer' => true, | |
], | |
'theme-scripts' => [ | |
'url' => THEME_URL . ( $f = '/assets/js/scripts.min.js' ), | |
'ver' => filemtime( THEME_DIR . $f ), | |
'deps' => [ 'jquery', 'theme-scripts-libs' ], | |
/* @javascript {object} kmjsdata */ | |
'localize' => [ | |
'kmjsdata' => [ | |
'spdelcook' => KILL_SAPE_COOKIE, | |
'jsl10n' => js_l10n_strings(), | |
] | |
], | |
], | |
]; | |
// jquery-ui-sortable | |
if( is_user_logged_in() ){ | |
$sortable = $GLOBALS['wp_scripts']->query('jquery-ui-sortable'); | |
$scripts[ 'jquery-ui-sortable' ] = [ | |
'url' => site_url( $sortable->src ), | |
'ver' => $GLOBALS['wp_version'], | |
'deps' => $sortable->deps, | |
]; | |
} | |
return [ | |
'scripts' => $scripts, | |
'styles' => $styles, | |
]; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$data_callback = function() { | |
return [ | |
'styles' => [ | |
'fonts' => [ | |
'url' => ASSETS_URL . ( $f = '/fonts/theme-fonts.css' ), | |
'ver' => filemtime( ASSETS_DIR . $f ), | |
'preload' => true, | |
'load_scope' => 'front,admin', // "admin", "front", "front,admin" | |
], | |
'theme-styles' => [ | |
'url' => ASSETS_URL . ( $f = '/scss/styles.min.css' ), | |
'ver' => filemtime( ASSETS_DIR . $f ), | |
'deps' => [], | |
'preload' => true, | |
], | |
], | |
'scripts' => [ | |
'theme-scripts-libs' => [ | |
'url' => ASSETS_URL . ( $f = '/js/scripts-libs.min.js' ), | |
'ver' => filemtime( ASSETS_DIR . $f ), | |
], | |
'theme-scripts' => [ | |
'url' => ASSETS_URL . ( $f = '/js/scripts.min.js' ), | |
'ver' => filemtime( ASSETS_DIR . $f ), | |
'deps' => [ 'theme-scripts-libs' ], | |
'localize' => [ | |
'globaljsdata' => [ | |
'spdelcook' => KILL_SAPE_COOKIE, | |
'jsl10n' => 'some data here...', | |
] | |
], | |
], | |
] | |
]; | |
}; | |
Theme_Scripts_Styles::init( $data_callback ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @author Kama (wp-kama.com) | |
* @see https://gist.github.com/doiftrue/d975646f41f218499866968a1a7dbf62 | |
* | |
* @version 2.4 | |
*/ | |
class Theme_Scripts_Styles { | |
/** | |
* Available parameters. | |
*/ | |
private static array $default_item_args = [ | |
'url' => '', | |
'ver' => '', | |
'deps' => [], | |
'load_scope' => 'front', // where to load asset: One of: "admin", "front", "front,admin" | |
'preload' => false, // bool | |
'prefetch' => false, // bool | |
'dns-prefetch' => false, // bool | |
'preconnect' => false, // bool | |
// js only | |
'async' => false, // bool | |
'defer' => false, // bool | |
'module' => false, // bool | |
/** | |
* Array of data to pass to {@see wp_localize_script()} | |
* The key becomes $object_name parameter and the value $i18n. | |
* Example: | |
* | |
* 'localize' => [ | |
* 'object_name' => [ | |
* 'hello' => 'Hallo Welt', | |
* ] | |
* ] | |
*/ | |
'localize' => [], | |
/** | |
* Array of data to render before script as json. | |
* Example: | |
* | |
* 'js_data' => [ | |
* 'object_name' => [ | |
* 'my_number' => 654, | |
* 'is_enabled' => true, | |
* 'my_value' => 'Hello', | |
* ] | |
* ] | |
*/ | |
'js_data' => [], | |
]; | |
private static array $opt; // init parameters | |
/** @var array{scripts:array, styles:array} */ | |
private static array $data; | |
/** @var callable */ | |
private static $data_callback; | |
/** | |
* @param callable $data_callback The callback whould return array{scripts:array, styles:array} | |
* @param array $options { | |
* @type bool $force_to_footer Default: true. | |
* } | |
*/ | |
public static function init( callable $data_callback, array $options = [] ): void { | |
self::$opt = $options + [ | |
'force_to_footer' => true, | |
'defer_all_scripts' => false, | |
]; | |
self::$data_callback = $data_callback; | |
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_scripts_styles' ], 99 ); | |
add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_scripts_styles' ], 99 ); | |
add_filter( 'script_loader_tag', [ __CLASS__, '_set_async_defer_attrs' ], 10, 2 ); | |
add_action( 'send_headers', [ __CLASS__, 'set_prefetch_headers__on_send_headers' ] ); | |
// all scripts to the footer | |
if( self::$opt['force_to_footer'] ){ | |
remove_action( 'wp_head', 'wp_print_head_scripts', 9 ); | |
} | |
// defer all scripts | |
if( self::$opt['defer_all_scripts'] && ! is_admin() ){ | |
add_filter( 'script_loader_tag', [ __CLASS__, 'defer_all_scripts' ], 20 ); | |
} | |
} | |
public static function defer_all_scripts( $tag ){ | |
if( ! preg_match( '/ type="module"|async |defer /', $tag ) ){ | |
return str_replace( ' src', ' defer src', $tag ); | |
} | |
return $tag; | |
} | |
private static function setup_data_once(): void { | |
if( isset( self::$data ) ){ | |
return; // already set | |
} | |
self::$data = ( self::$data_callback )(); | |
// fill defaults | |
self::$data['scripts'] = array_map( static fn( $dat ) => $dat + self::$default_item_args, self::$data['scripts'] ); | |
self::$data['styles'] = array_map( static fn( $dat ) => $dat + self::$default_item_args, self::$data['styles'] ); | |
// filter by load_scope | |
$cur_scope = is_admin() ? 'admin' : 'front'; | |
foreach( self::$data as $type => $type_data ){ | |
foreach( $type_data as $id => $item_data ){ | |
if( ! str_contains( $item_data['load_scope'], $cur_scope ) ){ | |
unset( self::$data[ $type ][ $id ] ); | |
} | |
} | |
} | |
} | |
public static function _set_async_defer_attrs( $tag, $id ) { | |
$data = self::$data['scripts'][ $id ] ?? null; | |
if( $data ){ | |
$data['module'] && $tag = str_replace( ' src', ' type="module" src', $tag ); | |
$data['async'] && $tag = str_replace( ' src', ' async src', $tag ); | |
$data['defer'] && $tag = str_replace( ' src', ' defer src', $tag ); | |
} | |
return $tag; | |
} | |
public static function set_prefetch_headers__on_send_headers(): void { | |
if( is_feed() || is_robots() ){ | |
return; | |
} | |
self::setup_data_once(); | |
foreach( self::$data['styles'] as $data ){ | |
self::add_prefetch_headers( $data, 'style' ); | |
} | |
foreach( self::$data['scripts'] as $data ){ | |
self::add_prefetch_headers( $data, 'script' ); | |
} | |
} | |
/** | |
* DOCS: https://html.spec.whatwg.org/#linkTypes | |
* DOCS: https://html.spec.whatwg.org/#link-type-preload | |
*/ | |
private static function add_prefetch_headers( $data, $type ): void { | |
$home_url = rtrim( home_url(), '/' ); | |
$url = str_starts_with( $data['url'], $home_url ) | |
? wp_make_link_relative( $data['url'] ) | |
: $data['url']; | |
if( $data['ver'] ){ | |
$url .= "?ver={$data['ver']}"; | |
} | |
if( $data['dns-prefetch'] ){ | |
header( "Link: <$url>; rel=dns-prefetch;", false ); | |
} | |
elseif( $data['prefetch'] ){ | |
header( "Link: <$url>; rel=prefetch;", false ); | |
} | |
elseif( $data['preconnect'] ){ | |
header( "Link: <$url>; rel=preconnect;", false ); | |
} | |
// DOCS: https://www.w3.org/TR/preload/ | |
elseif( $data['preload'] ){ | |
header( "Link: <$url>; rel=preload; as=$type", false ); | |
} | |
} | |
public static function enqueue_scripts_styles(): void { | |
self::setup_data_once(); | |
// scripts | |
foreach( self::$data['scripts'] as $id => $dat ){ | |
wp_deregister_script( $id ); // remove if registered | |
wp_enqueue_script( $id, $dat['url'], ( $dat['deps'] ?? [] ), $dat['ver'], true ); | |
if( $dat['localize'] ){ | |
foreach( $dat['localize'] as $obj_name => $l10n ){ | |
wp_localize_script( $id, $obj_name, $l10n ); | |
} | |
} | |
if( $dat['js_data'] ){ | |
foreach( $dat['js_data'] as $obj_name => $js_data ){ | |
wp_add_inline_script( $id, "window.$obj_name = " . wp_json_encode( $js_data ), 'before' ); | |
} | |
} | |
} | |
// styles | |
foreach( self::$data['styles'] as $id => $dat ){ | |
wp_deregister_style( $id ); // remove if registered | |
wp_enqueue_style( $id, $dat['url'], ( $dat['deps'] ?? [] ), $dat['ver'] ); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment