Ahead-of-Time Compilation - ts - COOKBOOK - Angular

文章推薦指數: 80 %
投票人數:10人

The ahead-of-time (AOT) compiler can catch template errors early and improve performance by compiling at build time. Ahead-of-time (AOT) vs just-in-time (JIT). Angularv2ArchiveSiteMenuCurrentAngularDocsGetStartedDocsHomeCoreDocumentationQuickstartCLIQuickstartGuide1.Overview2.Setup3.LearningAngular4.Architecture5.TheRootModule6.DisplayingData7.UserInput8.Forms9.DependencyInjection10.TemplateSyntax11.CheatSheet12.StyleGuide13.Glossary14.ChangeLogAPIReferenceAdditionalDocumentationTutorial1.Introduction2.TheHeroEditor3.Master/Detail4.MultipleComponents5.Services6.Routing7.HTTPAdvancedAnimationsAttributeDirectivesBrowsersupportComponentStylesDeploymentHierarchicalInjectorsReactiveFormsHTTPClientLifecycleHooksNgModulesNpmPackagesPipesRouting&NavigationSecuritySetupAnatomyStructuralDirectivesTestingTypeScriptConfigurationUpgradingfromAngularJSWebpack:anintroductionCookbookOverviewAhead-of-TimeCompilationAngularJStoAngularComponentInteractionDependencyInjectionDynamicComponentLoaderDynamicFormsFormValidationInternationalization(i18n)NgModuleFAQsSettheDocumentTitleTypeScripttoJavaScriptVisualStudio2015QuickStartAngularforTypeScriptAngularforTypeScriptAngularforJavaScriptLearnhowtouseahead-of-timecompilation.Thiscookbookdescribeshowtoradicallyimproveperformancebycompilingahead-of-time(AOT) duringabuildprocess. Contents Overview Ahead-of-time(AOT)vsjust-in-time(JIT) WhydoAOTcompilation? CompilewithAOT Bootstrap Treeshaking Rollup RollupPlugins RunRollup Loadthebundle Servetheapp AOTQuickStartsourcecode Workflowandconveniencescript DevelopJITalongwithAOT TourofHeroes JITindevelopment,AOTinproduction Treeshaking Runningtheapplication InspecttheBundle Overview AnAngularapplicationconsistslargelyofcomponentsandtheirHTMLtemplates. Beforethebrowsercanrendertheapplication, thecomponentsandtemplatesmustbeconvertedtoexecutableJavaScriptbytheAngularcompiler. WatchcompilerauthorTobiasBoschexplaintheAngularCompileratAngularConnect2016. Youcancompiletheappinthebrowser,atruntime,astheapplicationloads,usingthejust-in-time(JIT)compiler. Thisisthestandarddevelopmentapproachshownthroughoutthedocumentation. It'sgreatbutithasshortcomings. JITcompilationincursaruntimeperformancepenalty. Viewstakelongertorenderbecauseofthein-browsercompilationstep. TheapplicationisbiggerbecauseitincludestheAngularcompiler andalotoflibrarycodethattheapplicationwon'tactuallyneed. Biggerappstakelongertotransmitandareslowertoload. Compilationcanuncovermanycomponent-templatebindingerrors. JITcompilationdiscoversthematruntime,whichislateintheprocess. Theahead-of-time(AOT)compilercancatchtemplateerrorsearlyandimproveperformance bycompilingatbuildtime. Ahead-of-time(AOT)vsjust-in-time(JIT) ThereisactuallyonlyoneAngularcompiler.ThedifferencebetweenAOTandJITisamatteroftimingandtooling. WithAOT,thecompilerrunsonceatbuildtimeusingonesetoflibraries; withJITitrunseverytimeforeveryuseratruntimeusingadifferentsetoflibraries. WhydoAOTcompilation? Fasterrendering WithAOT,thebrowserdownloadsapre-compiledversionoftheapplication. Thebrowserloadsexecutablecodesoitcanrendertheapplicationimmediately,withoutwaitingtocompiletheappfirst. Fewerasynchronousrequests ThecompilerinlinesexternalHTMLtemplatesandCSSstylesheetswithintheapplicationJavaScript, eliminatingseparateajaxrequestsforthosesourcefiles. SmallerAngularframeworkdownloadsize There'snoneedtodownloadtheAngularcompileriftheappisalreadycompiled. ThecompilerisroughlyhalfofAngularitself,soomittingitdramaticallyreducestheapplicationpayload. Detecttemplateerrorsearlier TheAOTcompilerdetectsandreportstemplatebindingerrorsduringthebuildstep beforeuserscanseethem. Bettersecurity AOTcompilesHTMLtemplatesandcomponentsintoJavaScriptfileslongbeforetheyareservedtotheclient. Withnotemplatestoreadandnoriskyclient-sideHTMLorJavaScriptevaluation, therearefeweropportunitiesforinjectionattacks. CompilewithAOT Preparingforofflinecompilationtakesafewsimplesteps. TaketheSetupasastartingpoint. Afewminorchangestotheloneapp.componentleadtothesetwoclassandHTMLfiles:

