[{"data":1,"prerenderedAt":839},["ShallowReactive",2],{"technical-blog-page-content":3,"technical-blog-post-angular-speed-comparison":30,"technical-blog-author-angular-speed-comparison":6},{"id":4,"title":5,"author":6,"blogTags":6,"body":7,"customExcerpt":6,"date":6,"description":11,"excerpt":6,"extension":14,"h1":15,"image":6,"meta":16,"navigation":17,"path":18,"readingStats":19,"seo":24,"stem":28,"__hash__":29},"technicalBlogPage\u002Ftechnical-blog-page.md","Technical Blog Page",null,{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"md","Technical insights, stories and opinions from our team of consultants, analysts, developers and testers.",{},true,"\u002Ftechnical-blog-page",{"text":20,"minutes":21,"time":22,"words":23},"1 min read",0.29,17400,58,{"title":25,"description":26,"keywords":27},"Technology Insights | Audacia Digital Transformation","Technical insights, stories and opinions from leading software development company Audacia's teams of consultants, analysts, developers and testers.","Digital transformation technology, Technology blog, Technology insights, software development blog, software engineering blog","technical-blog-page","XD1gWfEur9Mu64WptQ5pF-e7Ej60LGiq7sRC58wOAeQ",{"id":31,"title":32,"author":33,"blogTags":34,"body":38,"customExcerpt":822,"date":823,"description":11,"excerpt":824,"extension":14,"h1":6,"image":825,"meta":826,"navigation":17,"path":827,"readingStats":828,"seo":833,"stem":837,"__hash__":838},"technicalBlog\u002Ftechnical-blog\u002Fangular-speed-comparison.md","Software development speed: Angular template comparisons","Liam Ward",[35,36,37],"Angular","Azure","NET",{"type":8,"value":39,"toc":819},[40,45,49,68,71,266,276,279,559,562,565,676,679,802,805,815],[41,42,44],"h2",{"id":43},"angular-software-development-projects","Angular software development projects",[46,47,48],"p",{},"For the past two years, the majority of Audacia's new web development projects have been built on a stack of:",[50,51,52,65],"ul",{},[53,54,55,64],"li",{},[56,57,63],"a",{"rel":58,"href":60,"target":61,"title":62},[59],"noopener","\u002Ftechnical-blog\u002Fwhat-is-net-core","_blank","What is .NET Core?","ASP.NET Core"," RESTful API",[53,66,67],{},"An Angular UI running within an ASP.NET Core project.",[46,69,70],{},"The ASP.NET Core UI running Angular was based on Microsoft's initial Angular 2 template. As a result of this, we had to configure the Angular build steps of the application within webpack and we were unable to take advantage of the capabilities of the Angular CLI. A typical Startup.cs file looked like the below:",[72,73,77],"pre",{"className":74,"code":75,"language":76,"meta":11,"style":11},"language-csharp shiki shiki-themes github-light","public class Startup\n{\n    \u002F\u002F Rest of code emitted for brevity\n    \u002F\u002F This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions configOptions)\n    {\n        if (env.IsDevelopment())\n        {\n            app.UseDeveloperExceptionPage();\n\n            app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions\n            {\n                HotModuleReplacement = true\n            });\n        }\n        \u002F\u002F Rest of code omitted for brevity\n    }\n}\n","csharp",[78,79,80,96,102,109,115,156,162,177,183,195,201,217,223,236,242,248,254,260],"code",{"__ignoreMap":11},[81,82,85,89,92],"span",{"class":83,"line":84},"line",1,[81,86,88],{"class":87},"sD7c4","public",[81,90,91],{"class":87}," class",[81,93,95],{"class":94},"s7eDp"," Startup\n",[81,97,98],{"class":83,"line":12},[81,99,101],{"class":100},"sgsFI","{\n",[81,103,105],{"class":83,"line":104},3,[81,106,108],{"class":107},"sAwPA","    \u002F\u002F Rest of code emitted for brevity\n",[81,110,112],{"class":83,"line":111},4,[81,113,114],{"class":107},"    \u002F\u002F This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n",[81,116,118,121,124,127,130,133,136,139,142,145,147,150,153],{"class":83,"line":117},5,[81,119,120],{"class":87},"    public",[81,122,123],{"class":87}," void",[81,125,126],{"class":94}," Configure",[81,128,129],{"class":100},"(",[81,131,132],{"class":94},"IApplicationBuilder",[81,134,135],{"class":94}," app",[81,137,138],{"class":100},", ",[81,140,141],{"class":94},"IHostingEnvironment",[81,143,144],{"class":94}," env",[81,146,138],{"class":100},[81,148,149],{"class":94},"IOptions",[81,151,152],{"class":94}," configOptions",[81,154,155],{"class":100},")\n",[81,157,159],{"class":83,"line":158},6,[81,160,161],{"class":100},"    {\n",[81,163,165,168,171,174],{"class":83,"line":164},7,[81,166,167],{"class":87},"        if",[81,169,170],{"class":100}," (env.",[81,172,173],{"class":94},"IsDevelopment",[81,175,176],{"class":100},"())\n",[81,178,180],{"class":83,"line":179},8,[81,181,182],{"class":100},"        {\n",[81,184,186,189,192],{"class":83,"line":185},9,[81,187,188],{"class":100},"            app.",[81,190,191],{"class":94},"UseDeveloperExceptionPage",[81,193,194],{"class":100},"();\n",[81,196,198],{"class":83,"line":197},10,[81,199,200],{"emptyLinePlaceholder":17},"\n",[81,202,204,206,209,211,214],{"class":83,"line":203},11,[81,205,188],{"class":100},[81,207,208],{"class":94},"UseWebpackDevMiddleware",[81,210,129],{"class":100},[81,212,213],{"class":87},"new",[81,215,216],{"class":94}," WebpackDevMiddlewareOptions\n",[81,218,220],{"class":83,"line":219},12,[81,221,222],{"class":100},"            {\n",[81,224,226,229,232],{"class":83,"line":225},13,[81,227,228],{"class":100},"                HotModuleReplacement ",[81,230,231],{"class":87},"=",[81,233,235],{"class":234},"sYu0t"," true\n",[81,237,239],{"class":83,"line":238},14,[81,240,241],{"class":100},"            });\n",[81,243,245],{"class":83,"line":244},15,[81,246,247],{"class":100},"        }\n",[81,249,251],{"class":83,"line":250},16,[81,252,253],{"class":107},"        \u002F\u002F Rest of code omitted for brevity\n",[81,255,257],{"class":83,"line":256},17,[81,258,259],{"class":100},"    }\n",[81,261,263],{"class":83,"line":262},18,[81,264,265],{"class":100},"}\n",[46,267,268,269,275],{},"Following our ",[56,270,274],{"rel":271,"href":272,"target":61,"title":273},[59],"\u002Ftechnical-blog\u002Fnet-core-2-0-released",".NET Core 2.0 Released","upgrade to ASP.NET Core 2+"," a new option became available, and a new template for Angular was released by Microsoft, that would allow us to use the Angular CLI to configure the application.",[46,277,278],{},"A typical Startup.cs file for an Angular CLI configured ASP.NET Core project looks like the below:",[72,280,282],{"className":74,"code":281,"language":76,"meta":11,"style":11},"public class Startup\n{\n    \u002F\u002F This method gets called by the runtime. Use this method to add services to the container.\n    \u002F\u002F For more information on how to configure your application, visit https:\u002F\u002Fgo.microsoft.com\u002Ffwlink\u002F?LinkID=398940\n    public void ConfigureServices(IServiceCollection services)\n    {\n        \u002F\u002F In production, the Angular files will be served from this directory\n        services.AddSpaStaticFiles(configuration =&gt;\n        {\n            configuration.RootPath = &quot;Client\u002Fdist&quot;;\n        });\n    }\n\n    \u002F\u002F This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n    public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n    {\n        app.UseSpa(spa =&gt;\n        {\n            \u002F\u002F This is the folder that contains your Angular CLI application\n            spa.Options.SourcePath = &quot;Client&quot;;\n    \n            if (env.IsDevelopment())\n            {\n                \u002F\u002F This is the method that should be run to start your application\n                \u002F\u002F This should call &quot;ng serve&quot; with no ssl\n                \u002F\u002F Here an npm script called start has been created\n                \u002F\u002Fto wrap around this command\n                spa.UseAngularCliServer(npmScript: &quot;start&quot;);\n            }\n        });\n    }\n}\n",[78,283,284,292,296,301,306,325,329,334,351,355,380,385,389,393,397,419,423,438,442,448,464,470,482,487,493,499,505,511,538,544,549,554],{"__ignoreMap":11},[81,285,286,288,290],{"class":83,"line":84},[81,287,88],{"class":87},[81,289,91],{"class":87},[81,291,95],{"class":94},[81,293,294],{"class":83,"line":12},[81,295,101],{"class":100},[81,297,298],{"class":83,"line":104},[81,299,300],{"class":107},"    \u002F\u002F This method gets called by the runtime. Use this method to add services to the container.\n",[81,302,303],{"class":83,"line":111},[81,304,305],{"class":107},"    \u002F\u002F For more information on how to configure your application, visit https:\u002F\u002Fgo.microsoft.com\u002Ffwlink\u002F?LinkID=398940\n",[81,307,308,310,312,315,317,320,323],{"class":83,"line":117},[81,309,120],{"class":87},[81,311,123],{"class":87},[81,313,314],{"class":94}," ConfigureServices",[81,316,129],{"class":100},[81,318,319],{"class":94},"IServiceCollection",[81,321,322],{"class":94}," services",[81,324,155],{"class":100},[81,326,327],{"class":83,"line":158},[81,328,161],{"class":100},[81,330,331],{"class":83,"line":164},[81,332,333],{"class":107},"        \u002F\u002F In production, the Angular files will be served from this directory\n",[81,335,336,339,342,345,348],{"class":83,"line":179},[81,337,338],{"class":100},"        services.",[81,340,341],{"class":94},"AddSpaStaticFiles",[81,343,344],{"class":100},"(configuration ",[81,346,347],{"class":87},"=&",[81,349,350],{"class":100},"gt;\n",[81,352,353],{"class":83,"line":185},[81,354,182],{"class":100},[81,356,357,360,362,365,368,371,374,377],{"class":83,"line":197},[81,358,359],{"class":100},"            configuration.RootPath ",[81,361,231],{"class":87},[81,363,364],{"class":87}," &",[81,366,367],{"class":100},"quot;Client",[81,369,370],{"class":87},"\u002F",[81,372,373],{"class":100},"dist",[81,375,376],{"class":87},"&",[81,378,379],{"class":100},"quot;;\n",[81,381,382],{"class":83,"line":203},[81,383,384],{"class":100},"        });\n",[81,386,387],{"class":83,"line":219},[81,388,259],{"class":100},[81,390,391],{"class":83,"line":225},[81,392,200],{"emptyLinePlaceholder":17},[81,394,395],{"class":83,"line":238},[81,396,114],{"class":107},[81,398,399,401,403,405,407,409,411,413,415,417],{"class":83,"line":244},[81,400,120],{"class":87},[81,402,123],{"class":87},[81,404,126],{"class":94},[81,406,129],{"class":100},[81,408,132],{"class":94},[81,410,135],{"class":94},[81,412,138],{"class":100},[81,414,141],{"class":94},[81,416,144],{"class":94},[81,418,155],{"class":100},[81,420,421],{"class":83,"line":250},[81,422,161],{"class":100},[81,424,425,428,431,434,436],{"class":83,"line":256},[81,426,427],{"class":100},"        app.",[81,429,430],{"class":94},"UseSpa",[81,432,433],{"class":100},"(spa ",[81,435,347],{"class":87},[81,437,350],{"class":100},[81,439,440],{"class":83,"line":262},[81,441,182],{"class":100},[81,443,445],{"class":83,"line":444},19,[81,446,447],{"class":107},"            \u002F\u002F This is the folder that contains your Angular CLI application\n",[81,449,451,454,456,458,460,462],{"class":83,"line":450},20,[81,452,453],{"class":100},"            spa.Options.SourcePath ",[81,455,231],{"class":87},[81,457,364],{"class":87},[81,459,367],{"class":100},[81,461,376],{"class":87},[81,463,379],{"class":100},[81,465,467],{"class":83,"line":466},21,[81,468,469],{"class":100},"    \n",[81,471,473,476,478,480],{"class":83,"line":472},22,[81,474,475],{"class":94},"            if",[81,477,170],{"class":100},[81,479,173],{"class":94},[81,481,176],{"class":100},[81,483,485],{"class":83,"line":484},23,[81,486,222],{"class":100},[81,488,490],{"class":83,"line":489},24,[81,491,492],{"class":107},"                \u002F\u002F This is the method that should be run to start your application\n",[81,494,496],{"class":83,"line":495},25,[81,497,498],{"class":107},"                \u002F\u002F This should call &quot;ng serve&quot; with no ssl\n",[81,500,502],{"class":83,"line":501},26,[81,503,504],{"class":107},"                \u002F\u002F Here an npm script called start has been created\n",[81,506,508],{"class":83,"line":507},27,[81,509,510],{"class":107},"                \u002F\u002Fto wrap around this command\n",[81,512,514,517,520,522,525,528,530,533,535],{"class":83,"line":513},28,[81,515,516],{"class":100},"                spa.",[81,518,519],{"class":94},"UseAngularCliServer",[81,521,129],{"class":100},[81,523,524],{"class":94},"npmScript",[81,526,527],{"class":100},": ",[81,529,376],{"class":87},[81,531,532],{"class":100},"quot;start",[81,534,376],{"class":87},[81,536,537],{"class":100},"quot;);\n",[81,539,541],{"class":83,"line":540},29,[81,542,543],{"class":100},"            }\n",[81,545,547],{"class":83,"line":546},30,[81,548,384],{"class":100},[81,550,552],{"class":83,"line":551},31,[81,553,259],{"class":100},[81,555,557],{"class":83,"line":556},32,[81,558,265],{"class":100},[46,560,561],{},"Thanks to this we were able to review our hosting process as well. We have previously hosted all of our applications via IIS, or Azure Web Apps on Windows. However, we could now think about static hosting of a site as all we need to host are the files generated by Angular along with a single html file.",[46,563,564],{},"As such we've been able to look at hosting within Linux using alternative web servers like nginx. A basic nginx configuration will look something like this:",[72,566,568],{"className":74,"code":567,"language":76,"meta":11,"style":11},"server {\n    listen 80;\n    server_name # server name goes here;\n    root \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n    index index.html index.htm;\n    location \u002F {\n        try_files $uri $uri\u002F \u002Findex.html;\n        # This will allow you to refresh page in your angular app. Which will not\n        give error 404.\n    }\n}\n",[78,569,570,575,586,599,624,629,639,652,657,668,672],{"__ignoreMap":11},[81,571,572],{"class":83,"line":84},[81,573,574],{"class":100},"server {\n",[81,576,577,580,583],{"class":83,"line":12},[81,578,579],{"class":100},"    listen ",[81,581,582],{"class":234},"80",[81,584,585],{"class":100},";\n",[81,587,588,591,594,597],{"class":83,"line":104},[81,589,590],{"class":100},"    server_name # server name ",[81,592,593],{"class":94},"goes",[81,595,596],{"class":94}," here",[81,598,585],{"class":100},[81,600,601,604,606,609,611,614,616,619,621],{"class":83,"line":111},[81,602,603],{"class":100},"    root ",[81,605,370],{"class":87},[81,607,608],{"class":100},"usr",[81,610,370],{"class":87},[81,612,613],{"class":100},"share",[81,615,370],{"class":87},[81,617,618],{"class":100},"nginx",[81,620,370],{"class":87},[81,622,623],{"class":100},"html;\n",[81,625,626],{"class":83,"line":117},[81,627,628],{"class":100},"    index index.html index.htm;\n",[81,630,631,634,636],{"class":83,"line":158},[81,632,633],{"class":100},"    location ",[81,635,370],{"class":87},[81,637,638],{"class":100}," {\n",[81,640,641,644,646,649],{"class":83,"line":164},[81,642,643],{"class":100},"        try_files $uri $uri",[81,645,370],{"class":87},[81,647,648],{"class":87}," \u002F",[81,650,651],{"class":100},"index.html;\n",[81,653,654],{"class":83,"line":179},[81,655,656],{"class":100},"        # This will allow you to refresh page in your angular app. Which will not\n",[81,658,659,662,665],{"class":83,"line":185},[81,660,661],{"class":100},"        give error ",[81,663,664],{"class":234},"404",[81,666,667],{"class":100},".\n",[81,669,670],{"class":83,"line":197},[81,671,259],{"class":100},[81,673,674],{"class":83,"line":203},[81,675,265],{"class":100},[46,677,678],{},"Using nginx we were able to drastically reduce the initial load times of our application. Below I have laid out a comparison between using the old and new ASP.NET Core Templates, as well as using nginx to host as a static site:",[680,681,685,711,785],"table",{"border":682,"className":683},0,[684],"styled-table",[686,687,688],"thead",{},[689,690,691,696,699,705],"tr",{},[692,693,695],"th",{"style":694},"text-align: center;","Run",[692,697,698],{"style":694},"Angular CLI on ASP.NET Core (ms)",[692,700,701,704],{"style":694},[81,702,703],{},"Angular CLI on ","NGINX (ms)",[692,706,707,710],{"style":694},[81,708,709],{},"ASP.NET Core MVC ","(ms)",[712,713,714,729,743,757,771],"tbody",{},[689,715,716,720,723,726],{},[717,718,719],"td",{"style":694},"1",[717,721,722],{"style":694},"329",[717,724,725],{"style":694},"312",[717,727,728],{"style":694},"600",[689,730,731,734,737,740],{},[717,732,733],{"style":694},"2",[717,735,736],{"style":694},"237",[717,738,739],{"style":694},"182",[717,741,742],{"style":694},"413",[689,744,745,748,751,754],{},[717,746,747],{"style":694},"3",[717,749,750],{"style":694},"185",[717,752,753],{"style":694},"340",[717,755,756],{"style":694},"970",[689,758,759,762,765,768],{},[717,760,761],{"style":694},"4",[717,763,764],{"style":694},"389",[717,766,767],{"style":694},"316",[717,769,770],{"style":694},"723",[689,772,773,776,779,782],{},[717,774,775],{"style":694},"5",[717,777,778],{"style":694},"371",[717,780,781],{"style":694},"210",[717,783,784],{"style":694},"796",[786,787,788],"tfoot",{},[689,789,790,793,796,799],{},[717,791,792],{"style":694},"Avg",[717,794,795],{"style":694},"302",[717,797,798],{"style":694},"270",[717,800,801],{"style":694},"700",[46,803,804],{},"As you can see moving to the new template is massively beneficial, giving us a >50% increase in performance. Moving to nginx provides another, albeit smaller, improvement to performance. One that we hope will get better as the hosted files get larger.",[46,806,807,808,814],{},"We're now moving all our new ",[56,809,813],{"rel":810,"href":811,"target":61,"title":812},[59],"\u002Fprojects\u002F","Projects","projects",", and migrating older projects, to use Angular CLI for this reason.",[816,817,818],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":11,"searchDepth":12,"depth":12,"links":820},[821],{"id":43,"depth":12,"text":44},"For the past two years, the majority of Audacia's new web development projects have been built on a stack of an ASP.NET Core RESTful API and An Angular UI running within an ASP.NET Core project. For our latest insight we conducted a speed experiment to compare the two. ","2018-11-16T00:00:00.000Z","[object Object]","\u002Fimg\u002Ftechnical-blog\u002Fangular.jpg",{},"\u002Ftechnical-blog\u002Fangular-speed-comparison",{"text":829,"minutes":830,"time":831,"words":832},"5 min read",4.215,252900,843,{"title":834,"description":835,"keywords":836},"Software development speed: Angular template comparisons | Audacia","Software development company Audacia discusses how you can improve performance by 50% through using Angular and ASP.NET Core 2.","ASP.NET Core, Angular, Web development, Web development projects, Web development performance, Web application, Bespoke web application, Web application development, .NET Core","technical-blog\u002Fangular-speed-comparison","mu_ieZaclBrA48Kdnrbql8XtcEMtCwPVXkwXgF1UePQ",1778145952070]