-
Notifications
You must be signed in to change notification settings - Fork 147
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
Scripts and style are enqueued on pages lacking forms #1278
Comments
Actually, what I tested was the best case because this is without any of the integrations enabled (reCAPTCHA and Stripe). When those are also active, then the homepage includes yet more styles and scripts. In total: <link rel='stylesheet' id='wpcf7-stripe-css' href='http://localhost:10033/wp-content/plugins/contact-form-7/modules/stripe/style.css?ver=5.8' media='all' />
<link rel='stylesheet' id='contact-form-7-css' href='http://localhost:10033/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.8' media='all' />
...
<script src='http://localhost:10033/wp-content/plugins/contact-form-7/includes/swv/js/index.js?ver=5.8' id='swv-js'></script>
<script id='contact-form-7-js-extra'>
var wpcf7 = {"api":{"root":"http:\/\/localhost:10033\/wp-json\/","namespace":"contact-form-7\/v1"}};
</script>
<script src='http://localhost:10033/wp-content/plugins/contact-form-7/includes/js/index.js?ver=5.8' id='contact-form-7-js'></script>
<script src='http://localhost:10033/wp-includes/js/dist/vendor/wp-polyfill-inert.min.js?ver=3.1.2' id='wp-polyfill-inert-js'></script>
<script src='http://localhost:10033/wp-includes/js/dist/vendor/regenerator-runtime.min.js?ver=0.13.11' id='regenerator-runtime-js'></script>
<script src='http://localhost:10033/wp-includes/js/dist/vendor/wp-polyfill.min.js?ver=3.15.0' id='wp-polyfill-js'></script>
<script id='wpcf7-stripe-js-extra'>
var wpcf7_stripe = {"publishable_key":"foo"};
</script>
<script src='http://localhost:10033/wp-content/plugins/contact-form-7/modules/stripe/index.js?ver=5.8' id='wpcf7-stripe-js'></script>
<script src='https://www.google.com/recaptcha/api.js?render=foo&ver=3.0' id='google-recaptcha-js'></script>
<script id='wpcf7-recaptcha-js-extra'>
var wpcf7_recaptcha = {"sitekey":"foo","actions":{"homepage":"homepage","contactform":"contactform"}};
</script>
<script src='http://localhost:10033/wp-content/plugins/contact-form-7/modules/recaptcha/index.js?ver=5.8' id='wpcf7-recaptcha-js'></script> None of these scripts seem to be needed as, again, there are no contact forms on the page. And now re-running with the plugin active and the integrations enabled:
Here now the LCP-TTFB goes up to 76.7ms compared with the above results of 36.4ms when the plugin is deactivated. So the plugin increases TTFB-LCP from 40.1ms to 76.7ms, an increase of 36.4ms or ~2x. |
Out of curiosity, I modified an HTTP Archive query I had previously written which listed out all blocking BigQuery SQL# HTTP Archive query to get counts of theme/plugin scripts blocking in head.
#
# WPP Research, Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
CREATE TEMP FUNCTION GET_BLOCKING_HEAD_SOURCES (custom_metrics STRING) RETURNS ARRAY<STRING> LANGUAGE js AS '''
const sourceRegExp = new RegExp( '/wp-content/(?<type>plugin|theme)s/(?<slug>[^/]+)/(?<path>[^\?]+)' );
/**
* Get slug of extension prefixed by theme/plugin from URL.
*
* @param {string} src Script URL.
* @return {?{type: "plugin"|"theme", slug: string, path: string}} Source info if matched.
*/
function getSource(src) {
const matches = src.match( sourceRegExp );
if (matches) {
return matches.groups;
}
return null;
}
/**
* Get script sources for scripts in the head which are blocking (not async nor defer).
*
* @param {object} data
* @param {object} data.cms
* @param {object} data.cms.wordpress
* @param {Array<{src: string, intended_strategy: string, async: boolean, defer: boolean, in_footer: boolean}>} data.cms.wordpress.scripts
* @return {Array} Sources.
*/
function getBlockingHeadScriptSources(data) {
const sources = [];
for ( const script of data.cms.wordpress.scripts ) {
const source = getSource(script.src);
if (!source) {
continue;
}
sources.push( [ source.type, source.slug ].join( ':' ) );
sources.push( [ source.type, source.slug, source.path ].join( ':' ) );
}
return sources;
}
const sources = [];
try {
const data = JSON.parse(custom_metrics);
sources.push(...getBlockingHeadScriptSources(data));
} catch (e) {}
return sources;
''';
WITH all_sources AS (
SELECT
GET_BLOCKING_HEAD_SOURCES(custom_metrics) AS sources,
FROM
`httparchive.all.pages`,
UNNEST(technologies) AS technology
WHERE
date = CAST("2023-07-01" AS DATE)
AND technology.technology = "WordPress"
AND is_root_page = TRUE
)
SELECT
source,
COUNT(source) AS source_count
FROM
all_sources,
UNNEST(sources) AS source
GROUP BY
source
HAVING
source_count >= 10000
ORDER BY
source_count DESC I found that scripts from CF7 are the 4th most commonly-found in HTTP Archive, and that the specific scripts
Conditionally enqueueing these scripts based on whether a contact form is on the page should drastically reduce the impact that CF7 scripts have on JavaScript downloads across the web. |
Don't the Google recaptcha v3 scripts need to load on all pages for it to work properly? Isn't that how Google tells what is usual behaviour, by running on all pages for a site? |
Humm, apparently so:
I'm going to inquire further. |
@PhilMakower I've reverted the change to reCAPTCHA in #1279 via 9d8fee2. |
Site owners should know which pages on their site have a contact form, so we recommend that site owners themselves decide on which pages Contact Form 7's scripts are necessary. This is the surest way to control script loading. Your approach is indeed elegant and maybe works nicely on a vanilla WordPress install, but in reality, a plugin have to live in a complicated world with thousand of different plugins and themes. I think it would be difficult to work without causing conflicts. |
@takayukister I hope you might reconsider. Excessive JavaScript is one of the worst performance problems on the web today, as you also affirm it is wasteful for your plugin to add its JS and CSS to every page in your blog post. My concern about the instructions in your post is that most users are not developers: they won’t realize the negative performance impact of the extra scripts and they certainly won’t feel comfortable adding PHP code to improve their site’s performance. You have such a popular plugin that you have a unique opportunity to make a big impact on the health of the web. Your post says:
However, your scripts are already being printed in the footer. Therefore, is there actually a difficulty here? Also, whenever a script or stylesheet is enqueued after I can see an argument for not changing the behavior for enqueueing the stylesheet as I did in my PR, since moving a stylesheet to the footer could indeed cause compatibility problems with themes/plugins in regards to the CSS cascade. Otherwise, do you have any specific plugins and themes in which you anticipate there being a conflict? What if I reverted the changes to the stylesheet so that it continues printing in the |
My biggest concern about your PR is the use of the Do you think applying the |
How is my PR using the Nevertheless, it doesn't seem the change I made to |
OK, I reverted that change. See the latest diff from my branch (not visible in PR since closed). |
Since your plugin is already enqueueing your scripts in the footer (which is great) then this means adding |
Thank you for the clarification. I reopened this issue since the discussion is valuable. I'll add an action hook in the shortcode callback function or somewhere else to make it easy for add-on plugins to implement the same script loading control as you did in the PR. If there are real needs, someone will soon develop and release such an add-on. |
I'm confused. Your blog post shares a sentiment that the plugin's current behavior of adding its scripts to every page is "redundant or wasteful". Therefore, if there isn't actually a technical difficulty to conditionally enqueue the scripts, why not have it be done by default in the plugin as my PR implements? |
So at the end we will still need to customize this behaviour to load the assets manually in the various pages when needed instead of something from above that automatically inject the assets only when need it? I think that is more healthy if the website itself, with the various plugins, load the assets only when need it without any action by the user or the website developer. |
This problem just got a writeup in Just one of us after all? A closer look at Taylor Swift‘s new website because her site is using Contact Form 7:
|
I agree this a very important issue that needs to be considered in any change to Contact Form 7 (CF7). I recall clearly the 100's of support questions that happened when Contact Form 7 added reCAPTCHA v3. A small percentage of CF7 users immediately had new issues with form submission & this created an avalanche of support questions (with other users then piling on and adding to the avalanche). So how do you ensure this change does not cause new form submission issues in a complicated world with thousand of different plugins and themes (many of them badly written)? |
I noticed that as soon as I activate the plugin, scripts are added to every single page on the frontend, even on pages that lack any contact form. This is a performance problem. These are the scripts and styles in particular:
I used the benchmark-web-vitals command on a vanilla WordPress install (WP 6.3 with Twenty Twenty-Three active) without the plugin active and I got the following:
And I ran it again with the plugin active:
So the plugin activation on the homepage increases LCP-TTFB from 40.1 to 45.55, so a ~5ms increase or ~9%.
I suggest that the scripts and stylesheet only be enqueued when a form is actually printed to the page.
The text was updated successfully, but these errors were encountered: