In my JS file I have these assets loaded like
const loadingGif3 = new URL('/src/assets/images/loading-3.gif', import.meta.url);
const noImg = new URL(',,/../assets/images/noimage.png', import.meta.url);
however I get an error
Not allowed to load local resource: file url here
I'm using Angular CLI v14.2.0 so I guess it's using webpack 5 under the hood which recommends to load assets with the import.meta.url way.
Am I missing something blindingly obvious?
What's happening is that Angular has disabled webpack's bundling of assets referenced with import.meta.url, which leads to the default (and quite broken) behaviour of rewriting import.meta.url to a file:// URL on the local filesystem, which is not where the asset will eventually live, obviously.
It appears that you can disable this with parser.javascript.importMeta in a custom webpack config. Make sure you have webpack 5.68.0 or newer. Here is the relevant flag: https://webpack.js.org/configuration/module/#moduleparserjavascriptimportmeta
This will preserve import.meta.url but it won't bundle the asset, so in this case (or if you disabled parser.javascript.importMeta), you need to add it to the assets section in your angular.json. Likewise, the experimental (for now) esbuild support will behave the same way.
EDIT: Alternately, you can re-enable webpack's default treatment of new URL(..., import.meta.url) which is to bundle (and munge the names of, etc) the assets referenced by it. This is done with this flag: https://webpack.js.org/configuration/module/#moduleparserjavascripturl
Angular's default is somewhere in between - it allows webpack to bundle workers (presumably because people would notice right away if this were broken), but nothing else, including WASM files, which can cause some nasty surprises.
You will have to install @angular-builders/custom-webpack and use @angular-builders/custom-webpack:browser and @angular-builders/custom-webpack:dev-server in place of the default ones in your angular.json.
Then add a custom webpack config like this:
module.exports = {
module: {
parser: {
javascript: {
importMeta: false,
},
},
},
};
or, for the second solution,
module.exports = {
module: {
parser: {
javascript: {
url: true,
},
},
},
};
For an explanation of why Angular does this see:
https://github.com/angular/angular-cli/issues/24617
Also note that you probably have to delete your .angular directory before rebuilding for the change to actually take effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With