Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Revert "Performance: Cache script data in a transient for production builds" #10509

Merged
merged 3 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .wp-env.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"core": null,
"core": "WordPress/WordPress#6.2.2",
"plugins": [
"https://downloads.wordpress.org/plugin/woocommerce.latest-stable.zip",
"https://github.com/WP-API/Basic-Auth/archive/master.zip",
Expand Down
147 changes: 22 additions & 125 deletions src/Assets/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,6 @@ class Api {
*/
private $inline_scripts = [];

/**
* Determines if caching is enabled for script data.
*
* @var boolean
*/
private $disable_cache = false;

/**
* Stores loaded script data for the current request
*
* @var array|null
*/
private $script_data = null;

/**
* Stores the hash for the script data, made up of the site url, plugin version and package path.
*
* @var string
*/
private $script_data_hash;

/**
* Stores the transient key used to cache the script data. This will change if the site is accessed via HTTPS or HTTP.
*
* @var string
*/
private $script_data_transient_key = 'woocommerce_blocks_asset_api_script_data';

/**
* Reference to the Package instance
*
Expand All @@ -59,18 +31,7 @@ class Api {
* @param Package $package An instance of Package.
*/
public function __construct( Package $package ) {
$this->package = $package;
$this->disable_cache = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) || ! $this->package->feature()->is_production_environment();

// If the site is accessed via HTTPS, change the transient key. This is to prevent the script URLs being cached
// with the first scheme they are accessed on after cache expiry.
if ( is_ssl() ) {
$this->script_data_transient_key .= '_ssl';
}
if ( ! $this->disable_cache ) {
$this->script_data_hash = $this->get_script_data_hash();
}
add_action( 'shutdown', array( $this, 'update_script_data_cache' ), 20 );
$this->package = $package;
}

/**
Expand Down Expand Up @@ -115,64 +76,6 @@ public function get_block_metadata_path( $block_name, $path = '' ) {
return $path_to_metadata_from_plugin_root;
}

/**
* Generates a hash containing the site url, plugin version and package path.
*
* Moving the plugin, changing the version, or changing the site url will result in a new hash and the cache will be invalidated.
*
* @return string The generated hash.
*/
private function get_script_data_hash() {
return md5( get_option( 'siteurl', '' ) . $this->package->get_version() . $this->package->get_path() );
}

/**
* Initialize and load cached script data from the transient cache.
*
* @return array
*/
private function get_cached_script_data() {
if ( $this->disable_cache ) {
return [];
}

$transient_value = json_decode( (string) get_transient( $this->script_data_transient_key ), true );

if (
json_last_error() !== JSON_ERROR_NONE ||
empty( $transient_value ) ||
empty( $transient_value['script_data'] ) ||
empty( $transient_value['version'] ) ||
$transient_value['version'] !== $this->package->get_version() ||
empty( $transient_value['hash'] ) ||
$transient_value['hash'] !== $this->script_data_hash
) {
return [];
}

return (array) ( $transient_value['script_data'] ?? [] );
}

/**
* Store all cached script data in the transient cache.
*/
public function update_script_data_cache() {
if ( is_null( $this->script_data ) || $this->disable_cache ) {
return;
}
set_transient(
$this->script_data_transient_key,
wp_json_encode(
array(
'script_data' => $this->script_data,
'version' => $this->package->get_version(),
'hash' => $this->script_data_hash,
)
),
DAY_IN_SECONDS * 30
);
}

/**
* Get src, version and dependencies given a script relative src.
*
Expand All @@ -182,37 +85,31 @@ public function update_script_data_cache() {
* @return array src, version and dependencies of the script.
*/
public function get_script_data( $relative_src, $dependencies = [] ) {
if ( ! $relative_src ) {
return array(
'src' => '',
'version' => '1',
'dependencies' => $dependencies,
);
}

if ( is_null( $this->script_data ) ) {
$this->script_data = $this->get_cached_script_data();
}

if ( empty( $this->script_data[ $relative_src ] ) ) {
$asset_path = $this->package->get_path( str_replace( '.js', '.asset.php', $relative_src ) );
// The following require is safe because we are checking if the file exists and it is not a user input.
// nosemgrep audit.php.lang.security.file.inclusion-arg.
$asset = file_exists( $asset_path ) ? require $asset_path : [];
$src = '';
$version = '1';

$this->script_data[ $relative_src ] = array(
'src' => $this->get_asset_url( $relative_src ),
'version' => ! empty( $asset['version'] ) ? $asset['version'] : $this->get_file_version( $relative_src ),
'dependencies' => ! empty( $asset['dependencies'] ) ? $asset['dependencies'] : [],
if ( $relative_src ) {
$src = $this->get_asset_url( $relative_src );
$asset_path = $this->package->get_path(
str_replace( '.js', '.asset.php', $relative_src )
);

if ( file_exists( $asset_path ) ) {
// The following require is safe because we are checking if the file exists and it is not a user input.
// nosemgrep audit.php.lang.security.file.inclusion-arg.
$asset = require $asset_path;
$dependencies = isset( $asset['dependencies'] ) ? array_merge( $asset['dependencies'], $dependencies ) : $dependencies;
$version = ! empty( $asset['version'] ) ? $asset['version'] : $this->get_file_version( $relative_src );
} else {
$version = $this->get_file_version( $relative_src );
}
}

// Return asset details as well as the requested dependencies array.
return [
'src' => $this->script_data[ $relative_src ]['src'],
'version' => $this->script_data[ $relative_src ]['version'],
'dependencies' => array_merge( $this->script_data[ $relative_src ]['dependencies'], $dependencies ),
];
return array(
'src' => $src,
'version' => $version,
'dependencies' => $dependencies,
);
}

/**
Expand Down