question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature request - 'mix()' function for javascript

See original GitHub issue

Issue: There are situations in a project where I need to reference a versioned file in a javascript file. I could of course get the mix-manifest.json file contents and print that to the page as a javascript object, then on the client side I could lookup the correct versioned path but this is a bit messy.

Solution: It would be nicer if perhaps there was a function like laravel’s mix() function but for javascript. Perhaps something like below:

//laravel-mix.js
window.laravelMix = function($assetUrl) {
  var json = require('../../../public/mix-manifest.json');
  for (var prop in json) if($assetUrl == prop) return json[prop];
  return $assetUrl;
};

// Usage
laravelMix('/css/base.css'); // OUTPUTS: /css/base.fdsa89f0dsa890fdsa890.css
// webpack.mix.js
mix.js('resources/assets/js/laravel-mix.js', 'public/js/laravel-mix.js')

Unfortunately this won’t work as laravel-mix.js requires mix-manifest.json before mix-manifest.json is updated meaning its contents is outdated.

Alternatively, perhaps creating a webpack plugin that transforms the paths to versioned paths would be better. Unfortunately I’m not that good with webpack so I wouldn’t know how to do this.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5

github_iconTop GitHub Comments

19reactions
jurridcommented, May 18, 2017

We would also like to have mix function in javascript. We have the same issue that we need a versioned file in a javascript file. It would be very nice to have it!

5reactions
fureycommented, Jul 24, 2019

Hi! 👋

Long time Laravel Project user; first time Stand-Alone Project user.

I just built a non-Laravel SPA that used Mix’s versioning and hmr features.

I implemented my own JavaScript mix() helper by porting Laravel’s Illuminate\Foundation\Mix class from PHP to JavaScript, then compiling it into my HTML template via lodash.template each time Mix dispatches a build event.

Here’s my simplified HTML template…

<!-- ./src/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="<%= mix('css/app.css') %>">
</head>
<body>
    <div id="app"></div>
    <script src="<%= mix('js/app.js') %>"></script>
</body>
</html>

Here’s my partial webpack.mix.js file, with version() toggle and build event listener…

// ./webpack.mix.js

const fs = require('fs');
const path = require('path');
const mix = require('laravel-mix');
const mixHelper = require('./mixHelper.js');
const template = require('lodash.template'); // "npm i lodash.template --save-dev"

// …etc…

if (mix.inProduction()) {
    mix.version();
}

Mix.listen('build', () => {
    const inputPath = path.join(__dirname, 'src/index.html');
    const outputPath = path.join(__dirname, 'dist/index.html');
    const inputString = fs.readFileSync(inputPath, 'utf-8');
    const compiled = template(inputString);
    const outputString = compiled({ mix: mixHelper });
    fs.writeFileSync(outputPath, outputString);
});

Here’s my JavaScript mix() helper, ported from Laravel’s PHP Mix class…

// ./mixHelper.js

const fs = require('fs');
const path = require('path');
const $manifests = {};

module.exports = function($path, $manifestDirectory = '') {
    if (! $path.startsWith('/')) {
        $path = `/${$path}`;
    }

    if ($manifestDirectory && ! $manifestDirectory.startsWith('/')) {
        $manifestDirectory = `/${$manifestDirectory}`;
    }

    const $hotPath = path.join(__dirname, Config.publicPath, 'hot');
    
    if (fs.existsSync($hotPath)) {
        const $url = fs.readFileSync($hotPath, 'utf-8').trimEnd();

        if ($url.startsWith('http://') || $url.startsWith('https://')) {
            return $url.slice($url.indexOf(':') + 1) + $path;
        }

        return `//localhost:8080${$path}`;
    }

    const $manifestPath = path.join(__dirname, Config.publicPath, $manifestDirectory, 'mix-manifest.json');

    if (! $manifests[$manifestPath]) {
        if (! fs.existsSync($manifestPath)) {
            throw Error('The Mix manifest does not exist.');
        }

        $manifests[$manifestPath] = require($manifestPath);
    }

    const $manifest = $manifests[$manifestPath];

    if (! $manifest[$path]) {
        throw Error(`Unable to locate Mix file: ${$path}.`);
    }

    return $manifestDirectory + $manifest[$path];
};

With my JavaScript mix() helper implemented, running the following npm commands produce the resulting HTML template output…

npm run dev, npm run watch, etc

<!-- ./dist/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="/css/app.css">
</head>
<body>
    <div id="app"></div>
    <script src="/js/app.js"></script>
</body>
</html>

npm run prod

<!-- ./dist/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="/css/app.css?id=1a05221a819af3149e65">
</head>
<body>
    <div id="app"></div>
    <script src="/js/app.js?id=d80a9ad8e827bafc2594"></script>
</body>
</html>

npm run hot

<!-- ./dist/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="//localhost:8080//css/app.css">
</head>
<body>
    <div id="app"></div>
    <script src="//localhost:8080//js/app.js"></script>
</body>
</html>

I hope this approach helps others looking for a similar end result.

Cheers!

🤓👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Feature request - 'mix()' function for javascript · Issue #740
I implemented my own JavaScript mix() helper by porting Laravel's Illuminate\Foundation\Mix class from PHP to JavaScript, then compiling it into ...
Read more >
JavaScript | Laravel Mix Documentation
With a single line of code, Laravel Mix allows you to trigger a number of vital ... Extract vendor libraries (via mix.extract() ),...
Read more >
Mixins - The Modern JavaScript Tutorial
The mixin will provide a method .trigger(name, [...data]) to “generate an event” when something important happens to it. · Also the method .on( ......
Read more >
Mix Razor and Javascript code - Stack Overflow
This is the best and simplest solution. Definitely need to feed the encoded JSON through Html.Raw() to get rid of the " entities....
Read more >
JavaScript best practices - W3C Wiki
One trap to avoid is marrying values and functionality in names. A function called isLegalDrinkingAge() makes more sense than isOverEighteen() as the legal ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found