aspnetcore/blazor/javascript-interoperability/location-of-javascript.md
Load JavaScript (JS) code using any of the following approaches:
:::moniker range=">= aspnetcore-6.0"
<head> markup (Not generally recommended)<body> markup.js) collocated with a component.js):::moniker-end
:::moniker range="< aspnetcore-6.0"
<head> markup (Not generally recommended)<body> markup.js):::moniker-end
Inline JavaScript isn't recommended for Blazor apps. We recommend using JS collocation combined with JS modules.
<script> tags:::moniker range=">= aspnetcore-8.0"
Only place a <script> tag in a component file (.razor) if the component is guaranteed to adopt static server-side rendering (static SSR) without enhanced navigation. Placing a <script> tag in a component file doesn't produce a compile-time warning or error, but script loading behavior might not match your expectations in components that adopt an interactive render mode or static SSR with enhanced navigation.
:::moniker-end
:::moniker range="< aspnetcore-8.0"
Don't place a <script> tag in a component file (.razor) because the <script> tag can't be updated dynamically. Placing a <script> tag in a component file produces a compile-time error.
:::moniker-end
:::moniker range=">= aspnetcore-5.0"
[!NOTE] Documentation examples usually place scripts in a
<script>tag or load global scripts from external files. These approaches pollute the client with global functions. For production apps, we recommend placing JS into separate JS modules that can be imported when needed. For more information, see the JavaScript isolation in JavaScript modules section.
:::moniker-end
:::moniker range="< aspnetcore-5.0"
[!NOTE] Documentation examples place scripts into a
<script>tag or load global scripts from external files. These approaches pollute the client with global functions. Placing JS into separate JS modules that can be imported when needed is not supported in Blazor earlier than .NET 5. If the app requires the use of JS modules for JS isolation, we recommend using .NET 5 or later to build the app. For more information, use the Version dropdown list to select a .NET 5 or later version of this article and see the JavaScript isolation in JavaScript modules section.
:::moniker-end
<head> markupThe approach in this section isn't generally recommended.
Place the JavaScript (JS) tags (<script>...</script>) in the <head> element markup:
<head>
...
<script>
window.jsMethod = (methodParameter) => {
...
};
</script>
</head>
Loading JS from the <head> isn't the best approach for the following reasons:
<head> markup.:::moniker range=">= aspnetcore-8.0"
In component markup, scripts can be loaded via a HeadContent component with the usual caveat that the approach slows down page load on the client, which we recommend avoiding. When a script is loaded with a HeadContent component in a Blazor Server app, Blazor WebAssembly app, or a Blazor Web App using either an interactive render mode (interactive SSR, CSR) or static SSR with enhanced navigation, navigating away from the component's page removes the <script> tag from the rendered <head> content but doesn't unload the script's JavaScript code, including event handlers that the script registers, exposed variables, and methods that the script provides. Only Blazor Web Apps using static SSR without enhanced navigation unload JavaScript code when the user navigates away from the page. Generally, you're better off adding <script> tags to the physical <head> content, unless you explicitly desire to keep such script references in the components that use them and don't mind that the code isn't unloaded on navigation events.
:::moniker-end
:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0"
In component markup, scripts can be loaded via a HeadContent component with the usual caveat that the approach slows down page load on the client, which we recommend avoiding. When a script is loaded with a HeadContent component, navigating away from the component's page removes the <script> tag from the rendered <head> content but doesn't unload the script's JavaScript code, including event handlers that the script registers, exposed variables, and methods that the script provides. Generally, you're better off adding <script> tags to the physical <head> content, unless you explicitly desire to keep such script references in the components that use them and don't mind that the code isn't unloaded on navigation events.
:::moniker-end
<body> markupPlace the JavaScript tags (<script>...</script>) inside the closing </body> element after the Blazor script reference:
<body>
...
<script src="{BLAZOR SCRIPT}"></script>
<script>
window.jsMethod = (methodParameter) => {
...
};
</script>
</body>
In the preceding example, the {BLAZOR SCRIPT} placeholder is the Blazor script path and file name. For the location of the script, see xref:blazor/project-structure#location-of-the-blazor-script.
:::moniker range=">= aspnetcore-6.0"
.js) collocated with a componentFor more information on RCLs, see xref:blazor/components/class-libraries.
:::moniker-end
.js)Place the JavaScript (JS) tags (<script>...</script>) with a script source (src) path inside the closing </body> element after the Blazor script reference:
<body>
...
<script src="{BLAZOR SCRIPT}"></script>
<script src="{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>
For the placeholders in the preceding example:
{BLAZOR SCRIPT} placeholder is the Blazor script path and file name. For the location of the script, see xref:blazor/project-structure#location-of-the-blazor-script.{SCRIPT PATH AND FILE NAME (.js)} placeholder is the path and script file name under wwwroot.In the following example of the preceding <script> tag, the scripts.js file is in the wwwroot/js folder of the app:
<script src="js/scripts.js"></script>
You can also serve scripts directly from the wwwroot folder if you prefer not to keep all of your scripts in a separate folder under wwwroot:
<script src="scripts.js"></script>
When the external JS file is supplied by a Razor class library, specify the JS file using its stable static web asset path: _content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}:
{PACKAGE ID} placeholder is the library's package ID. The package ID defaults to the project's assembly name if <PackageId> isn't specified in the project file.{SCRIPT PATH AND FILE NAME (.js)} placeholder is the path and file name under wwwroot.<body>
...
<script src="{BLAZOR SCRIPT}"></script>
<script src="_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>
In the following example of the preceding <script> tag:
ComponentLibrary, and a <PackageId> isn't specified in the library's project file.scripts.js file is in the class library's wwwroot folder.<script src="_content/ComponentLibrary/scripts.js"></script>
For more information, see xref:blazor/components/class-libraries.
:::moniker range=">= aspnetcore-6.0"
To ensure scripts load before or after Blazor starts, use a JavaScript initializer. For more information and examples, see xref:blazor/fundamentals/startup#javascript-initializers.
:::moniker-end
:::moniker range="< aspnetcore-6.0"
To inject a script after Blazor starts, chain to the Promise that results from a manual start of Blazor. For more information and an example, see xref:blazor/fundamentals/startup#inject-a-script-after-blazor-starts.
:::moniker-end
Blazor enables JavaScript (JS) isolation in standard JS modules (ECMAScript specification).
JS isolation provides the following benefits:
In server-side scenarios, always trap xref:Microsoft.JSInterop.JSDisconnectedException in case loss of Blazor's SignalR circuit prevents a JS interop call from disposing a module, which results in an unhandled exception. Blazor WebAssembly apps don't use a SignalR connection during JS interop, so there's no need to trap xref:Microsoft.JSInterop.JSDisconnectedException in Blazor WebAssembly apps for module disposal.
For more information, see the following resources: