-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webpacker fails to find image asset in a subdirectory #2956
Comments
I'm having the same issue. Looks like this was an issue before, and it was fixed in #1964 (and #1973 I guess). The way the rules are set up seems to have significantly changed in 6.x for webpack 5 compatbility, so #2802 has I think "broken" these original fixes. I believe the change that causes this problem is here. |
@taylorthurlow many thanks for the pointers. The changes you are indicating seems to have happened in webpacker v5, and v6 (with webpack 5 compatibility) has a completely different configuration. The relevant configuration in v6 seems to be here: webpacker/package/rules/file.js Lines 20 to 22 in 45cc2a2
I'll try tweaking it to find what can work edit: From webpack docs, it seems this customizes the generated output filename, which does not contain the path or file name, which is good. We just want te manifest to contain the file paths. |
The issue seems to be with webpack-assets-manifests when it takes the basename of the file: const { sourceFilename } = asset.info;
const name = sourceFilename ?
( contextRelativeKeys ? sourceFilename : path.basename( sourceFilename ) ) :
asset.name; Here, for me, sourceFilename is equal to |
See probably related issue: webdeveric/webpack-assets-manifest#131
|
Investigating, this code is not called. The condition
In file.js tweaking the generated location with Perhaps nothing will need to be patched in webpack-assets-manifest after all... |
discussed in webpack/webpack#12916 |
I do have a similar problem with pre.2 and media files. As stated by @taylorthurlow above, the cause may be in the removal of some path definitions in the file-loader. |
We are also encountering the same problem. Manifest v5
Manifest v6
It seems like:
|
I'm not much of a javascript programmer so there is probably a better way to do this, but this is my current work around in case it helps anyone. Basically just restoring the file-loader rule to that of version 5.2.1. //config/webpack/base.js
const { webpackConfig, rules } = require('@rails/webpacker')
const fileIndex = rules.findIndex(r => r.type === 'asset/resource')
if (fileIndex !== -1) {
rules[fileIndex] = {
test: [
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
/\.tiff$/,
/\.ico$/,
/\.avif$/,
/\.webp$/,
/\.eot$/,
/\.otf$/,
/\.ttf$/,
/\.woff$/,
/\.woff2$/,
/\.svg$/
],
exclude: [/\.(js|mjs|jsx|ts|tsx)$/],
use: [
{
loader: 'file-loader',
options: {
name(file) {
if (file.includes('app/packs')) {
return 'media/[path][name]-[hash].[ext]'
}
return 'media/[folder]/[name]-[hash:8].[ext]'
},
context: 'app/packs'
},
},
],
}
}
module.exports = webpackConfig |
Any solutions worked facing same with webpacker 5.2.1 version |
@kb-ally you shouldn't be experiencing this problem with webpacker 5.2.x. This problem is related to a config change for webpacker 6. |
We have an png placed in and we need to reference it like Is above expected ? I was looking for full path with we are moving from sprockets to webpacker |
We are trying to update webpacker, and are encountering the same issue. Any news on that topic? I've tried using @sovapatr's solution, however, it can only work for a depth of 1. |
I follow @sovapatr's solution , use at webpacker 6.0.0.beta.7, need two more step to work:
|
Just a heads up for anyone in the future reading this. This issue may hit you and may not even be obvious, i had a situation where some assets would start to fail, somewhat randomly, and only on production. When inspecting the manifest, the failing file is mysteriously be missing, while every other asset around it being included just fine. I had the same image, with different filenames, both being called in a view. This basically creates a near impossible-to-debug race condition where the first to be hashed is the key (filename) ends up in the manifest, when subsequent is dropped because same exact hash. |
I faced the same issue and got it working with webpack's built-in asset handling (v5), the solution is the Here's my setup: Versions:
Folder structure:
const path = require('path')
const { webpackConfig, merge } = require('@rails/webpacker')
const WebpackAssetsManifest = require('webpack-assets-manifest')
const manifestPlugin = webpackConfig.plugins.find(r => r instanceof WebpackAssetsManifest)
if (manifestPlugin) {
manifestPlugin.options.contextRelativeKeys = true // <-- important!
}
const customConfig = {
context: path.resolve(__dirname, '../../app/webpacker'), // <-- Adjust to your folder structure!
// ... omitted rest of config
}
module.exports = merge(webpackConfig, customConfig) With this I get the correct subdirectories in my "application.js": "/packs/js/application-6f017e22569258b8eb93.js",
"fonts/ObjektivMk2_W_Bd.eot": "/packs/media/images/bd920ee6b47f6c02808a.eot",
"images/icons/notice-alert.svg": "/packs/media/images/782e9f7b586c7677dd9f.svg"
... |
Thanks @sled! For anyone else following this and wants to revert to the webpacker-5 mainfest structure you will also need to also use const path = require('path')
const { webpackConfig, merge } = require('@rails/webpacker')
const WebpackAssetsManifest = require('webpack-assets-manifest')
const manifestPlugin =
webpackConfig.plugins.find(r => r instanceof WebpackAssetsManifest)
if (manifestPlugin) {
manifestPlugin.options.contextRelativeKeys = true;
manifestPlugin.options.customize = function(entry) {
if (entry.key.startsWith('images/')) {
return {
key: entry.key.replace(/^images/, 'media/images'),
value: entry.value
};
}
if (entry.key.startsWith('fonts/')) {
return {
key: entry.key.replace(/^fonts/, 'media/fonts'),
value: entry.value
};
}
return entry;
};
}
const customConfig = {
context: path.resolve(__dirname, '../../app/packs'), // Default webpacker setup, old setup was app/javascripts, this is the value from webpacker.yml "source_path"
// ...rest of your customConfig goes here
}
module.exports = merge(webpackConfig, customConfig) |
A more generic solution: const path = require('path')
const { webpackConfig, merge } = require('@rails/webpacker')
const WebpackAssetsManifest = require('webpack-assets-manifest')
const manifestPlugin =
webpackConfig.plugins.find(r => r instanceof WebpackAssetsManifest)
if (manifestPlugin) {
manifestPlugin.options.contextRelativeKeys = true;
// if asset path begins e.g. with `images/` it will be replaced with `media/images/`
const assetPrefixes = ['images/', 'fonts/', 'pdfs/'];
manifestPlugin.options.customize = function(entry) {
const assetPrefix = assetPrefixes.find(prefix => entry.key.startsWith(prefix));
if (assetPrefix) {
return {
key: entry.key.replace(assetPrefix, `media/${assetPrefix}`),
value: entry.value
};
}
return entry;
};
}
const customConfig = {
context: path.resolve(__dirname, '../../app/packs'), // Default webpacker setup, old setup was app/javascripts, this is the value from webpacker.yml "source_path"
// ...rest of your customConfig goes here
}
module.exports = merge(webpackConfig, customConfig) |
Still seeing nested directories get dropped. For example:
Ends up as I would expect webpacker: 6.0.0-rc.5 |
I don't think this change has been proposed as PR yet, I also ran into a different problem, if you have an asset file twice with identical content hash, only one will land in the output, i.e:
manifest.json
which means if you have something like |
Ran into the same problem. |
Fixed in shakacode/shakapacker#47 and released on v6.1.0. Thanks, @tomdracz! 🎉 |
Using webpacker 6.0.0.pre.2 and webpack 5.26.1, rails view cannot find paths for image asset.
Here is the haml line that fails in my view:
= image_pack_tag('flags/fr.svg', class: 'flag rounded-circle me-1')
I'm getting the
Webpacker::Manifest::MissingEntryError
exception. The image is located inapp/webpack/images/flags/fr.svg
. The directory structure looks like:webpacker.yml
contains:It seems that the problem lies with the manifest generation. The asset path should be
flags/fr.svg
relative toapp/webpack/images
but theflags/
path prefix seems to be missing. The manifest contains:Perhaps this is a misconfiguration or a bug of webpack-assets-manifest in
webpacker/package/environments/base.js
Lines 57 to 63 in 45cc2a2
The text was updated successfully, but these errors were encountered: