-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
In register_core_block_style_handles
store CSS files with relative path in transient
#5052
Conversation
…path in transient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @petitphp for the PR. Overall look solid to me. Left some feedback for consideration.
Co-authored-by: Mukesh Panchal <mukeshpanchal27@users.noreply.github.com>
Co-authored-by: Mukesh Panchal <mukeshpanchal27@users.noreply.github.com>
Thanks for the review and the suggestions @mukeshpanchal27 ! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @petitphp, this fix looks great to me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My approval was a bit too fast :)
The approach here overall is solid, but I found one thing that needs to be addressed and one minor performance recommendation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @petitphp for the update.
In line no. 31 could you please update code.
$core_blocks_meta = require ABSPATH . WPINC . '/blocks/blocks-json.php';
replace to
$core_blocks_meta = require BLOCKS_PATH . 'blocks-json.php';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petitphp Looks great now! One minor follow-up, but not a big deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this approach. The main thing we need to consider that has not yet been discussed is that the list of file paths will change between WP versions, which could cause breakage after an update. Furthermore, I think it would be safer for us to add an expiration time to this cache so a transient value that is corrupted for any reason would eventually expire and be rebuilt.
I also think we can restructure this a bit to remove some redundancy in the string replacing logic. Here's an example of what I'm thinking...
- Add the WP version to the transient name, so a change in WP versions would result in a cache miss.
- Add an expiry time of
DAY_IN_SECONDS
, which will allow this value to expire naturally. Setting an expiration will also result in this option not being autoload, which is probably ok. - Check dev mode before trying to retrieve the files from cache and again before setting the cache to avoid duplicated logic.
/*
* Ignore transient cache when the development mode is set to 'core'. Why? To avoid interfering with
* the core developer's workflow.
*/
$files = false;
if ( ! wp_is_development_mode( 'core' ) ) {
$transient_name = 'wp_core_block_css_files_' . $wp_version;
$files = get_transient( $transient_name );
// Ensure cached values use relative paths.
if ( is_array( $files ) && ! str_starts_with( reset( $files ), 'blocks/' ) ) {
$files = false;
}
}
if ( ! $files ) {
$files = glob( wp_normalize_path( __DIR__ . '/**/**.css' ) );
$files = array_map(
static function ( $file ) use ( $includes_path ) {
return str_replace( $includes_path, '', $file );
},
$files
);
}
// Save core block style paths in cache when not in development mode.
if ( ! wp_is_development_mode( 'core' ) ) {
set_transient( $transient_name, $files, DAY_IN_SECONDS );
}
What do you think?
@joemcgill Your additional feedback makes sense to me, except for:
I think we should autoload this transient because it's going to be used on pretty much every page load. Introducing a new database request for this on every page load will likely nullify, or certainly reduce the benefit of using a cache in the first place. By including the WordPress version in the cache key, we should have enough protections in place to not run into stale values, I think we should avoid an expiration. |
Ideally, I agree. I'm fine with omitting the expiration time for now. In the future, we could combine setting an expiration with also manually setting the autoload value once https://core.trac.wordpress.org/ticket/58964 is committed. |
@joemcgill I agree with your feedback, I completely overlooked the case where the paths changed. As @felixarntz said, It would be good to keep autoloading this transient. My main concern is that if we make the transient's name custom but don't add an expiration to the transient, this mean we'll keep autoloading all the previous versions of the transient in the future too since they will never be deleted. To have the best of both (correctly handle change of files between versions but don't clutter autoload options), we can store the WordPress's version alongside the paths to be able to invalidate the value when WordPress is updated : /*
* Ignore transient cache when the development mode is set to 'core'. Why? To avoid interfering with
* the core developer's workflow.
*/
$files = false;
if ( ! wp_is_development_mode( 'core' ) ) {
$transient_name = 'wp_core_block_css_files';
$cached_files = get_transient( $transient_name );
/*
* Check the validity of cached values.
* - Should match the current WordPress version
* - Should use relative paths for the files
*/
if ( is_array( $cached_files ) ) {
if ( ! isset( $cached_files['version'] || ! isset( $cached_files['files'] ) {
$files = false;
} elseif ( $cached_files['version'] !== $wp_version ) {
$files = false;
} elseif ( ! str_starts_with( reset( $cached_files['files'] ), 'blocks/' ) ) {
$files = false;
} else {
$files = $cached_files['files'];
}
}
}
if ( ! $files ) {
$files = glob( wp_normalize_path( __DIR__ . '/**/**.css' ) );
$files = array_map(
static function ( $file ) use ( $includes_path ) {
return str_replace( $includes_path, '', $file );
},
$files
);
// Save core block style paths in cache when not in development mode.
if ( ! wp_is_development_mode( 'core' ) ) {
set_transient(
$transient_name,
array(
'version' => $wp_version,
'files' => $files
)
);
}
} |
Completely agree, @petitphp. My original suggestion assumed these transients would expire. Saving the version along with the files makes a lot of sense to me. Alternately, we could save the In your example above, I think you could combine all of the |
…WordPress versions
@joemcgill @felixarntz I've push an update which integrate your feedbacks :
I kept the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, @petitphp! It looks good from my perspective.
src/wp-includes/blocks/index.php
Outdated
$cached_files = get_transient( $transient_name ); | ||
|
||
/* | ||
* Check the validity of cached values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Check the validity of cached values. | |
* Validate the transient cached values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I think the original reads a bit better here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @petitphp the updates look good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petitphp Tiny bit of follow up feedback, but this is otherwise good to commit.
Co-authored-by: Felix Arntz <felixarntz@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on more info and testing from David Smith in this comment, it seems we've overlooked one assumption here, and it's that __DIR__
in the glob function will return a path that includes the $includes_path
so it can be removed. However, if the files are symlinked, it appears this might not work as expected.
I think a safer, and more consistent thing for us to do is to replace all instances of $includes_path
and the __DIR__
in the glob with references to BLOCKS_PATH
, which would ensure all of these places are referencing the same path.
The diff would be something like this:
diff --git a/src/wp-includes/blocks/index.php b/src/wp-includes/blocks/index.php
index d4dfde75b3..6aaffef0f6 100644
--- a/src/wp-includes/blocks/index.php
+++ b/src/wp-includes/blocks/index.php
@@ -30,18 +30,17 @@ function register_core_block_style_handles() {
return;
}
- $includes_url = includes_url();
- $includes_path = ABSPATH . WPINC . '/';
- $suffix = wp_scripts_get_suffix();
- $wp_styles = wp_styles();
- $style_fields = array(
+ $includes_url = includes_url();
+ $suffix = wp_scripts_get_suffix();
+ $wp_styles = wp_styles();
+ $style_fields = array(
'style' => 'style',
'editorStyle' => 'editor',
);
static $core_blocks_meta;
if ( ! $core_blocks_meta ) {
- $core_blocks_meta = require $includes_path . 'blocks/blocks-json.php';
+ $core_blocks_meta = require BLOCKS_PATH . 'blocks-json.php';
}
$files = false;
@@ -68,10 +67,10 @@ function register_core_block_style_handles() {
}
if ( ! $files ) {
- $files = glob( wp_normalize_path( __DIR__ . '/**/**.css' ) );
+ $files = glob( wp_normalize_path( BLOCKS_PATH . '**/**.css' ) );
$files = array_map(
- static function ( $file ) use ( $includes_path ) {
- return str_replace( $includes_path, '', $file );
+ static function ( $file ) {
+ return str_replace( BLOCKS_PATH, '', $file );
},
$files
);
@@ -88,9 +87,9 @@ function register_core_block_style_handles() {
}
}
- $register_style = static function( $name, $filename, $style_handle ) use ( $includes_path, $includes_url, $suffix, $wp_styles, $files ) {
- $style_path = "blocks/{$name}/{$filename}{$suffix}.css";
- $path = wp_normalize_path( $includes_path . $style_path );
+ $register_style = static function( $name, $filename, $style_handle ) use ( $includes_url, $suffix, $wp_styles, $files ) {
+ $style_path = "{$name}/{$filename}{$suffix}.css";
+ $path = wp_normalize_path( BLOCKS_PATH . $style_path );
if ( ! in_array( $style_path, $files, true ) ) {
$wp_styles->add(
@joemcgill Thank you, I agree with your proposed path. Regarding the concrete diff, I think there's one problem with it which is that it still relies on This should be trivial to fix though. I would suggest we get rid of the |
Good catch. Yeah, we'll also need to update line 102, like so: diff --git a/src/wp-includes/blocks/index.php b/src/wp-includes/blocks/index.php
index 6aaffef0f6..270b2bb0a4 100644
--- a/src/wp-includes/blocks/index.php
+++ b/src/wp-includes/blocks/index.php
@@ -99,7 +99,7 @@ function register_core_block_style_handles() {
return;
}
- $wp_styles->add( $style_handle, $includes_url . $style_path );
+ $wp_styles->add( $style_handle, $includes_url . '/blocks/' . $style_path );
$wp_styles->add_data( $style_handle, 'path', $path );
$rtl_file = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $path ); |
Sorry @felixarntz. I missed this part of your suggestion. I think it would be fine to swap |
@joemcgill I'm wary of defining a new global constant |
src/wp-includes/blocks/index.php
Outdated
$files = glob( wp_normalize_path( __DIR__ . '/**/**.css' ) ); | ||
$files = array_map( | ||
static function ( $file ) use ( $includes_path ) { | ||
return str_replace( $includes_path, '', $file ); | ||
}, | ||
$files | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$files = glob( wp_normalize_path( __DIR__ . '/**/**.css' ) ); | |
$files = array_map( | |
static function ( $file ) use ( $includes_path ) { | |
return str_replace( $includes_path, '', $file ); | |
}, | |
$files | |
); | |
$raw_files = glob( wp_normalize_path( __DIR__ . '/**/**.css' ) ); | |
$files = array(); | |
foreach( $raw_files as $file ){ | |
$files[] = str_replace( $includes_path, '', $file ); | |
} |
This feels a little more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel strongly about this, but array_map
seems totally fine to me. It's used already in several places in core and is a syntax that is fairly common in the broader PHP ecosystem.
One nice side effect of this change is that we can also add file sizes as in the cache. This saves an expensive file_size check. I put together a POC petitphp#1. Something to explore later, but this is a good change. |
I've applied the suggestions from yesterday to a new PR here, which consistently uses |
Issue 59111 updates
Thank @joemcgill, I've merged your changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @petitphp. All blockers from my perspective are now resolved. Really appreciate you sticking with us through all the iterations!
Merged in r56524. |
This PR propose a solution to fix the ticket 59111.
This is loosely based on the second option suggested, this PR will do additional change to the CSS files paths before storing and after retrieving them in the transient. Paths stored in the transient doesn't contain the path to the
wp-includes
folder in the server.Trac ticket: https://core.trac.wordpress.org/ticket/59111
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.