asp-prerender-module breaks React's ability to detect Server-Side Rendering #55

Closed
opened 2025-08-09 17:14:50 +00:00 by fergalmoran · 0 comments
Owner

Originally created by @baughmann on 5/26/2018

This is in reference to using OpenLayers to render a Map in .NET Core/React/Redux

asp-prerender-module breaks React's ability to detect Server-Side Rendering

asp-prerender-module breaks React's canUseDOM, window detection, etc.
While asp-prerender-module is enabled, detecting whether or a component is rendering in the client becomes [seemingly] impossible. I've attempted the following methods:

  1. exenv module's canUseDOM function: https://github.com/JedWatson/exenv
  2. Detecting the window (i.e. if (typeof window !== 'undefined') // render map
  3. Creating map in inside of componentDidMount()

I did not attempt to provide a fake window object.

Functional impact

Forces disabling of Server-Side Rendering application-wide
Would highly prefer to just disable rendering of that specific component, rather than disable SSR for teh whole application.

Minimal repro steps

What is the smallest, simplest set of steps to reproduce the issue. If needed, provide a project that demonstrates the issue.

  1. Run Dotnet CLI command dotnet new reactredux and then npm install
  2. Install openlayers module and it's types, and exenv:
    $ npm i --save openlayers
    $ npm i --save @types/openlayers
    $ npm i --save exenv
  3. Target ES6: change target from es5 to es6 in tsconfig.json
  4. Disable strict mode: set "strict": false in tsconfig.json
  5. import { canUseDOM } from 'exenv'; in Home.tsx
  6. import * as ol from 'openlayers'; in Home.tsx
  7. Create map <div>: inside render():
    <div id="map" className="map" style={{ height: '500px' }}></div>
  8. Create map if canUseDOM:
        new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                })
            ],
            view: new ol.View({
                center: [0, 0],
                zoom: 3
            })
        });
  1. $ dotnet run

Expected result

See OpenLayers Map render in Home

Actual result

Got ReferenceError: window is not defined
See below for full error. Would like guidance on how to accomplish my goals stated above. Thank you.

Further technical details

Full error stack

NodeInvocationException: Prerendering failed because of error: ReferenceError: window is not defined at xb.wb (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:632:723) at new xb (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:633:454) at C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:633:655 at OPENLAYERS (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:607:22) at Object.<anonymous> (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:613:2) at __webpack_require__ (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:20:30) at Object.<anonymous> (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:437:69) at __webpack_require__ (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:20:30) at Object.<anonymous> (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:243:75) at __webpack_require__ (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:20:30) Current directory is: C:\Users\nbaughman\source\Mercury\Jupiter
Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance+<InvokeExportAsync>d__7.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance+<InvokeExportAsync>d__13.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.NodeServices.NodeServicesImpl+<InvokeExportWithPossibleRetryAsync>d__10.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.NodeServices.NodeServicesImpl+<InvokeExportWithPossibleRetryAsync>d__10.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.SpaServices.Prerendering.PrerenderTagHelper+<ProcessAsync>d__29.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner+<RunAsync>d__0.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
AspNetCore._Views_Home_Index_cshtml+<ExecuteAsync>d__12.MoveNext() in Index.cshtml
+
    ViewData["Title"] = "Home Page";
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderPageCoreAsync>d__16.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderPageAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderAsync>d__14.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor+<ExecuteAsync>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor+<ExecuteAsync>d__21.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.ViewResult+<ExecuteResultAsync>d__26.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeResultAsync>d__19.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResultFilterAsync>d__24.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
*Originally created by @baughmann on 5/26/2018* This is in reference to using OpenLayers to render a Map in .NET Core/React/Redux ### `asp-prerender-module` breaks React's ability to detect Server-Side Rendering *asp-prerender-module breaks React's canUseDOM, window detection, etc.* While `asp-prerender-module` is enabled, detecting whether or a component is rendering in the client becomes [seemingly] impossible. I've attempted the following methods: 1. `exenv` module's `canUseDOM` function: https://github.com/JedWatson/exenv 2. Detecting the window (i.e. `if (typeof window !== 'undefined') // render map` 3. Creating map in inside of `componentDidMount()` I did not attempt to provide a fake `window` object. ### Functional impact *Forces disabling of Server-Side Rendering application-wide* Would highly prefer to just disable rendering of that specific component, rather than disable SSR for teh whole application. ### Minimal repro steps *What is the smallest, simplest set of steps to reproduce the issue. If needed, provide a project that demonstrates the issue.* 1. Run Dotnet CLI command `dotnet new reactredux` and then `npm install` 2. Install `openlayers` module and it's `types`, and `exenv`: `$ npm i --save openlayers ` `$ npm i --save @types/openlayers ` `$ npm i --save exenv ` 3. Target ES6: change `target` from `es5` to `es6` in `tsconfig.json` 4. Disable strict mode: set `"strict": false` in `tsconfig.json` 5. `import { canUseDOM } from 'exenv';` in `Home.tsx` 6. `import * as ol from 'openlayers';` in `Home.tsx` 7. Create map `<div>`: inside `render()`: `<div id="map" className="map" style={{ height: '500px' }}></div>` 8. Create map if `canUseDOM`: ``` new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: [0, 0], zoom: 3 }) }); ``` 9. `$ dotnet run ` ### Expected result *See OpenLayers Map render in Home* ### Actual result *Got `ReferenceError: window is not defined`* See below for full error. Would like guidance on how to accomplish my goals stated above. Thank you. ### Further technical details *Full error stack* ``` NodeInvocationException: Prerendering failed because of error: ReferenceError: window is not defined at xb.wb (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:632:723) at new xb (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:633:454) at C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:633:655 at OPENLAYERS (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:607:22) at Object.<anonymous> (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:613:2) at __webpack_require__ (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:20:30) at Object.<anonymous> (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:437:69) at __webpack_require__ (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:20:30) at Object.<anonymous> (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:243:75) at __webpack_require__ (C:\Users\nbaughman\source\Mercury\Jupiter\ClientApp\dist\main-server.js:20:30) Current directory is: C:\Users\nbaughman\source\Mercury\Jupiter Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance+<InvokeExportAsync>d__7.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance+<InvokeExportAsync>d__13.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.AspNetCore.NodeServices.NodeServicesImpl+<InvokeExportWithPossibleRetryAsync>d__10.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.NodeServices.NodeServicesImpl+<InvokeExportWithPossibleRetryAsync>d__10.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.AspNetCore.SpaServices.Prerendering.PrerenderTagHelper+<ProcessAsync>d__29.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner+<RunAsync>d__0.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) AspNetCore._Views_Home_Index_cshtml+<ExecuteAsync>d__12.MoveNext() in Index.cshtml + ViewData["Title"] = "Home Page"; System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderPageCoreAsync>d__16.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderPageAsync>d__15.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.AspNetCore.Mvc.Razor.RazorView+<RenderAsync>d__14.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor+<ExecuteAsync>d__22.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor+<ExecuteAsync>d__21.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.ViewResult+<ExecuteResultAsync>d__26.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeResultAsync>d__19.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResultFilterAsync>d__24.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware+<Invoke>d__6.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware+<Invoke>d__6.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext() ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/JavaScriptServices#55
No description provided.