Skip to content
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

[5.x] Prevent multiple invocations of the {{ vite }} tag to eliminate asset duplication #11298

Open
wants to merge 1 commit into
base: 5.x
Choose a base branch
from

Conversation

JoshSalway
Copy link

Description

This PR addresses the issue of duplicate CSS and JS asset links in the generated index.html caused by multiple invocations of the {{ vite }} tag during the Static Site Generation (SSG) process. By introducing a static flag within the Vite tag class, the {{ vite }} tag is now rendered only once per request, effectively eliminating redundant <link> and <script> tags.

Problem

Previously, the {{ vite }} tag was being called multiple times (approximately 10 times) during the SSG process. This resulted in duplicated CSS and JS asset links in the index.html file for every generated page. Such duplication can lead to increased page load times, redundant asset fetching, and potential conflicts in script execution.

Solution

  • Introduced a Static Flag:

    • Added a private static $hasRendered property initialized to false to track whether the {{ vite }} tag has already been rendered.
  • Modified the index() Method:

    • Implemented a check at the beginning of the index() method to determine if the {{ vite }} tag has been rendered previously.
    • If self::$hasRendered is true, the method returns an empty string, preventing further rendering of asset links.
    • After the first render, self::$hasRendered is set to true to block subsequent invocations.
  • Enhanced Logging:

    • Added Log::info('Vite tag called with src: ' . implode(', ', $src)); to monitor the invocation of the {{ vite }} tag and ensure it is called only once.

Benefits
Performance Improvement:
Eliminates redundant asset loading by ensuring each CSS and JS file is linked only once, reducing page load times and bandwidth usage.

Maintainability:
Simplifies asset management within the SSG process, making the codebase cleaner and easier to maintain.

Debugging Ease:
Enhanced logging provides clear insights into the invocation of the {{ vite }} tag, facilitating easier troubleshooting in the future.

Testing

Add Logging for debugging purposes:
Log::info('Vite tag called with src: ' . implode(', ', $src));

Build Assets:
npm run build

Generate Static Site:
php please ssg:generate

Verify Logs:

Open storage/logs/laravel.log.

Ensure that the Vite tag is called only once:

[2024-12-21 15:52:56] local.INFO: Vite tag called with src: resources/css/site.css, resources/js/site.js

Inspect index.html:

Navigate to storage/app/static/index.html.
Confirm the absence of duplicated and <script> tags (may be unrelated):

<link rel="preload" as="style" href="https://yourdomain.com/build/assets/site-DWDe1f42.css" />
<link rel="modulepreload" href="https://yourdomain.com/build/assets/site-CNdXaVfx.js" />
<link rel="stylesheet" href="https://yourdomain.com/build/assets/site-DWDe1f42.css" data-navigate-track="reload" />
<script type="module" src="https://yourdomain.com/build/assets/site-CNdXaVfx.js" data-navigate-track="reload"></script>

Possible related issues:
https://github.com/statamic/cms/issues/11295

…that the `{{ vite }}` tag is rendered only once per request. This change prevents the tag from being invoked multiple times during the Static Site Generation (SSG) process, thereby eliminating duplicate `<link>` and `<script>` tags in the generated `index.html`.

### Changes Made:
- Introduced a `private static $hasRendered` property initialized to `false`.
- Modified the `index()` method to check the `$hasRendered` flag before rendering assets.
  - If `$hasRendered` is `true`, the method returns an empty string, preventing further rendering.
  - After the first render, `$hasRendered` is set to `true` to block subsequent invocations.
- Added logging to confirm that the `{{ vite }}` tag is called only once.

### Benefits:
- **Performance Improvement:** Reduces redundant asset loading by eliminating duplicate asset links.
- **Maintainability:** Ensures a cleaner and more efficient asset management process within the SSG.
- **Debugging Ease:** Maintains logging for monitoring the invocation of the `{{ vite }}` tag.

### Testing:
- Ran `npm run build` to compile assets.
- Executed `php please ssg:generate` to generate the static site.
- Verified `laravel.log` to ensure the `Vite` tag is called only once.
- Inspected `storage/app/static/index.html` to confirm the absence of duplicated asset links.
- Please use Log::info('Vite tag called with src: ' . implode(', ', $src)); to log the duplication.
@ryanmitchell
Copy link
Contributor

ryanmitchell commented Dec 23, 2024

As it stands this will break sites where the tag is used multiple times with different src values. Eg one for css once for js.

@duncanmcclean duncanmcclean changed the title fix: prevent multiple invocations of the {{ vite }} tag to eliminate asset duplication [5.x] prevent multiple invocations of the {{ vite }} tag to eliminate asset duplication Dec 23, 2024
@duncanmcclean duncanmcclean changed the title [5.x] prevent multiple invocations of the {{ vite }} tag to eliminate asset duplication [5.x] Prevent multiple invocations of the {{ vite }} tag to eliminate asset duplication Dec 23, 2024
@JoshSalway
Copy link
Author

A sit stand this will break sites where the tag is used multiple times with different src values. Eg one for css once for js.

Perhaps there is a better way to implement the change if there is only 2 files it shouldn't get called 10 times.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants