How can I add the version number to the path using Laravel Mix?
Asked Answered
T

2

8

I am using Laravel Mix to compile my JS and CSS assets. I'm currently using .version() to achieve this.

The problem is that this produces a file similar to:

/css/app.css?id=03def6a69840076e8f29

That works fine when serving it locally, but if I'm using a CDN to serve this content via an origin pull then the query string doesn't force a new pull of the file. Ideally I'd like the following instead:

/css/03def6a69840076e8f29/app.css

Or:

/css/03def6a69840076e8f29.css

Both of these are different files, so it forces a pull on the CDN.

How can this be achieved with Laravel Mix?

Thor answered 25/6, 2018 at 14:24 Comment(1)
github.com/JeffreyWay/laravel-mix/issues/934Haymo
F
3

I had the same problem, and came up with the solution:

  1. Add the following line to public/.htaccess:

    RewriteRule ^assets/[a-f0-9]+/(.*)$ /$1 [L]

right before RewriteCond %{REQUEST_FILENAME} !-d

this will treat urls like /assets/ab7320d/css/whatever.css as /css/whatever.css

  1. Put the following code to resources/assets/js/rewriteMixManifest.js

    let fs = require('fs')
    let mixManifestPath = `${process.cwd()}/public/mix-manifest.json`
    let mixFileContents = fs.readFileSync(mixManifestPath)
    let oldMapping = JSON.parse(mixFileContents)
    function updateMapping(path) {
        if(path.indexOf("?") < 1) {
            return path
        }
        let [filename, idPart] = path.split("?")
        let [_, id] = idPart.split("=")
        return `/assets/${id}${filename}`
    }
    let newContent = {}
    for(let file in oldMapping) {
        newContent[file] = updateMapping(oldMapping[file])
    }
    console.log("Manifest rewritten.")
    fs.writeFileSync(mixManifestPath, JSON.stringify(newContent, null, 2))
    
  2. In package.json, add the following line in scripts (just like "dev" key)

    "rewrite-manifest": "node resources/assets/js/rewriteMixManifest.js",
    
  3. After each build (e.g. npm run production) also run npm run rewrite-manifest

So what public/mix-manifest.json file does is it maps each assets file (for {{ mix('css/app.css') }}) to some string that will actually go to HTML. My script rewrites the string to put version not to query string, but to the path. .htaccess makes sure the path is interpreted right.

The path structure is of course up to you to change to your liking

For me it solved the problem with Google Cloud CDN, hope it helps you too

Frozen answered 14/8, 2018 at 10:24 Comment(0)
G
-1

You can try calling the asset this way:

<link rel="stylesheet" type="text/css" href="{{ mix('css/app.css') }}">
Goshen answered 25/6, 2018 at 15:50 Comment(1)
That just outputs the app.css file with a version appended as a query string. I need it part of the path to allow for origin-pull CDNs.Thor

© 2022 - 2024 — McMap. All rights reserved.