Is there a way to run webpack middleware run synchronously and complete its action before next middleware runs.
Problem I am having is that page renders first and I am dynamically reading main.js file from wwwroot folder inside angular 2/webpack based project. e.g this is the dynamic main.js file reference:
<script src="~/dist/@ViewBag.HashedMain" asp-append-version="true"></script>
But the file isn't created in wwwroot folder yet. After few seconds, file is created and refreshing the page picks that file up.
Have you thought about using webpack to generate index.chtml file instead of using ViewBag?
@maxisam Is is possible? Not sure.
index.cshtml is server generated file and we have the ability to manipulate this file or pass data from .net server side. in my case e.g I am reading file from physical location and injecting that name dynamically from server side. Another reason of using cshtm is to leverage server side rendering offered Asp.Net core javascript services package.
Not sure if this is applicable in my scenario.
What I meant was not really generate the whole file. Just inject the scripts and css
I think I tried in the past to inject files in cshtml, but the html-plugin for webpack doesn't work with cshtml I guess. If I can force webpack dev middle ware to run synchronously, that will get me what I want. Application runs only when webpack completes its operation anyway. But asp.net core javascript services took a different approach of generating bundle assets before.
yeah, I just realized it. But then I came out another idea. Generate partial html files, only scripts or styles. Then use .net's ability to include those files. It seems working so far.
@maxisam What do you mean by partial html files? have you got an example somewhere?
create a file called scripts.html with only the following code.
<% for (key in htmlWebpackPlugin.files.js) { %>
<script src="<%= htmlWebpackPlugin.files.js[key] %>" type="text/javascript"></script>
<% } %>
html webpack pluging will generate a html file
use Response.WriteFile or @RenderPage to inject the file content to your asp.net page.
@maxisam thats smart, back to the question. :)
How will it resolve postpond index file rendering until webpack dev middleware creates js/css assets on destination to be picked up by index file?
Thanks, I got this idea after pulling couple of my hears.
As for your question, I don't have a good answer. But by doing this, we can use other way or 2 webpack processes to refresh the page by monitoring files. However, we lose the ability to do HMR.
I'm not sure I understand the request here, because ASP.NET middleware entries already are "synchronous" in the sense that the middleware pipeline runs in series (each middleware entry completes before handing over control to the next item). They are not "synchronous" in the sense of blocking a thread, but I don't think that's what you're asking for anyway.
If you're able to describe your requirements more precisely we can certainly consider it. In the meantime I'll close this because it's unclear that there's anything for us to do. Hope that's OK!
Hi Steve, Thanks for the response. I will try to explain this problem as much as I can here.
I am loading main.js bundle for production dynamically in my Index.cshtml like this:

Code which makes main.js file available on ViewBag is here:
// Becasue for production this is hashed chunk so has changes on each production build
public string GetMainDotJs()
{
var basePath = _env.WebRootPath + "//dist//";
var info = new System.IO.DirectoryInfo(basePath);
var file = info.GetFiles().Where(f => f.Name.StartsWith("main.") && !f.Name.EndsWith("bundle.map")).FirstOrDefault();
return file.Name;
}
The reason I have to dynamically load main.js file is that I am using angular2 lazy loading in my project for production. All the bundles created have got chunkhash in them for production, so we don't know what will be file name when webpack creates these bundle in prod mode. Starter project has only one main bundle for the whole app, so we can leverage asp.net core cache busing through asp-append-version="true" as an alternative, but this approach doesn't work in lazy loading scenario.
Another option to consider could be if there is a plugin like (html-webpack-plugin) which can manipulate the index file and inject dynamically created bundles for prod. Since we aren't using index.html, rather index.cshtml, this plugin doesn't seem to be an option.
Now, the approach which I am using to read main file from wwwroot/dist folder and use that in index.cshtml works, but when I launch the applicaiton, webpack hasn't build the main.js file I get this error:

