node -v): v6.10.3npm -v): 3.10.10mix.version() is not generating hashed URL's for my assets
in my webpack.mix.js I have:
if (mix.inProduction()) {
console.log("We are in production");
mix.version(['public/js/app.js', 'public/css/app.css']);
}
the console log gets triggered just fine, but there are no hashes appended to my stylesheet or js file, which I'm loading in my views like so:
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
the output is the following without cache busting:
<link href="/css/app.css" rel="stylesheet">
the mix-manifest.json file looks like this
{
"/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css",
"/js/app.js.map": "/js/app.js.map",
"/css/app.css.map": "/css/app.css.map"
}
UPDATE: this seems to be working locally on my machine, but not on my CentOS server. I've set permissions to 777 on the mix-manifest.json file, but that doesn't solve the issue. I'm thinking this might be permission related? Are there any other files that mix needs to be able to write to while running the build in order to update the mix-manifest file?
not working toooo..........
Same error here, I had to implement my own solution for this
+1
Exact same issue here
me, too................
Can the rest of you confirm your OS? I'm having trouble reproducing, so I agree that it's probably a permissions issue.
Actually I first thought that the version was still being appended to the filename and after reviewing the master branch history I figured the version is now inside mix-manifest.json, which I should have opened sooner, in a commit that reads "refactoring"...
Anyways, in my case it was a big confusion (albeit the fact I didn't find a doc telling me how the versioning works...)
In case you guys want to use a temparary PHP script solution, check this https://github.com/JeffreyWay/laravel-mix/issues/1161
It would be awesome to opt in to the 'old' way of versioning if needed (i.e. filename versioning instead of query-string versioning). Is this functionality something you'd consider supporting in Laravel Mix?
One example use-case is that I use S3/CDNs and load-balancing on my site. I require that an old version of a file still remains on the CDN (S3) while the new version is uploaded/exists. An example scenario: I've very recently deployed a new release for my webapp - with some newly compiled javascript/css. While this release is being deployed to all the servers behind load balancers, someone requests a webpage. The load balancer then serves up the HTML from an old server via the load balancer that hasn't yet been updated with the latest release (and the new javascript version for app.js). With filename versioning, this isn't an issue, because this old server is using the old mix-manifest.js with the old version-hashed filename (e.g. app.abc123.js). So, the browser ends up correctly downloading the old file (app.abc123.js). Concurrently, other website visitors are hitting the servers with the latest release (via the load-balancer), and therefore being told to download the new javascript file from S3 (app.def456.js). All is well here...
Unfortunately, with query string versioning, requesting app.js?id=def456 and app.js?id=abc123.js from S3 will return the same file - the new one (version def456), and so the webapp breaks. 😩
This is just one scenario, but if not convinced, I can try explain another. I don't think there's a _right_ way to version it per se, more just that in certain circumstances, file versioning is preferred over querystring versioning.
Thoughts?
Apologies - when I said the "old way of versioning", I'm not sure that way ever actually existed, but still, it would be great.
Oh and just noticed that there's already a ticket re: filebased versioning for load balancers: #1022
I can confirm, this issue is still not fixed
same problem
I found out that the mix configuration parameter "inProduction" has been rename to "production". I'm using the below code for versioning.
if (mix.config.production) {
mix.version();
}
The final JS file with hash mappings are stored in the mix-manifest.json file.
same issue. Does anyone solve this problem?
For me, it seems like my versioned resources (with the querystring - the old filenames worked better) are sometimes pointing to old envoyer mix files in the releases directory rather than pointing to my latest deploy.
Anyone have any issues like this?
I've noticed that that problem comes when I use .combine() or .scripts() method after .js(). Laravel mix creates first banch of scripts versioned using .js(), but when I tried to concatenate them with other script
using .combine() and make them versioned, the problem shows.
This worked for me (version "laravel-mix": "0.*"):
if (mix.config.inProduction) {
mix.version();
}
I was confused for a while that version 0.* changed the file names, so in the console it was evident the versioning worked.
Then I updated laravel-mix to v2.* and @allentcm solution above worked just fine — only you don't visually see that it's versioned from the console; you have to look in mix-manifest.json to find the versioned query param.
Seems to be a fairly old thread now but I had the same issue and I managed to fix it by updating node_modules/laravel-mix/src/config.js.
I changed the versioning property from false to true, added mix.version() to my webpack.mix.js file, then everything worked as expected 🕺
_The versioning property has been removed from Laravel 5.6 onward, I must have been using an old version of Laravel when I posted this._
@olicarter
I changed the versioning property from false to true
Where did you find it ? I opened node_modules/laravel-mix/src/config.js. but could not find a versioning property
Seems to be a fairly old thread now but I had the same issue and I managed to fix it by updating node_modules/laravel-mix/src/config.js.
I changed the versioning property from false to true, added mix.version() to my webpack.mix.js file, then everything worked as expected 🕺
There's no versioning property inside node_modules/laravel-mix/src/config.js file
let paths = new (require('./Paths'))();
let webpackMerge = require('webpack-merge');
module.exports = function() {
return {
/**
* Determine if webpack should be triggered in a production environment.
*
* @type {Boolean}
*/
production:
process.env.NODE_ENV === 'production' ||
process.argv.includes('-p'),
/**
* A list of custom assets that are being compiled outside of Webpack.
*
* @type {Array}
*/
customAssets: [],
/**
* Determine if we should enable hot reloading.
*
* @type {Boolean}
*/
hmr: process.argv.includes('--hot'),
/**
* Hostname and port used for the hot reload module
*
* @type {Object}
*/
hmrOptions: {
host: 'localhost',
port: '8080'
},
/**
* PostCSS plugins to be applied to compiled CSS.
*
* See: https://github.com/postcss/postcss/blob/master/docs/plugins.md
*
* @type {Array}
*/
postCss: [],
/**
* Determine if we should enable autoprefixer by default.
*
* @type {Boolean}
*/
autoprefixer: {
enabled: true,
options: {}
},
/**
* Determine if Mix should remove unused selectors from your CSS bundle.
* You may provide a boolean, or object for the Purify plugin.
*
* https://github.com/webpack-contrib/purifycss-webpack#options
*
* @type {Boolean|object}
*/
purifyCss: false,
/**
* The public path for the build.
*
* @type {String}
*/
publicPath: '',
/**
* Determine if error notifications should be displayed for each build.
*
* @type {Boolean}
*/
notifications: {
onSuccess: true,
onFailure: true
},
/**
* Determine if sourcemaps should be created for the build.
*
* @type {Boolean}
*/
sourcemaps: false,
/**
* The resource root for the build.
*
* @type {String}
*/
resourceRoot: '/',
/**
* vue-loader specific options.
*
* @type {Object}
*/
vue: {
preLoaders: {},
postLoaders: {},
esModule: false
},
/**
* Image Loader defaults.
* See: https://github.com/thetalecrafter/img-loader#options
*
* @type {Object}
*/
imgLoaderOptions: {
enabled: true,
gifsicle: {},
mozjpeg: {},
optipng: {},
svgo: {}
},
/**
* File Loader directory defaults.
*
* @type {Object}
*/
fileLoaderDirs: {
images: 'images',
fonts: 'fonts'
},
/**
* The default Babel configuration.
*
* @type {Object}
*/
babel: function() {
let options = {};
tap(Mix.paths.root('.babelrc'), babelrc => {
if (File.exists(babelrc)) {
options = JSON.parse(File.find(babelrc).read());
}
});
if (this.babelConfig) {
options = webpackMerge.smart(options, this.babelConfig);
}
return webpackMerge.smart(
{
cacheDirectory: true,
presets: [
[
'env',
{
modules: false,
targets: {
browsers: ['> 2%'],
uglify: true
}
}
]
],
plugins: [
'transform-object-rest-spread',
[
'transform-runtime',
{
polyfill: false,
helpers: false
}
]
]
},
options
);
},
/**
* Determine if CSS url()s should be processed by Webpack.
*
* @type {Boolean}
*/
processCssUrls: true,
/**
* Whether to extract .vue component styles into a dedicated file.
* You may provide a boolean, or a dedicated path to extract to.
*
* @type {Boolean|string}
*/
extractVueStyles: false,
/**
* File with global styles to be imported in every component.
*
* See: https://vue-loader.vuejs.org/en/configurations/pre-processors.html#loading-a-global-settings-file
*
* @type {string}
*/
globalVueStyles: '',
/**
* Uglify-specific settings for Webpack.
*
* See: https://github.com/mishoo/UglifyJS2#compressor-options
*
* @type {Object}
*/
uglify: {
sourceMap: true,
uglifyOptions: {
compress: {
warnings: false
},
output: {
comments: false
}
}
},
/**
* CleanCss-specific settings for Webpack.
*
* See: https://github.com/jakubpawlowicz/clean-css#constructor-options
*
* @type {Object}
*/
cleanCss: {},
/**
* Custom Webpack-specific configuration to merge/override Mix's.
*
* @type {Object}
*/
webpackConfig: {},
/**
* Custom Babel configuration to be merged with Mix's defaults.
*
* @type {Object}
*/
babelConfig: {},
/**
* Determine if Mix should ask the friendly errors plugin to
* clear the console before outputting the results or not.
*
* https://github.com/geowarin/friendly-errors-webpack-plugin#options
*
* @type {Boolean}
*/
clearConsole: true,
/**
* Merge the given options with the current defaults.
*
* @param {object} options
*/
merge(options) {
let mergeWith = require('lodash').mergeWith;
mergeWith(this, options, (objValue, srcValue) => {
if (Array.isArray(objValue)) {
return objValue.concat(srcValue);
}
});
}
};
};
This issue is still not resolved
mix.version(); doesn't do anything
Apologies for the late response. I did some digging and turns out the versioning property was removed from node_modules/laravel-mix/src/config.js from Laravel 5.6 onward.
I must've been using an outdated version of Laravel at the time of posting above. I've now updated my original comment to prevent confusion.
Unfortunately I don't use Laravel anymore so can't work on a solution.
In my case, I did not update mix-manifest.json to the production server. After updating to the server, it works.
I was really stuck here for a while. If nothing above seems to work, it's possible you've made the same mistake I did.
Make sure you are calling mix and not asset when you include your script.
Good:
<script src="{{ mix('js/app.js') }}" defer></script>
Bad:
<script src="{{ asset('js/app.js') }}" defer></script>
Solution is Simple...
Just Try
For CSS:
<link rel="stylesheet" href="{{asset(mix('/css/app.css'))}}">
For JS
<script src="{{asset(mix('js/app.js'))}}"></script>
I know this Look Stupid But Its Work Because Laravel Mix.manifest.js File path is not valid.so assets() return as Current Path with Version
Most helpful comment
I found out that the mix configuration parameter "inProduction" has been rename to "production". I'm using the below code for versioning.
The final JS file with hash mappings are stored in the mix-manifest.json file.