TrilonIO / aspnetcore-angular-universal

ASP.NET Core & Angular Universal advanced starter - PWA w/ server-side rendering for SEO, Bootstrap, i18n internationalization, TypeScript, unit testing, WebAPI REST setup, SignalR, Swagger docs, and more! By @TrilonIO
https://www.trilon.io
MIT License
1.46k stars 433 forks source link

Publish/Deployment Doesnt work #413

Closed naveedahmed1 closed 7 years ago

naveedahmed1 commented 7 years ago

I downloaded this repo, restored the npm dependencies and then tried to publish both using VS2017and dotnet publish command but none of these works.

Its keeps stuck in publish process for hours, with CPU utilization of 100% where node is taking over 90% resources.

MarkPieszak commented 7 years ago

That's strange, just tried it and dotnet publish finished fairly quickly, it runs the vendor bundles then the normal ones.

Do you have dotnet core 2.0.0 installed, or the latest VS2017?

naveedahmed1 commented 7 years ago

Yes I have dotnet core 2.0 and using latest VS 2017 (15.3.3) with latest version of nodejs (v8.5.0). I also tried using ASP.Net SPA template and have issues with that as well (though its publish task completes successfully), Please take a look at https://github.com/aspnet/JavaScriptServices/issues/292#issuecomment-329324155

MarkPieszak commented 7 years ago

Did increasing the --max-old-space-size=4096 fix the issue at all?

naveedahmed1 commented 7 years ago

I edited csproj file and updated below under PublishRunWebpack tag:

    <Exec Command="node --max_old_space_size=5048 node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod" />
    <Exec Command="node --max_old_space_size=5048 node_modules/webpack/bin/webpack.js --env.prod" />

After this change, ASP.Net SPA template: Publish task completes but produces extremely large bundles (the size of files in PublishFolder\ClientApp\dist is 27.6 Mb and the size of files in PublishFolder\wwwroot\distis 7.67 Mb.), and when I deploy it on IIS, the requests always timeout.

Aspnetcore-angular2-universal: Publish task continue running for hours and never concludes.

MarkPieszak commented 7 years ago

Strange, we have synced up on webpack configurations except that we have scss and font-awesome setup here. I'm going to a few other improvements as well (such as switching away from awesome-typescript-loader etc), maybe those would help but still, it should work for either repo!

Do you have a sample repo I could look at to try and investigate?

naveedahmed1 commented 7 years ago

Its a private repo, should I drop you an email with a sample?

naveedahmed1 commented 7 years ago

Can you please also confirm the size of files in these folders in your publish directory:

PublishFolder\ClientApp\dist
PublishFolder\wwwroot\dist

Does the size of files in PublishFolder\ClientApp\dist larger than size of files in PublishFolder\wwwroot\dist, if so, can you please explain why is it so?

MarkPieszak commented 7 years ago

The server bundle is in client app and the size of that one doesn't matter as there is no "load" on the server, it just contains everything it needs to serialize the app. Wwwroot is the client browser bunde(s).

Problem is it could be a large number of things causing it, I don't have much time as I'm also still dealing with Irma aftermath 😓 My email is mpieszak84@gmail.com I can try to take a look sometime if you have a private repo you can invite me to look at.

naveedahmed1 commented 7 years ago

Thank you so much @MarkPieszak , I really appreciate your quick reply and help despite being affected by Irma.

Regarding the slow publish, I was able to resolve it by upgrading the Node version in Visual Studio 2017 (default is 5.x). I also upgraded Webpack to the latest version.

Though I am still having the timeout problem, I enabled the log in IIS and found that it was throwing below error ERROR { Error: Uncaught (in promise): Error: Cannot find module './home/home.module.ngfactory'. when running node on server.

I investigated little further and found that when using Lazy loading and when we do publish the publish process doesn't generate the bundles for the lazy loaded modules for server (i.e. in ClientApp\dist folder).

You can try below to reproduce:

  1. Perform Clean (Build>Clean Solution)
  2. Then perform Publish.

In the Publish directory examine the files in ClientApp\dist, you will notice that the bundles for the lazy loaded modules are missing.

Normally, when we have already debug the application, it generate the bundles in ClientApp\dist and after this if we Publish (without performing Clean Solution) these bundles are copied to publish folder and the app works when deployed on server but its actually using un-optimized Debug build bundles.

Probably its something related to this:

https://github.com/angular/universal/issues/741#issuecomment-325508716

BTW, cant we integrate Angular CLI to build production bundles as well? Angular CLI will have support for Lazy Loading for Universal soon (https://github.com/angular/angular-cli/wiki/stories-universal-rendering#caveats). And in my opinion bundles produced by Angular CLI are very well optimized and smaller in size.

jrmcdona commented 7 years ago

which commands does dotnet publish run exactly? Does it run the webpack production builds (if yes, how does it know what your weback prod commands are) ? Been trying to figure out just want dotnet publish does!

(UPDATE: Nevermind I see it in the csproj)

davidsekar commented 7 years ago

@naveedahmed1 try the code from the pull request #410

It has the npm dependencies updated to latest, and lazy loading works as expected.

naveedahmed1 commented 7 years ago

@davidsekar are you sure commenting out resolve: { mainFields: ['main'] }, is the way to ensure server size bundles are created properly with Lazy loading? What about module-map-ngfactory-loader see this angular/universal#741 (comment)

The bundles generated for server side after commenting out resolve: { mainFields: ['main'] } for my project are of size 30 mb. Which is very huge. Also can we make use of @angular-devkit/build-optimizer and CommonsChunkPlugin to get better optimized bundles for Client as well as Server side builds?

@MarkPieszak mentioned above The server bundle is in client app and the size of that one doesn't matter as there is no "load" on the server, it just contains everything it needs to serialize the app but I think larger the file size more would be the load on the server, deploy it to IIS and monitor CPU and memory utilization for any server rendered request.

davidsekar commented 7 years ago

@naveedahmed1 - UglifyPlugin is already ON for client bundles in production mode, which is pretty effective. Not sure if @angular-devkit/build-optimizer can get client bundle smaller than current size (approx 300kb GZipped).

1) CommonsChunkPlugin - It is really helpful when you have 2 or more asynchronous/lazy loaded modules.

App -- Module1 (/lazy1) (uses ngx-bootstrap) -- Module2 (/lazy2) (uses ngx-bootstrap + ng-signalr)

Then using commonchunks plugin would prove useful, It automatically moves ngx-bootstrap to an asynchronous common chunk.

In current repo setup, there is just a single lazy/async loaded module. It doesn't help. Not sure if adding How To integrate CommonChunksPlugin is part of this repo's direction.

2) Running webpack bundle analyzer shows that the complete GZipped size of main-client.js is less than 300kb ( which includes complete ngx-bootstrap + momentjs, bootstrap css).

Visual comparison on various modules imported

Possible optimizations: a) Import just the required ngx-bootstrap modules. If you avoid, datepicker module then moment.js will not be added to your bundle. OR if you need datepicker, then include just the required language locale https://davidsekar.com/angular/optimize-moment-js-size-using-webpack

b) Remove duplicated bootstrap css styles. Check the issue #415