HelloAngular

ListofHeroes

{{hero}}
import{Component}from'@angular/core'; @Component({ selector:'my-app', templateUrl:'./app.component.html' }) exportclassAppComponent{ showHeading=true; heroes=['Magneta','Bombasto','Magma','Tornado']; toggleHeading(){ this.showHeading=!this.showHeading; } } Installafewnewnpmdependencieswiththefollowingcommand: npminstall@angular/compiler-cli@angular/platform-server--saveYouwillrunthengccompilerprovidedinthe@angular/compiler-clinpmpackage insteadoftheTypeScriptcompiler(tsc). ngcisadrop-inreplacementfortscandisconfiguredmuchthesameway. ngcrequiresitsowntsconfig.jsonwithAOT-orientedsettings. Copytheoriginalsrc/tsconfig.jsontoafilecalledtsconfig-aot.jsonontheprojectroot, thenmodifyitasfollows. { "compilerOptions":{ "target":"es5", "module":"es2015", "moduleResolution":"node", "sourceMap":true, "emitDecoratorMetadata":true, "experimentalDecorators":true, "lib":["es2015","dom"], "noImplicitAny":true, "suppressImplicitAnyIndexErrors":true }, "files":[ "src/app/app.module.ts", "src/main.ts" ], "angularCompilerOptions":{ "genDir":"aot", "skipMetadataEmit":true } } ThecompilerOptionssectionisunchangedexceptforoneproperty. Setthemoduletoes2015. ThisisimportantasexplainedlaterintheTreeShakingsection. What'sreallynewisthengcsectionatthebottomcalledangularCompilerOptions. ItsgenDirpropertytellsthecompiler tostorethecompiledoutputfilesinanewaotfolder. The"skipMetadataEmit":truepropertypreventsthecompilerfromgeneratingmetadatafileswiththecompiledapplication. MetadatafilesarenotnecessarywhentargetingTypeScriptfiles,sothereisnoreasontoincludethem. Component-relativetemplateURLS TheAOTcompilerrequiresthat@ComponentURLSforexternaltemplatesandCSSfilesbecomponent-relative. Thatmeansthatthevalueof@Component.templateUrlisaURLvaluerelativetothecomponentclassfile. Forexample,an'app.component.html'URLmeansthatthetemplatefileisasiblingofitscompanionapp.component.tsfile. WhileJITappURLsaremoreflexible,stickwithcomponent-relativeURLsforcompatibilitywithAOTcompilation. Compilingtheapplication InitiateAOTcompilationfromthecommandlineusingthepreviouslyinstalledngccompilerbyexecuting: node_modules/.bin/ngc-ptsconfig-aot.jsonWindowsusersshouldsurroundthengccommandindoublequotes: "node_modules/.bin/ngc"-ptsconfig-aot.jsonngcexpectsthe-pswitchtopointtoatsconfig.jsonfileorafoldercontainingatsconfig.jsonfile. Afterngccompletes,lookforacollectionofNgFactoryfilesintheaotfolder. TheaotfolderisthedirectoryspecifiedasgenDirintsconfig-aot.json. Thesefactoryfilesareessentialtothecompiledapplication. Eachcomponentfactorycreatesaninstanceofthecomponentatruntimebycombiningtheoriginalclassfile andaJavaScriptrepresentationofthecomponent'stemplate. Notethattheoriginalcomponentclassisstillreferencedinternallybythegeneratedfactory. Thecuriouscanopenaot/app.component.ngfactory.tstoseetheoriginalAngulartemplatesyntax compiledtoTypeScript,itsintermediateform. JITcompilationgeneratesthesesameNgFactoriesinmemorywheretheyarelargelyinvisible. AOTcompilationrevealsthemasseparate,physicalfiles. DonotedittheNgFactories!Re-compilationreplacesthesefilesandalleditswillbelost. Bootstrap TheAOTapproachchangesapplicationbootstrapping. InsteadofbootstrappingAppModule,youbootstraptheapplicationwiththegeneratedmodulefactory,AppModuleNgFactory. Makeacopyofmain.tsandnameitmain-jit.ts. ThisistheJITversion;setitasideasyoumayneeditlater. Openmain.tsandconvertittoAOTcompilation. SwitchfromtheplatformBrowserDynamic.bootstrapusedinJITcompilationto platformBrowser().bootstrapModuleFactoryandpassintheAOT-generatedAppModuleNgFactory. HereisAOTbootstrapinmain.tsnexttotheoriginalJITversion: import{platformBrowser}from'@angular/platform-browser'; import{AppModuleNgFactory}from'../aot/src/app/app.module.ngfactory'; console.log('RunningAOTcompiled'); platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); import{platformBrowserDynamic}from'@angular/platform-browser-dynamic'; import{AppModule}from'./app/app.module'; console.log('RunningJITcompiled'); platformBrowserDynamic().bootstrapModule(AppModule); Besuretorecompilewithngc! Treeshaking AOTcompilationsetsthestageforfurtheroptimizationthroughaprocesscalledtreeshaking. Atreeshakerwalksthedependencygraph,toptobottom,andshakesoutunusedcodelike deadleavesinatree. Treeshakingcangreatlyreducethedownloadedsizeoftheapplication byremovingunusedportionsofbothsourceandlibrarycode. Infact,mostofthereductioninsmallappscomesfromremovingunreferencedAngularfeatures. Forexample,thisdemoapplicationdoesn'tuseanythingfromthe@angular/formslibrary. Thereisnoreasontodownloadforms-relatedAngularcodeandtreeshakingensuresthatyoudon't. TreeshakingandAOTcompilationareseparatesteps. TreeshakingcanonlytargetJavaScriptcode. AOTcompilationconvertsmoreoftheapplicationtoJavaScript, whichinturnmakesmoreoftheapplication"treeshakable". Rollup ThiscookbookillustratesatreeshakingutilitycalledRollup. Rollupstaticallyanalyzestheapplicationbyfollowingthetrailofimportandexportstatements. Itproducesafinalcodebundlethatexcludescodethatisexported,butneverimported. RollupcanonlytreeshakeES2015moduleswhichhaveimportandexportstatements. Recallthattsconfig-aot.jsonisconfiguredtoproduceES2015modules. It'snotimportantthatthecodeitselfbewrittenwithES2015syntaxsuchasclassandconst. WhatmattersisthatthecodeusesESimportandexportstatementsratherthanrequirestatements. Intheterminalwindow,installtheRollupdependencieswiththiscommand: npminstallrolluprollup-plugin-node-resolverollup-plugin-commonjsrollup-plugin-uglify--save-devNext,createaconfigurationfile(rollup-config.js) intheprojectrootdirectorytotellRolluphowtoprocesstheapplication. Thecookbookconfigurationfilelookslikethis. importrollupfrom'rollup' importnodeResolvefrom'rollup-plugin-node-resolve' importcommonjsfrom'rollup-plugin-commonjs'; importuglifyfrom'rollup-plugin-uglify' exportdefault{ entry:'src/main.js', dest:'src/build.js',//outputasingleapplicationbundle sourceMap:false, format:'iife', onwarn:function(warning){ //Skipcertainwarnings //shouldintercept...butdoesn'tinsomerollupversions if(warning.code==='THIS_IS_UNDEFINED'){return;} //interceptsinsomerollupversions if(warning.indexOf("The'this'keywordisequivalentto'undefined'")>-1){return;} //console.warneverythingelse console.warn(warning.message); }, plugins:[ nodeResolve({jsnext:true,module:true}), commonjs({ include:'node_modules/rxjs/**', }), uglify() ] } ThisconfigfiletellsRollupthattheappentrypointissrc/app/main.js. ThedestattributetellsRolluptocreateabundlecalledbuild.jsinthedistfolder. ItoverridesthedefaultonwarnmethodinordertoskipannoyingmessagesabouttheAOTcompiler'suseofthethiskeyword. Thenextsectioncoversthepluginsinmoredepth. RollupPlugins OptionalpluginsfilterandtransformtheRollupinputsandoutput. RxJS RollupexpectsapplicationsourcecodetouseES2015modules. NotallexternaldependenciesarepublishedasES2015modules. Infact,mostarenot.ManyofthemarepublishedasCommonJSmodules. TheRxJsObservablelibraryisanessentialAngulardependencypublishedasanES5JavaScriptCommonJSmodule. Luckily,thereisaRolluppluginthatmodifiesRxJs tousetheESimportandexportstatementsthatRolluprequires. RollupthenpreservesthepartsofRxJSreferencedbytheapplication inthefinalbundle.Usingitisstraigthforward.Addthefollowingto thepluginsarrayinrollup-config.js: commonjs({ include:'node_modules/rxjs/**', }), Minification Rolluptreeshakingreducescodesizeconsiderably.Minificationmakesitsmallerstill. ThiscookbookreliesontheuglifyRollupplugintominifyandmanglethecode. Addthefollowingtothepluginsarray: uglify() Inaproductionsetting,youwouldalsoenablegziponthewebservertocompress thecodeintoanevensmallerpackagegoingoverthewire. RunRollup ExecutetheRollupprocesswiththiscommand: node_modules/.bin/rollup-crollup-config.jsWindowsusersshouldsurroundtherollupcommandindoublequotes: "node_modules/.bin/rollup"-crollup-config.jsLoadthebundle LoadingthegeneratedapplicationbundledoesnotrequireamoduleloaderlikeSystemJS. RemovethescriptsthatconcernSystemJS. Instead,loadthebundlefileusingasingle Servetheapp You'llneedawebservertohosttheapplication. Usethesamelite-serveremployedelsewhereinthedocumentation: npmrunliteTheserverstarts,launchesabrowser,andtheappshouldappear. AOTQuickStartsourcecode Here'sthepertinentsourcecode:

HelloAngular

ListofHeroes

{{hero}}
import{Component}from'@angular/core'; @Component({ selector:'my-app', templateUrl:'./app.component.html' }) exportclassAppComponent{ showHeading=true; heroes=['Magneta','Bombasto','Magma','Tornado']; toggleHeading(){ this.showHeading=!this.showHeading; } } import{platformBrowser}from'@angular/platform-browser'; import{AppModuleNgFactory}from'../aot/src/app/app.module.ngfactory'; console.log('RunningAOTcompiled'); platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); Aheadoftimecompilation Loading... { "compilerOptions":{ "target":"es5", "module":"es2015", "moduleResolution":"node", "sourceMap":true, "emitDecoratorMetadata":true, "experimentalDecorators":true, "lib":["es2015","dom"], "noImplicitAny":true, "suppressImplicitAnyIndexErrors":true }, "files":[ "src/app/app.module.ts", "src/main.ts" ], "angularCompilerOptions":{ "genDir":"aot", "skipMetadataEmit":true } } importrollupfrom'rollup' importnodeResolvefrom'rollup-plugin-node-resolve' importcommonjsfrom'rollup-plugin-commonjs'; importuglifyfrom'rollup-plugin-uglify' exportdefault{ entry:'src/main.js', dest:'src/build.js',//outputasingleapplicationbundle sourceMap:false, format:'iife', onwarn:function(warning){ //Skipcertainwarnings //shouldintercept...butdoesn'tinsomerollupversions if(warning.code==='THIS_IS_UNDEFINED'){return;} //interceptsinsomerollupversions if(warning.indexOf("The'this'keywordisequivalentto'undefined'")>-1){return;} //console.warneverythingelse console.warn(warning.message); }, plugins:[ nodeResolve({jsnext:true,module:true}), commonjs({ include:'node_modules/rxjs/**', }), uglify() ] } Workflowandconveniencescript You'llrebuildtheAOTversionoftheapplicationeverytimeyoumakeachange. Thosenpmcommandsarelonganddifficulttoremember. Addthefollowingnpmconveniencescripttothepackage.jsonsoyoucancompileandrollupinonecommand. { "scripts":{ "build:aot":"ngc-ptsconfig-aot.json&&rollup-crollup-config.js" } }Openaterminalwindowandtryit. npmrunbuild:aot DevelopJITalongwithAOT AOTcompilationandrolluptogethertakeseveralseconds. YoumaybeabletodevelopiterativelyalittlefasterwithSystemJSandJIT. Thesamesourcecodecanbebuiltbothways.Here'sonewaytodothat. Makeacopyofindex.htmlandcallitindex-jit.html. Deletethescriptatthebottomofindex-jit.htmlthatloadsbundle.js RestoretheSystemJSscriptslikethis: Noticetheslightchangetothesystem.importwhichnowspecifiessrc/app/main-jit. That'stheJITversionofthebootstrapfilethatwepreservedabove. Openadifferentterminalwindowandenternpmstart. npmstartThatcompilestheappwithJITandlaunchestheserver. Theserverloadsindex.htmlwhichisstilltheAOTversion,whichyoucanconfirminthebrowserconsole. Changetheaddressbartoindex-jit.htmlanditloadstheJITversion. Thisisalsoevidentinthebrowserconsole. Developasusual. TheserverandTypeScriptcompilerarein"watchmode"soyourchangesarereflectedimmediatelyinthebrowser. ToseethosechangesinAOT,switchtotheoriginalterminalandre-runnpmrunbuild:aot. Whenitfinishes,gobacktothebrowserandusethebackbuttonto returntotheAOTversioninthedefaultindex.html. NowyoucandevelopJITandAOT,side-by-side. TourofHeroes ThesampleaboveisatrivialvariationoftheQuickStartapplication. Inthissectionyouapplywhatyou'velearnedaboutAOTcompilationandtreeshaking toanappwithmoresubstance,theTourofHeroesapplication. JITindevelopment,AOTinproduction TodayAOTcompilationandtreeshakingtakemoretimethanispracticalfordevelopment.Thatwillchangesoon. Fornow,it'sbesttoJITcompileindevelopmentandswitchtoAOTcompilationbeforedeployingtoproduction. Fortunately,thesourcecodecanbecompiledeitherwaywithoutchangeifyouaccountforafewkeydifferences. index.html TheJITandAOTappsrequiretheirownindex.htmlfilesbecausetheysetupandlaunchsodifferently. Heretheyareforcomparison: AngularTourofHeroes Loading... AngularTourofHeroes Loading... TheJITversionreliesonSystemJStoloadindividualmodules. Itsscriptsappearinitsindex.html. TheAOTversionloadstheentireapplicationinasinglescript,aot/dist/build.js. ItdoesnotneedSystemJS,sothatscriptisabsentfromitsindex.html main.ts JITandAOTapplicationsbootinmuchthesamewaybutrequiredifferentAngularlibrariestodoso. Thekeydifferences,coveredintheBootstrapsectionabove, areevidentinthesemainfileswhichcanandshouldresideinthesamefolder: import{platformBrowser}from'@angular/platform-browser'; import{AppModuleNgFactory}from'../aot/src/app/app.module.ngfactory'; platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); import{platformBrowserDynamic}from'@angular/platform-browser-dynamic'; import{AppModule}from'./app/app.module'; platformBrowserDynamic().bootstrapModule(AppModule); TypeScriptconfiguration JIT-compiledapplicationstranspiletocommonjsmodules. AOT-compiledapplicationstranspiletoES2015/ES6modulestofacilitatetreeshaking. AOTrequiresitsownTypeScriptconfigurationsettingsaswell. You'llneedseparateTypeScriptconfigurationfilessuchasthese: { "compilerOptions":{ "target":"es5", "module":"es2015", "moduleResolution":"node", "sourceMap":true, "emitDecoratorMetadata":true, "experimentalDecorators":true, "lib":["es2015","dom"], "noImplicitAny":true, "suppressImplicitAnyIndexErrors":true, "typeRoots":[ "../../node_modules/@types/" ] }, "files":[ "src/app/app.module.ts", "src/main-aot.ts" ], "angularCompilerOptions":{ "genDir":"aot", "skipMetadataEmit":true } } { "compilerOptions":{ "target":"es5", "module":"commonjs", "moduleResolution":"node", "sourceMap":true, "emitDecoratorMetadata":true, "experimentalDecorators":true, "lib":["es2015","dom"], "noImplicitAny":true, "suppressImplicitAnyIndexErrors":true } } Inthefilestructureofthisparticularsampleproject, thenode_modulesfolderhappenstobetwolevelsupfromtheprojectroot. Therefore,"typeRoots"mustbesetto"../../node_modules/@types/". Inamoretypicalproject,node_moduleswouldbeasiblingoftsconfig-aot.json and"typeRoots"wouldbesetto"node_modules/@types/". Edityourtsconfig-aot.jsontofityourproject'sfilestructure. Treeshaking Rollupdoesthetreeshakingasbefore. importrollupfrom'rollup' importnodeResolvefrom'rollup-plugin-node-resolve' importcommonjsfrom'rollup-plugin-commonjs'; importuglifyfrom'rollup-plugin-uglify' //pathsarerelativetotheexecutionpath exportdefault{ entry:'src/main-aot.js', dest:'aot/dist/build.js',//outputasingleapplicationbundle sourceMap:true, sourceMapFile:'aot/dist/build.js.map', format:'iife', onwarn:function(warning){ //Skipcertainwarnings //shouldintercept...butdoesn'tinsomerollupversions if(warning.code==='THIS_IS_UNDEFINED'){return;} //interceptsinsomerollupversions if(warning.indexOf("The'this'keywordisequivalentto'undefined'")>-1){return;} //console.warneverythingelse console.warn(warning.message); }, plugins:[ nodeResolve({jsnext:true,module:true}), commonjs({ include:['node_modules/rxjs/**'] }), uglify() ] } Runningtheapplication ThegeneralaudienceinstructionsforrunningtheAOTbuildoftheTourofHeroesapparenotready. Thefollowinginstructionspresupposethatyouhaveclonedthe angular.io githubrepositoryandprepareditfordevelopmentasexplainedintherepo'sREADME.md. TheTourofHeroessourcecodeisinthepublic/docs/_examples/toh-6/tsfolder. RuntheJIT-compiledappwithnpmstartasforallotherJITexamples. CompilingwithAOTpresupposescertainsupportingfiles,mostofthemdiscussedabove. AngularTourofHeroes Loading... varfs=require('fs'); varresources=[ 'node_modules/core-js/client/shim.min.js', 'node_modules/zone.js/dist/zone.min.js', 'src/styles.css' ]; resources.map(function(f){ varpath=f.split('/'); vart='aot/'+path[path.length-1]; fs.createReadStream(f).pipe(fs.createWriteStream(t)); }); importrollupfrom'rollup' importnodeResolvefrom'rollup-plugin-node-resolve' importcommonjsfrom'rollup-plugin-commonjs'; importuglifyfrom'rollup-plugin-uglify' //pathsarerelativetotheexecutionpath exportdefault{ entry:'src/main-aot.js', dest:'aot/dist/build.js',//outputasingleapplicationbundle sourceMap:true, sourceMapFile:'aot/dist/build.js.map', format:'iife', onwarn:function(warning){ //Skipcertainwarnings //shouldintercept...butdoesn'tinsomerollupversions if(warning.code==='THIS_IS_UNDEFINED'){return;} //interceptsinsomerollupversions if(warning.indexOf("The'this'keywordisequivalentto'undefined'")>-1){return;} //console.warneverythingelse console.warn(warning.message); }, plugins:[ nodeResolve({jsnext:true,module:true}), commonjs({ include:['node_modules/rxjs/**'] }), uglify() ] } { "compilerOptions":{ "target":"es5", "module":"es2015", "moduleResolution":"node", "sourceMap":true, "emitDecoratorMetadata":true, "experimentalDecorators":true, "lib":["es2015","dom"], "noImplicitAny":true, "suppressImplicitAnyIndexErrors":true, "typeRoots":[ "../../node_modules/@types/" ] }, "files":[ "src/app/app.module.ts", "src/main-aot.ts" ], "angularCompilerOptions":{ "genDir":"aot", "skipMetadataEmit":true } } Extendthescriptssectionofthepackage.jsonwiththesenpmscripts: { "scripts":{ "build:aot":"ngc-ptsconfig-aot.json&&rollup-crollup-config.js", "serve:aot":"lite-server-cbs-config.aot.json" } }CopytheAOTdistributionfilesintothe/aotfolderwiththenodescript: nodecopy-dist-filesYouwon'tdothatagainuntilthereareupdatestozone.jsorthecore-jsshimforoldbrowsers. NowAOT-compiletheappandlaunchitwiththelite-server: npmrunbuild:aot&&npmrunserve:aot InspecttheBundle It'sfascinatingtoseewhatthegeneratedJavaScriptbundlelookslikeafterRollup. Thecodeisminified,soyouwon'tlearnmuchfrominspectingthebundledirectly. Butthesource-map-explorer toolcanbequiterevealing. Installit: npminstallsource-map-explorer--save-devRunthefollowingcommandtogeneratethemap. node_modules/.bin/source-map-exploreraot/dist/build.js Thesource-map-exploreranalyzesthesourcemapgeneratedwiththebundleanddrawsamapofalldependencies, showingexactlywhichapplicationandAngularmodulesandclassesareincludedinthebundle. Here'sthemapforTourofHeroes.


請為這篇文章評分?