Here is the same error in console:
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 1036.0402ms 500 text/html; charset=utf-8
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 1036.0402ms 500 text/html; charset=utf-8
info: Microsoft.AspNetCore.NodeServices[0]
DLL: Bundling done, all DLLs are valid.
Microsoft.AspNetCore.NodeServices:Information: DLL: Bundling done, all DLLs are valid.
info: Microsoft.AspNetCore.NodeServices[0]
webpack building...
Microsoft.AspNetCore.NodeServices:Information: webpack building...
info: Microsoft.AspNetCore.NodeServices[0]
[at-loader] Using [email protected] from typescript and "tsconfig.json" from c:\Users\asahi\AspNetCoreSpa/tsconfig.json (in a forked process).
Microsoft.AspNetCore.NodeServices:Information:
[at-loader] Using [email protected] from typescript and "tsconfig.json" from c:\Users\asahi\AspNetCoreSpa/tsconfig.json (in a forked process).
info: Microsoft.AspNetCore.NodeServices[0]
[at-loader] Checking started in a separate process...
Microsoft.AspNetCore.NodeServices:Information: [at-loader] Checking started in a separate process...
info: Microsoft.AspNetCore.NodeServices[0]
webpack built 8a46a7226f595e65858f in 22923ms
Microsoft.AspNetCore.NodeServices:Information: webpack built 8a46a7226f595e65858f in 22923ms
info: Microsoft.AspNetCore.NodeServices[0]
DLL: Checking if DLLs are valid.
Microsoft.AspNetCore.NodeServices:Information: DLL: Checking if DLLs are valid.
info: Microsoft.AspNetCore.NodeServices[0]
DLL: All DLLs are valid.
Microsoft.AspNetCore.NodeServices:Information: DLL: All DLLs are valid.
info: Microsoft.AspNetCore.NodeServices[0]
[at-loader] Ok, 2.248 sec.
Microsoft.AspNetCore.NodeServices:Information: [at-loader] Ok, 2.248 sec.
info: Microsoft.AspNetCore.NodeServices[0]
webpack building...
Microsoft.AspNetCore.NodeServices:Information: webpack building...
info: Microsoft.AspNetCore.NodeServices[0]
[at-loader] Checking started in a separate process...
Microsoft.AspNetCore.NodeServices:Information: [at-loader] Checking started in a separate process...
info: Microsoft.AspNetCore.NodeServices[0]
[at-loader] Ok, 0.004 sec.
Microsoft.AspNetCore.NodeServices:Information: [at-loader] Ok, 0.004 sec.
info: Microsoft.AspNetCore.NodeServices[0]
webpack built 515ae4ba9fff57d663bd in 2509ms
Microsoft.AspNetCore.NodeServices:Information: webpack built 515ae4ba9fff57d663bd in 2509ms
As you can see in above error, index page fails to load as file isn't available, however after 3-4~ seconds files are created by webpack and if I referesh the page, everything works.
There is one difference compared to starter template i.e I am using awesome-typescript-loader, which forks the node process for typechecking as explained on their website.
As you explained above the webpack middleware is synchronous, but how come it lets the following middle runs where as webpack hasn't finished creating files.
Above issue can be replicated in this branch of the repo:
As you explained above the webpack middleware is synchronous, but how come it lets the following middle runs where as webpack hasn't finished creating files.
Webpack dev middleware intercepts requests for the .js files themselves, and holds them until the Webpack compiler supplies the contents for the response. The only reason your approach isn't working with that is that you're trying to locate the file on disk from server-side code, rather than making an HTTP request for the file.
I am loading main.js bundle for production dynamically
For production? Perhaps your issue only occurs in development, but just for clarity, webpack dev middleware should only be used in development, and not enabled in production. The default templates here only enable it in development.
As a fix for your issue, you could change your GetMainDotJs .NET code so that, before making the GetFiles call, it makes an HTTP request for your main.js file and waits for the response. Since that response would wait until Webpack is done, by the time the code continues inside your GetMainDotJs code, the files will be on disk. This should not affect performance in production, because you shouldn't run that code (or Webpack dev middleware at all) in production :) Also I'm not sure there's any way that SpaServices could cover it in any more generally-applicable way. Hope this solution works for you!
Thanks Steve.
Sorry for the confusion. I meant currently main.js file is bing loaded dynamically both for dev and prod. And you are right the problem is only in Dev.
Let me try the solution you recommend.
Spot On!!! Solution worked, exactly what I need for webpack dev middleware to complete first.
Thanks Steve.
Most helpful comment
Webpack dev middleware intercepts requests for the
.jsfiles themselves, and holds them until the Webpack compiler supplies the contents for the response. The only reason your approach isn't working with that is that you're trying to locate the file on disk from server-side code, rather than making an HTTP request for the file.For production? Perhaps your issue only occurs in development, but just for clarity, webpack dev middleware should only be used in development, and not enabled in production. The default templates here only enable it in development.
As a fix for your issue, you could change your
GetMainDotJs.NET code so that, before making theGetFilescall, it makes an HTTP request for yourmain.jsfile and waits for the response. Since that response would wait until Webpack is done, by the time the code continues inside yourGetMainDotJscode, the files will be on disk. This should not affect performance in production, because you shouldn't run that code (or Webpack dev middleware at all) in production :) Also I'm not sure there's any way thatSpaServicescould cover it in any more generally-applicable way. Hope this solution works for you!