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.