Pros and Cons of Using JavaScript Interop in Blazor
Tags: javascript, blazor, webdev, productivity
Published: 2022-02-20 06:53:35

---
title: Pros and Cons of Using JavaScript Interop in Blazor
published: true
date: 2022-02-18 11:42:58 UTC
tags: javascript, blazor, webdev, productivity
canonical_url: https://www.syncfusion.com/blogs/post/pros-and-cons-of-using-javascript-interop-in-blazor.aspx
cover_image: https://www.syncfusion.com/blogs/wp-content/uploads/2022/02/Pros-and-Cons-of-Using-JavaScript-Interop-in-Blazor.png
---

[Blazor](https://en.wikipedia.org/wiki/Blazor "Wikipedia page for Blazor") is an open-source, single-page web application development framework. Unlike other frameworks, such as [Angular](https://angular.io/ "Angular home page"), [React](https://reactjs.org/ "React home page") and [Vue](https://vuejs.org/ "Vue home page"), which depend on JavaScript libraries, Blazor allows you to write and run C# code in web browsers via WebAssembly.

The Blazor framework can, however, call JavaScript functions from .NET (C#) methods and vice versa. It handles the [DOM (document object model)](https://en.wikipedia.org/wiki/Document_Object_Model "Wikipedia page for Document Object Model") manipulation and browser API calls through a method called JavaScript interoperability (JS interop).

We can also use TypeScript in Blazor, as TypeScript is the superset of JavaScript. When we compile a Blazor project, the TypeScript file will be converted into a JavaScript file using the [MSBuild properties](https://www.typescriptlang.org/docs/handbook/compiler-options-in-msbuild.html "Compiler Options in MSBuild documentation").

In this blog post, we will see how to use JavaScript interop in Blazor, its pros, and its cons.

## Invoke JavaScript functions from .NET methods

In a Blazor app, to [call JavaScript functions from .NET](https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-5.0 "Call JavaScript functions from .NET methods in ASP.NET Core Blazor documentation"), we need to inject the [IJSRuntime](https://docs.microsoft.com/en-us/dotnet/api/microsoft.jsinterop.ijsruntime?view=dotnet-plat-ext-6.0 "IJSRuntime Interface documentation") abstraction and call the [InvokeAsync](https://docs.microsoft.com/en-us/dotnet/api/microsoft.jsinterop.ijsruntime.invokeasync?view=dotnet-plat-ext-6.0 "IJSRuntime.InvokeAsync Method") method. The **InvokeAsync** method accepts the function name and number of arguments that the function requires.

```csharp
ValueTask<TValue> InvokeAsync<TValue>(string identifier, object[] args);
```

This method has three arguments: function name, **CancellationToken** (for notification of whether the operation is canceled or not), and the number of arguments that the function requires.

```csharp
ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object[] args)
```

## Invoke .NET methods from JavaScript functions

To call static .[NET methods from JavaScript functions](https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-5.0 "Call .NET methods from JavaScript functions in ASP.NET Core Blazor documentation") in a Blazor app, use the **DotNet.invokeMethod** or  **DotNet.invokeMethodAsync** method.

Refer to the following code example.

```csharp
DotNet.invokeMethodAsync('{ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});
```

The previous method has three arguments:

- Application assembly name.
- .NET method name (identifier).
- The number of arguments (optional) that the function requires. (Note: Each argument should be **JSON-serializable** ).

## Pros of JS interop

Let’s see the advantages of using JavaScript interop in your Blazor application.

### Injecting a script

Using the JavaScript interop, we can easily inject the required code on-demand anywhere in our Blazor app. You can see the injected [JavaScript function after the DOM is loaded in the Blazor](https://stackoverflow.com/questions/62859002/how-do-i-make-a-javascript-function-available-after-the-document-is-loaded-in-bl "Make JavaScript function available after the document is loaded in Blazor documentation") app (both WebAssembly and Server apps).

Follow these steps to inject a script file in Blazor:

1. First, set the **autostart** attribute as **false** in the script tag <script>.
2. Then, inject the required script using the start().then(…) method. The injected function will be called after starting the Blazor app.
3. Next, create the script tag using the JavaScript function **createElement** and set the custom script file path in the **src** attribute.
4. Finally, append the script element to the **head** method.

Refer to the following code example.

```html
<body>
 <script src="_framework/blazor.{webassembly|server}.js"
         autostart="false"></script>
 <script>
   Blazor.start().then(function () {
      var customScript = document.createElement('script');
      customScript.setAttribute('src', 'scripts.js');
      document.head.appendChild(customScript);
   });
 </script>
</body>
```

### JavaScript isolation

Blazor allows [JavaScript isolation](https://www.syncfusion.com/faq/blazor/general/what-is-javascript-isolation-in-blazor-components "JavaScript isolation in Blazor components Knowledge Base documentation") in standard JavaScript modules. This JavaScript isolation feature provides the following benefits:

- JavaScript code will load only the specified components. This will save memory and rendering time.
- Imported JavaScript code does not affect any global namespace.
- We don’t need the library and component consumers to import the related JavaScript.

### Use any third-party JavaScript framework

One of the major advantages of using JavaScript interop is that we can integrate any of the JavaScript frameworks into the Blazor app and achieve its functionalities.

In the following code, we are going to call the [Syncfusion JS 2 JavaScript](https://www.syncfusion.com/javascript-ui-controls "Syncfusion JavaScript UI controls") library animation functions in our Blazor server app.

**[\_Host.cshtml]**

```html
<head>
  <link href="JSinterop.styles.css" rel="stylesheet" />
  @*Syncfusion library CDN script and CSS reference*@
  <link href="https://cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet">
  <script src="https://cdn.syncfusion.com/ej2/dist/ej2.min.js" type="text/javascript"></script>
  <script>
      window.initializeAnimation = () => {
         //initialize the Animation code.
         var animation = new ej.base.Animation({ duration: 5000 });
         animation.animate('#element1', { name: 'FadeOut' });
         animation.animate('#element2', { name: 'ZoomOut' });
      }
   </script>
</head>
```

**[Index.razor]**

```html
@page "/"
@inject IJSRuntime JsRuntime;
<style>
  #element1, #element2 {
    background: #333333;
    border: 1px solid #cecece;
    box-sizing: border-box;
    float: left;
    height: 100px;
    width: 100px;
  }
</style>
<h1>Hello, world!</h1>
 
  <div id="element1"></div>
  <div id="element2"></div>
 
@code{
  bool firstRender = true;
  protected override async Task OnAfterRenderAsync(bool firstRender)
  {
    if (firstRender)
    {
      // call the JS function.
      await JsRuntime.InvokeVoidAsync(
            "initializeAnimation");
    }
  }
}
```

### Cached JavaScript files

In a web platform, while caching static resources (the JavaScript file on the client-side browser), a static file will be loaded from the cache by default. This cache file will reduce the number of requests to the server, so it enhances the loading speed of the pages.

You can further improve the performance of the browser cache using the [catche-control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#cacheability "Cache Control") with the value of no-catch or by setting the [max-age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#controlling_caching "Controlling catching documentation") value.

### Asynchronous JavaScript method calls

By default, the JavaScript interop calls [asynchronous](https://en.wikipedia.org/wiki/Asynchronous_method_invocation "Wikipedia page for Asynchronous method invocation") methods, so it is compatible with both Blazor server and WebAssembly apps.

**Note:** Blazor server’s JS interop calls should be asynchronous, as they’re sent over a network connection.

## Cons of JavaScript interop

Even though the JavaScript interop in Blazor has so many advantages, there are some limitations to it.

### Directly modifying the DOM with JavaScript isn’t recommended

The DOM is used for display purposes alone in browsers. Modifying the DOM using JavaScript code is not suggested, anyway, as JavaScript restricts updating a Blazor element’s tracked changes.

Consider a situation where an element is rendered by Blazor code and modified externally using JavaScript directly or via JavaScript interop. Then, the DOM structure may not match Blazor’s internal representation. This may lead to undefined behaviors.

### JavaScript interop call _timeouts_

The JavaScript interop call may fail due to a network issue and low bandwidth network in a server app. By default, it takes a one-minute timeout for each JavaScript call. Luckily, we have an option to [increase the timeout](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.server.circuitoptions.jsinteropdefaultcalltimeout?view=aspnetcore-6.0#Microsoft_AspNetCore_Components_Server_CircuitOptions_JSInteropDefaultCallTimeout "CircuitOptions.JSInteropDefaultCallTimeout Property") value in the server app. But this may also lead to performance deterioration.

Refer to the following code.

[**Program.CS**]

```csharp
builder.Services.AddServerSideBlazor(
  options => options.JSInteropDefaultCallTimeout = {TIMEOUT});
```

We can override the global timeout set using the **JSInteropDefaultCallTimeout** method.

**[C#]**

```csharp
var result = await JS.InvokeAsync<string>("{ID}", {TIMEOUT}, new[] { "Arg1" });
```

### Size limits on JavaScript interop calls

In a Blazor server app, JavaScript interop calls are limited in size while maximizing the incoming SignalR message permitted for hub methods.

If we pass a huge [message](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.huboptions.maximumreceivemessagesize?view=aspnetcore-6.0#Microsoft_AspNetCore_SignalR_HubOptions_MaximumReceiveMessageSize "HubOptions.MaximumReceiveMessageSize Property") (more than 32 KB) in a JS call, then it will throw an error.

However, we can increase the size of the SignalR message in the Program.CS file like in the following code.

[**Program.CS**]

```csharp
builder.Services.AddServerSideBlazor()
  .AddHubOptions(options => options.MaximumReceiveMessageSize = 64 * 1024);
```

Increasing the message size will also increase the risks for the user. Additionally, reading a huge amount of content into memory as strings or byte arrays can also result in poor allocation of memory with the garbage collector. Further, it results in additional performance penalties.

### Other performance issues

A Blazor app will experience poor performance when we serialize a huge amount of .NET objects and sent them to the JS interop call. For example, serializing huge .NET objects rapidly in the resize and mouse wheel events.

Calling the JS interop frequently may lead to performance lag. The synchronous calls that don’t perform JSON serialization of arguments or return values, the memory management, and translations between .NET and JavaScript also result in poor performance.

## Conclusion

Thanks for reading! In this blog, we have seen JavaScript interop concepts used in the Blazor framework along with their pros and cons. With this JS interop, we can easily call JavaScript functions from .NET (C#) methods and vice versa.

Syncfusion’s [Blazor](https://www.syncfusion.com/blazor-components "Blazor UI components") component suite offers over 70 UI components that work with both server-side and client-side (WebAssembly) hosting models seamlessly. Use them to build marvelous applications!

If you have questions, you can contact us through our [support forum](https://www.syncfusion.com/forums "Syncfusion support forum"), [support portal](https://support.syncfusion.com/ "Syncfusion support portal"), or [feedback portal](https://www.syncfusion.com/feedback "Syncfusion Feedback Portal"). As always, we are happy to assist you!

## Related blogs

- [10 JavaScript Naming Conventions Every Developer Should Know](https://www.syncfusion.com/blogs/post/10-javascript-naming-conventions-every-developer-should-know.aspx "10 JavaScript Naming Conventions Every Developer Should Know blog")
- [Easily Use a JavaScript Control in a Blazor Server App](https://www.syncfusion.com/blogs/post/easily-use-a-javascript-control-in-a-blazor-server-app.aspx "Easily Use a JavaScript Control in a Blazor Server App blog")
- [Syncfusion Visual Studio Extensions Are Compatible with .NET 6.0](https://www.syncfusion.com/blogs/post/syncfusion-visual-studio-extensions-are-compatible-with-net-6-0.aspx "Syncfusion Visual Studio Extensions Are Compatible with .NET 6.0 blog")
- [7 Features of Blazor That Make It an Outstanding Framework for Web Development](https://www.syncfusion.com/blogs/post/7-features-of-blazor-that-make-it-an-outstanding-framework-for-web-development.aspx "7 Features of Blazor That Make It an Outstanding Framework for Web Development blog")