<script type="module" src="..."> is fetched twice in published MVC apps when importmap is present
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
In an ASP.NET Core MVC project using `MapStaticAssets()` with `WithStaticAssets()`, the JavaScript file referenced via `` is fetched twice when:
- The application has been published, and
- The page is loaded for the first time, or the browser cache is disabled, or a hard reload (Ctrl+F5) is performed
In development, the issue does not occur regardless of cache state.
Modules imported transitively from the entry script (via `import` statements inside JS) are fetched only once. The duplicate is specifically on the script directly referenced by the `src` attribute on a `<script type="module">` tag.
I am not sure whether this is a bug or intentional behavior. Either way, clarification or documentation would be appreciated, since the workaround (inline `import` statement) is non-obvious and the bandwidth cost is real on cold loads.
### Expected Behavior
`<script type="module" src="...">` should result in a single network request, matching the behavior of:
- The same setup in development
- Modules imported via `import` statements
- Non-module scripts (`<script>`, `<script defer>`)
### Steps To Reproduce
1. `dotnet new mvc -n ImportMapRepro`
2. Configure `Program.cs`:
```c#
app.MapStaticAssets();
// NOTE: WithStaticAssets() does not work with MapControllerRoute()
// (see #59003), so MapControllers + MapDefaultControllerRoute is used instead.
app.MapControllers().WithStaticAssets();
app.MapDefaultControllerRoute();
```
3. Add `wwwroot/js/dependency.js`:
```javascript
export const value = 42;
```
4. Add `wwwroot/js/entry.js`:
```javascript
import { value } from './dependency.js';
console.log(value);
```
5. In `_Layout.cshtml`'s `<head>`:
```html
<base href="~/" />
<script type="importmap">
```
6. In `_Layout.cshtml`'s ``:
```html
```
7. Publish the app and run it from the publish output.
8. Open the app, DevTools → Network → enable "Disable cache" → reload.
**Result:**
- entry.{hash}.js appears twice (HTTP 200, same URL, same ETag)
- dependency.{hash}.js appears once
### Exceptions (if any)
None
### .NET Version
.NET 10 (also reproducible on .NET 9)
### Anything else?
**Observations narrowing down the trigger**
The duplicate occurs only when all of the following are true:
- The application has been published (not development)
- A `` tag is rendered in the layout
- The script is loaded via ``
Changing any one eliminates the duplicate:
- Removing the importmap tag → single fetch (but disables JS module fingerprinting)
- Loading the entry via inline `import` instead of `src` -> single fetch:
```html
<script type="module">
import "/js/entry.js";
```
- Using a non-module → single fetch
Difference between dev and publish importmaps
In development the rendered importmap contains only the `imports` field. After publish it also contains an `integrity` field with hashes for each asset. This is the most visible difference between the two modes; whether it relates to the issue is unclear.
Network tab screenshot
<img width="882" height="290" alt="Image" src="https://github.com/user-attachments/assets/43096e56-624c-4659-a9f8-08420ed15048" />
> The entry module loaded via <script type="module" src> is fetched twice (red box). The dependency imported from inside that entry is fetched once (red underline).
For a page loading 10–20 module scripts, the cold load and Ctrl+F5 cost is doubled. There is no clear reason why a module script loaded via `src` should be fetched differently from one loaded via `import`. If this is intentional, it would help to document it — the workaround is not discoverable.
_Note: This issue was drafted with assistance from an AI assistant based on observations from my own testing. The reproduction steps and behavior described have been verified by me._
Contributor guide
Assessment
This issue has not been assessed yet.