nystudio107 / craft-plugin-vite

Plugin Vite is the conduit between Craft CMS plugins and Vite, with manifest.json & HMR support
MIT License
12 stars 11 forks source link

Add support for Servd Bundle Hash #26

Closed mortscode closed 4 months ago

mortscode commented 5 months ago

Is your feature request related to a problem? Please describe.

The problem is that my site's caching (Servd & Cloudflare) creates a situation where the available css & js assets differ from the cached version of the manifest.json file. This renders the site without styles applied for a moment after deployment.

Servd's suggested approach to cache-busting assets is to append the SERVD_BUNDLE_HASH to the end of the asset file urls. I'd like to be able to accomplish this as it's described in their docs: https://servd.host/docs/cache-busting#using-the-bundle-hash

Describe the solution you would like

Provide a config option to append a string like ?v={{ getenv('SERVD_BUNDLE_HASH') }} to the end of the compiled assets on build.

Using rollupOptions.output in my vite.config file, I'm able to remove the Vite hash from the file name, which renders this in my site head:

<link href="https://my.ddev.site/dist/assets/app.css" rel="stylesheet">

My request is to append a string to the end of the href like so (assuming the SERVD_BUNDLE_HASH is "123456"):

<link href="https://my.ddev.site/dist/assets/app.css?v=123456" rel="stylesheet">

Describe alternatives you have considered

I've been blowing up the servd team ( @mattgrayisok & Joe ) on their intercom about configuring for Vite. The above article has 2 suggestions that would be problematic:

  1. Clear site cache on post-deploy: this would put a large load on our server every time i push code to production as Servd would be forced to re-cache the whole site
  2. Include historical copies of my assets: I don't think this is possible with Vite as the entire dist folder is wiped out on build
  3. In my vite.config.js, I removed the hash with the rollupOptions.output config:
    build: {
        [...]
        rollupOptions: {
            [...]
            output: {
                assetFileNames: `assets/[name].[ext]`,
                entryFileNames: `assets/[name].js`,
            },
        },
    },

    Then using Ben C's (@bencroker) cloudflare plugin, I'm attempting to purge the cache when the bundle is built, with the cloudflare/purge/purge-urls console command. Unfortunately, this is also not purging the css & js files as expected after a build.

Additional context

This Vite local setup absolutely rules and I'm committed to making it work somehow. I'm certainly open to other solutions if you have thoughts. Just looking to avoid the site rendering without styles & scripts.

mortscode commented 4 months ago

With the cloudflare purge not working as hoped, I'm going to attempt to manually add the scripts and styles to my staging and production environments with the string param. I've removed the hash from my vite config, and i'm adding it into the manual script & style injections like so:

{% if envIsDev %}
    {{ craft.vite.script("/app-ui/scripts/app.js", false) }}
{% else %}
    <script type="module" src="https://mysite.com/dist/assets/app.js?v={{ servdHash }}" crossorigin="" onload="e=new CustomEvent('vite-script-loaded', {detail:{path: 'app-ui/scripts/app.js?v={{ servdHash }}'}});document.dispatchEvent(e);"></script>
    <link href="https://mysite.com/dist/assets/app.css?v={{ servdHash }}" rel="stylesheet">
    <script src="https://mysite.com/dist/assets/app-legacy.js?v={{ servdHash }}" nomodule="" onload="e=new CustomEvent('vite-script-loaded', {detail:{path: 'app-ui/scripts/app-legacy.js?v={{ servdHash }}'}});document.dispatchEvent(e);"></script>
{% endif %}

~Presently working on production, seemingly just fine~. @khalwat do you see any potential issues with this approach?

Update:

This doesn't build correctly for some reason. It's like the new css isn't being compiled on build without that craft.vite.script present.

mortscode commented 4 months ago

Ok. We're back to the drawing board.

I put the hashes back on to the asset files and I'm using wildcards in cloudflare to purge the cache as a post-deploy task:

cloudflare/purge/purge-urls https://mysite.com/dist/assets/*.js,https://mysite.com/dist/assets/*.js.gz,https://mysite.com/dist/assets/*.css,https://mysite.com/dist/assets/*.css.gz,https://mysite.com/dist/manifest.json

I have yet to see a broken frontend after a build. I'll keep testing.

khalwat commented 4 months ago

So rather than modifying the Craft Vite plugin in some way, I think the right way to do this is to have your Vite build system bake the query string into the asset URLs in your manifest.json ala:

https://github.com/vitejs/vite/issues/5825#issuecomment-1084087519