ctf0 / laravel-mix-versionhash

Auto append hash to file instead of using virtual one
MIT License
61 stars 18 forks source link

/public/mix.*.js created when no mix.js() given #9

Closed wolfgang42 closed 4 years ago

wolfgang42 commented 5 years ago

I'm using Laravel Mix for SCSS compilation, but not JS. If I don't have any mix.js() calls in webpack.mix.json, I get a public/mix.08780b.js (though the hash seems to vary) with a blank webpackBootstrap boilerplate.

ctf0 commented 5 years ago

this is related to changing webpackConfig.output.filename, @jellycode @Tlapi do u have any suggestions for this ?

jellycode commented 5 years ago

I think we need to check the webpackConfig.entry to see if 'js' is called. If not, no need to change the output.filename?

ctf0 commented 5 years ago

actually if no js file is used, laravel-mix will add a default empty entry https://github.com/JeffreyWay/laravel-mix/blob/a57fcf7e5ecd8ca3a8294d92fad1905c700cd6f6/src/builder/WebpackConfig.js#L40-L42

https://github.com/JeffreyWay/laravel-mix/blob/a57fcf7e5ecd8ca3a8294d92fad1905c700cd6f6/src/builder/Entry.js#L76-L81

however am not sure why changing the output.filename have side effects.

Erutan409 commented 4 years ago

@ctf0 Has there been any headway on this?

ctf0 commented 4 years ago

sadly no :cry:

Erutan409 commented 4 years ago

I figured it out. Here's what's happening:

Laravel Mix does use a mock entry plugin that will test for the existence of an unnecessary mix.js file. That is, Laravel Mix, by default, doesn't actually change the file of the versioned asset, as it just suffixes it with a query string at the end.

When I changed the code, here, with the following:

class MockEntryPlugin {
    /**
     * Handle the deletion of the temporary mix.js
     * output file that was generated by webpack.
     *
     * This file is created when the user hasn't
     * requested any JavaScript compilation, but
     * webpack still requires an entry.
     *
     * @param {Object} compiler
     */
    apply(compiler) {
        compiler.plugin('done', stats => {
            let temporaryOutputFile = stats
                .toJson()
                .assets.find(asset => /^mix(?:\W.*?)?\.js$/i.test(asset.name));

            if (temporaryOutputFile) {
                delete stats.compilation.assets[temporaryOutputFile.name];

                File.find(
                    path.resolve(Config.publicPath, temporaryOutputFile.name)
                ).delete();
            }
        });
    }
}

module.exports = MockEntryPlugin;

The file is removed with your plugin. Notice the change in the .assets.find( ... ) logic. Since your plugin changes the name of mix.js into something hashed, the original code isn't finding that file.

You may need to add subsequent logic to look for this file as the code above is doing.

ctf0 commented 4 years ago

@Erutan409 can u make a PR for this ?

Erutan409 commented 4 years ago

@ctf0 I'd love to. I'd just need to figure out the best/elegant way to accomplish it without breaking @JeffreyWay's intended fluent API.

ctf0 commented 4 years ago

i was thinking of making it through the lib, so maybe check if the mix.js size is zero then delete it but of course it will add extra unnecessary time to the build :(

Erutan409 commented 4 years ago

@ctf0 I'll see what I can come up with. I have an idea that may work without going outside the intended extending.

ctf0 commented 4 years ago

@wolfgang42 can u check if the latest commit fix ur issue ?

wolfgang42 commented 4 years ago

Yes, I've just confirmed this problem is gone as of ca3a67c8076a6f70db0642cd42b5eed3d093e57a.