Importing a .svg file into my react component is failing with the following error:
Uncaught Error: Cannot find module 'images/pefin-logo.svg'
at newRequire (styles.8986bff4.js:37)
at newRequire (src.e31bb0bc.js:29)
at newRequire (LoginPage.115627cb.js:29)
at newRequire (src.e31bb0bc.js:21)
at localRequire (src.e31bb0bc.js:53)
at Object.parcelRequire.components/Nav.js.@babel/runtime/helpers/slicedToArray (Nav.js:7)
at newRequire (src.e31bb0bc.js:47)
at localRequire (src.e31bb0bc.js:53)
at Object.parcelRequire.components/Page.js.@babel/runtime/helpers/slicedToArray (Page.js:6)
at newRequire (src.e31bb0bc.js:47)
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": "last 2 versions"
},
"debug": true,
"modules": false,
"useBuiltIns": "usage"
}
],
"@babel/preset-react"
],
"plugins": [
"syntax-dynamic-import",
"@babel/plugin-transform-runtime",
],
"env": {
"test": {
"presets": [
[
"@babel/preset-env", {
"targets": {
"node": "current"
},
"modules": "commonjs"
}
]
]
}
}
}
It should work.
The app succeeds in building. I tried changing the path of the image it was importing to ensure that line was being hit, and sure enough, it breaks if I put a path that doesn't exist. When I open my app in the browser, I get the error above.
If I look at my dist dir, I can see the image in there as pefin-logo.36442847.svg
I noticed issues https://github.com/parcel-bundler/parcel/issues/2769 and possibly https://github.com/parcel-bundler/parcel/issues/1756 looks similar, since I am code-splitting but that refers to a missing JS file. I tried stepping through the requires, I noticed that there's a chain of requires for each bundle, and each one falls through to the previous bundle's require. In the case of this image, it's falling through to the first bundle, and failing to find the image, though I'm not quite sure why, since I'm not too familiar with all the internal machinery of parcel's require runtime code.
My components are as follows:
I have an React.lazy()
One of the bundles is LoginPage.js which imports a Page component, which imports Nav, which imports pefin-logo.svg to display it:
import logo from '../images/pefin-logo.svg'
When I browse to /login (which pulls in the LoginPage bundle), I get the error above.
Curiously, when I look at the src bundle, I find the following code near the end.
b.load([["pefin-logo.36442847.svg","images/pefin-logo.svg"]])
Also, I've extracted what looks like a map of file paths and dependencies at https://gist.github.com/akatechis/9ea8a1a830a664c42e6b21061f3d5815
The only thing I notice here is that the svg image is listed under the NotFound page, but not under the LoginPage. That said, I'm not sure exactly how to interpret this, so I don't know if that's peculiar or not.
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.3
| Node | 10.12.0
| Yarn | 1.13.0
| Operating System | Windows 10
The only thing I notice here is that the svg image is listed under the NotFound page, but not under the LoginPage
Just to verify:
Are you using the logo in multiple bundles (main and/or dynamic)?
That's a known bug.
https://github.com/parcel-bundler/parcel/issues/2546, https://github.com/parcel-bundler/parcel/issues/2340
No, it doesn't look like we are importing the same file using both static and dynamic methods, but we do have multiple dynamic bundles that import Page -> Nav -> logo.svg
No, it doesn't look like we are importing the same file using both static and dynamic method
That's not what I meant. Here's an example:
main.js
|- home.js
|- logo.svg
|- about.js (dynamic, "bundle boundary")
|-logo.svg
The key is that the first logo.svg is used by one bundle and the other logo.svg is used by another bundle (caused by dynamic imports or by using multiple entrypoints).
Here's what my graph looks like:
index.js
|- App.js
|- (dynamic import) LoginPage.js
|- Page.js
|- Nav.js
|- logo.svg
|- (dynamic import) SignupPage.js
|- Page.js
|- Nav.js
|- logo.svg
There's more pages than just those two, but they're all imported dynamically in App.js:
const NotFoundPage = lazy(() => import('./NotFoundPage'))
const SignupPage = lazy(() => import('./SignupPage'))
const LoginPage = lazy(() => import('./LoginPage'))
const ForgotPasswordPage = lazy(() => import('./ForgotPasswordPage'))
const ResetPasswordPage = lazy(() => import('./ResetPasswordPage'))
const NewUserPage = lazy(() => import('./NewUserPage'))
const FeedPage = lazy(() => import('./FeedPage'))
const SpendingPage = lazy(() => import('./SpendingPage'))
const DebugPage = lazy(() => import('./DebugPage'))
My confusion with that description is that it seems like that issue occurs when you import the same file both statically and dynamically, but it seems like always importing statically (or always importing dynamically) should work?
My confusion with that description is that it seems like that issue occurs when you import the same file both statically and dynamically, but it seems like always importing statically (or always importing dynamically) should work?
No:
If you import a single asset multiple times (logo.svg), Parcel correctly recognises this and removes the second asset because it will be included in the bundle because of the first usage and can be referred to by its name:
index.js
|- app.js
|- logo.svg
|- something.js
|- logo.svg (gets removed/deduplicated)
But when Parcel processes multiple entrypoints (because of dynamic imports or because multiple files were passed to the cli), it also deduplicates it across bundles:
index.js
|- app.js
|- logo.svg
|- dynamic: something.js
something.js
|- logo.svg (gets removed/deduplicated __across bundles__)
In theory, it should work because when the async bundle is required and can't find some dependency in it's own bundle, require will continue to search in the requiring bundle as well (I think). But that doesn't work....
But now I'm curious as well: why doesn't this happen to Page.js but only the logo?
In theory, it should work because when the async bundle is required and can't find some dependency in it's own bundle, require will continue to search in the requiring bundle as well (I think). But that doesn't work....
Correct, I did see that behavior when I attempted to debug this issue, but it seems to not work. The other thing that's odd is that this only happens for the SVG file. For javascript modules that are imported in the same way as the logo (eg, in multiple dynamically-loaded bundles) I see that those properly get hoisted into the main bundle with the rest of the shared code.
Hello, parcel devs. Sorry to be bumping this, but I'd like to know if this is currently being worked on. If not, might I be able to join in? I'm not too familiar with the internals of Parcel, so some pointers on where/what to look at in order to investigate this might be helpful.
I'm also eager to get this fixed. Anyone that could give some pointers on where to start and I would be happy to give it a try to solve it :)
Hello, parcel devs. I've managed to clone the repo, and step through the code, to see the SVG file get loaded, transformed into a module.exports = JS asset, and I can even find where it gets written to the output dir, but I can't seem to find where the file is moved from one bundle to the parent or does that happen before the asset itself is loaded?
A bit of guidance would be appreciated here.
Thanks!
@devongovett Could you give some guidance? 馃檹
I have taken another look and feel like I'm getting closer. I tried tracing the asset through the Bundler's bundle() method, and noticed that on this line: https://github.com/parcel-bundler/parcel/blob/a50ddd5ee18bbf2a70033fb118e6ec3a93a4ed97/packages/core/parcel-bundler/src/Bundler.js#L647 asset.parentBundle is null.
That said, I have no idea whether that is expected or not.
As a side note, I was able to verify that if I add an import to my common bundle (in my App.js module) for that same file, then the import inside the dynamic bundle works.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.
Hello, was this issue looked at? I'm currently experiencing the same problem. My svg is getting bundled into the first bundle, but if I navigate via url to another page (or reload on another page) which has its own bundle the svg cannot be found.
How does parcel determine which bundle you will navigate to first?
I'm on [email protected] and I'm also seeing this issue.
I have created a minimal repro repo here: https://github.com/lucasterra/parcel-dynamic-import-repro
Any updates?
Most helpful comment
@devongovett Could you give some guidance? 馃檹