Update. Instead of using filters (excerpt_more, the_content_more_link, or the_excerpt), I use preg_replace to render_block_core/post-excerpt. This replaces the text as expected. Hope this helps those who may have the same problem.
function custom_search_read_more_text( $block_content ) {
if ( is_search() ) {
global $post;
if ( 'product' === get_post_type( $post ) ) {
$block_content = preg_replace( '/(><a[^>]*>)Read more(<\/a>)/i', '$1' . 'View Product' . '$2', $block_content );
}
}
return $block_content;
}
add_filter( 'render_block_core/post-excerpt', 'custom_search_read_more_text' );