Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

SSR not working on initial request when using Kestrel #166

Closed
antmdvs opened this issue Jul 7, 2016 · 3 comments
Closed

SSR not working on initial request when using Kestrel #166

antmdvs opened this issue Jul 7, 2016 · 3 comments

Comments

@antmdvs
Copy link

antmdvs commented Jul 7, 2016

Repro steps:

  1. use the yeoman generator to create a new react-redux app
  2. dotnet run
  3. request http://localhost:5000/fetchdata

Expected result:
Weather Forecast data is displayed in the grid

Actual result:
"Loading..." is displayed in the grid

I haven't been able to repro this when running on IIS Express.

Project rrcore1 (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
Hosting environment: Production
Content root path: C:\Git\rrcore1
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/fetchdata  
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method Rrcore1.Controllers.HomeController.Index (rrcore1) with arguments () - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
      Executing ViewResult, running view at path /Views/Home/Index.cshtml.
info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
      User profile is available. Using 'C:\Users\e5006399\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
[Node] ts-loader: Using typescript@1.8.10 and C:\Git\rrcore1\tsconfig.json
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/api/SampleData/WeatherForecasts?startDateIndex=0  
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method Rrcore1.Controllers.SampleDataController.WeatherForecasts (rrcore1) with arguments (0) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action Rrcore1.Controllers.SampleDataController.WeatherForecasts (rrcore1) in 150.6004ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 162.991ms 200 application/json; charset=utf-8
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action Rrcore1.Controllers.HomeController.Index (rrcore1) in 7659.4053ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 7914.9728ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/dist/vendor.css?v=ALPkvIaKC1T2242cKAFhm3Sn3ig2huZNWkXQa7RUv0c  
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/dist/site.css  
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/dist/main.js  
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/dist/vendor.js?v=sH3XNFYZpAM_75zY7fmOcjZQvi27vJH0-pm_ZPIMr64  
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 3.6947ms 404 
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 3.0229ms 404 
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /dist/vendor.js was not modified
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      The file /dist/vendor.css was not modified
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 15.3442ms 304 text/css
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 14.4214ms 304 application/javascript
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/dist/main.js  
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 0.3254ms 404 
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/favicon.ico  
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/favicon.ico'. Physical path: 'C:\Git\rrcore1\wwwroot\favicon.ico'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 17.0513ms 200 image/x-icon

@antmdvs antmdvs changed the title SSR not working with React+Redux template on initial request when using Kestrel (dotnet run) SSR not working on initial request when using Kestrel Jul 7, 2016
@laskoviymishka
Copy link
Contributor

laskoviymishka commented Jul 8, 2016

It looks like you not build your client code. So in browser console you probably will see that your bundle.js is missing. This is becouse webpack integration switched off (you run it in PROD mode), and template is expected that bundle.js exist.

To fix this issue you need run your code in development mode:
dotnet run --environment="DEV"
Or build bundle via webpack:
webpack

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Jul 11, 2016

Thanks for reporting this. It turns out it was a race condition inside the domain-task NPM module, which exposed an underlying design issue. The domain-task module was relying on all server-side prerendering tasks being queued up before its first setTimeout(...) callback ran, but on the first invocation (on my machine, at least, and I guess on @antmdvs's), it took long enough to JIT/execute the code that the callbacks ran in the wrong order. On subsequent requests, the code executed much faster (I guess because it already ran once, so Node had already loaded and compiled it in memory) and then the race condition was not triggered.

To fix this, I've updated domain-task to version >= 2.0.0, and modified the usage slightly. Before, your code would call:

fetch(something).then(doMoreStuff);

...and domain-task would try to delay the server-side rendering until the whole promise chain completed. But because of the race condition, sometimes the server-side rendering happened too early, and you'd end up rendering something like the "Loading" screen.

Now, the usage is like this:

var myTask = fetch(something).then(doMoreStuff);
addTask(myTask);

... so that domain-task waits for the entire promise chain to complete before allowing server-side rendering to execute.

I've updated the Yeoman generator, so if you get the latest generator-aspnetcore-spa, you should find that the issue is gone.

If you want to update an existing project, upgrade to the latest domain-task and aspnet-prerendering packages, and modify any uses of domain-task/fetch as described above, or as in this example diff. This is unfortunately a breaking change to the API, but it's unavoidable as far as I can tell.

@antmdvs
Copy link
Author

antmdvs commented Jul 14, 2016

@SteveSandersonMS Thanks, Steve!

BTW, I'm not sure if this is an issue but I noticed that Node Domain module is "pending deprecation." https://nodejs.org/api/domain.html#domain_domain

Is this of concern since domain-task takes a dependency on it?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants