[AngularJS2]AngularJS2应用启动过程

当浏览器访问Angular应用时,首先index.html页面被加载。









然后,inline.bundle.js被浏览器加载执行。在inline.bundle.js中定义了函数webpackJsonp(...)__webpack_require__(...)
通过函数webpackJsonp(chunkIds, moreModules, executeModules)可以向应用添加代码块,参数chunkIds是代码块的ID, moreModules是代码块中包含的模块,而executeModules指定了需要执行的模块。webpackJsonp(...)调用__webpack_require__()执行executeModules指定的模块。

/******/ (function(modules) { // webpackBootstrap
/******/     // install a JSONP callback for chunk loading
/******/     var parentJsonpFunction = window["webpackJsonp"];
/******/     window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
/******/
/******/         ... ...
/******/
/******/         if(executeModules) {
/******/             for(i=0; i < executeModules.length; i++) {
/******/                 result = __webpack_require__(__webpack_require__.s = executeModules[i]);
/******/             }
/******/         }
/******/         return result;
/******/     };
/******/
/******/     ... ...
/******/
/******/     // The require function
/******/     function __webpack_require__(moduleId) {
/******/
/******/         ... ...
/******/
/******/         // Execute the module function
/******/         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/         ... ...
/******/
/******/         // Return the exports of the module
/******/         return module.exports;
/******/     }
/******/
/******/ })
/******/ ([]);

当main.bundle.js被浏览器加载执行,函数webpackJsonp(["main"], ..., [0])会被调用执行。ID为“0”的模被块被执行,在执行中”../../../../../src/main.ts”模块也会被执行__webpack_require__("../../../../../src/main.ts")

这里就是angular应用入口点: platformBrowserDynamic().bootstrapModule(AppModule));

webpackJsonp(["main"],{

"../../../../../src/main.ts":

(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("Object.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n

var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__(\"../../../core/esm5/core.js\");
var __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__ = 
    __webpack_require__(\"../../../platform-browser-dynamic/esm5/platform-browser-dynamic.js\");
var __WEBPACK_IMPORTED_MODULE_2__app_app_module__ = __webpack_require__(\"../../../../../src/app/app.module.ts\");

Object(__WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__[\"a\" /* platformBrowserDynamic */])()
    .bootstrapModule(__WEBPACK_IMPORTED_MODULE_2__app_app_module__[\"a\" /* AppModule */])); 

/***/ 0:
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__("../../../../webpack-dev-server/client/index.js?http://0.0.0.0:0");
module.exports = __webpack_require__("../../../../../src/main.ts");

/***/ })

},[0]);

platformBrowserDynamic的定义可以在angular源代码packages\platform-browser-dynamic\src\platform-browser-dynamic.ts中找到。

export const platformBrowserDynamic = createPlatformFactory
    ( platformCoreDynamic, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);

createPlatformFactory()创建并返回对应的PlatformRef对象,PlatformRef是应用程序运行的环境。在packages\core\src\core\application_ref.ts中我们可以找到PlatformRef的定义。

export class PlatformRef {
  private _modules: NgModuleRef<any>[] = [];
  private _destroyListeners: Function[] = [];
  private _destroyed: boolean = false;

  bootstrapModule<M>(
      moduleType: Type<M>, compilerOptions: (CompilerOptions&BootstrapOptions)|
      Array<CompilerOptions&BootstrapOptions> = []): Promise<NgModuleRef<M>> {
    const compilerFactory: CompilerFactory = this.injector.get(CompilerFactory);
    const options = optionsReducer({}, compilerOptions);
    const compiler = compilerFactory.createCompiler([options]);

    return compiler.compileModuleAsync(moduleType)
        .then((moduleFactory) => this.bootstrapModuleFactory(moduleFactory, options));
  }
}

在BootstrapModule()中,首先是模块被编译, 然后调用BootstrapModuleFactory()_moduleDoBootstrap()。在_moduleDoBootstrap()中,我们可以看到对象ApplicationRefbootstrap()方法被调用,参数是模块的每一Component。

const appRef = moduleRef.injector.get(ApplicationRef) as ApplicationRef;
if (moduleRef._bootstrapComponents.length > 0) {
  moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));

ApplicationRef.bootstrap(componentOrFactory: ComponentFactory<C>|Type<C>, rootSelectorOrNode?: string|any)的实现:

const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);

compRef.onDestroy(() => { this._unloadComponent(compRef); });
const testability = compRef.injector.get(Testability, null);
if (testability) {
  compRef.injector.get(TestabilityRegistry)
      .registerApplication(compRef.location.nativeElement, testability);
}

this._loadComponent(compRef);

在这个函数里,componentFactoryComponentFactory_对象的一个实例。componentFactory.create()的定义可以在packages\core\source\view\ref.ts中找到。

   class ComponentFactory_ extends ComponentFactory<any>   
    /**
   * Creates a new component.
   */
  create(
      injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any,
      ngModule?: NgModuleRef<any>): ComponentRef<any> {
    if (!ngModule) {
      throw new Error('ngModule should be provided');
    }
    const viewDef = resolveDefinition(this.viewDefFactory);
    const componentNodeIndex = viewDef.nodes[0].element !.componentProvider !.nodeIndex;
    const view = Services.createRootView(
        injector, projectableNodes || [], rootSelectorOrNode, viewDef, ngModule, EMPTY_CONTEXT);
    const component = asProviderData(view, componentNodeIndex).instance;
    if (rootSelectorOrNode) {
      view.renderer.setAttribute(asElementData(view, 0).renderElement, 'ng-version', VERSION.full);
    }

    return new ComponentRef_(view, new ViewRef_(view), component);
  }
}

core\src\view\view.ts: function createRootView()->core\src\view\services.ts: function createProdRootView()->function createRootData()/function createRootView()

export function createRootView(root: RootData, def: ViewDefinition, context?: any): ViewData {
  const view = createView(root, root.renderer, null, null, def);
  initView(view, context, context);
  createViewNodes(view);
  return view;
}

createViewNode()会遍历view.def.nodes。如果node的类型是NodeFlags.TypeElement,createElement()会被调用在DOM树上创建节点,如果这个节点还是一个component, componentView也会被创建。
最后,调用execComponentViewsAction(view, ViewAction.CreateViewNodes),如果子节点是componentView, 递归的调用callViewAction()-> createViewNodes()来创建子节点,直到没有子节点是component.

function createViewNodes(view: ViewData) {
  let renderHost: any;
  if (isComponentView(view)) {
    const hostDef = view.parentNodeDef;
    renderHost = asElementData(view.parent !, hostDef !.parent !.nodeIndex).renderElement;
  }
  const def = view.def;
  const nodes = view.nodes;
  for (let i = 0; i < def.nodes.length; i++) {
    const nodeDef = def.nodes[i];
    Services.setCurrentNode(view, i);
    let nodeData: any;
    switch (nodeDef.flags & NodeFlags.Types) {
      case NodeFlags.TypeElement:
        const el = createElement(view, renderHost, nodeDef) as any;
        let componentView: ViewData = undefined !;
        if (nodeDef.flags & NodeFlags.ComponentView) {
          const compViewDef = resolveDefinition(nodeDef.element !.componentView !);
          componentView = Services.createComponentView(view, nodeDef, compViewDef, el);
        }
        listenToElementOutputs(view, componentView, nodeDef, el);
        nodeData = <ElementData>{
          renderElement: el,
          componentView,
          viewContainer: null,
          template: nodeDef.element !.template ? createTemplateData(view, nodeDef) : undefined
        };
        if (nodeDef.flags & NodeFlags.EmbeddedViews) {
          nodeData.viewContainer = createViewContainerData(view, nodeDef, nodeData);
        }

    nodes[i] = nodeData;
  }
  // Create the ViewData.nodes of component views after we created everything else,
  // so that e.g. ng-content works
  execComponentViewsAction(view, ViewAction.CreateViewNodes);



export function createElement(view: ViewData, renderHost: any, def: NodeDef): ElementData {
  const elDef = def.element !;
  const rootSelectorOrNode = view.root.selectorOrNode;
  const renderer = view.renderer;
  let el: any;
  if (view.parent || !rootSelectorOrNode) {
    if (elDef.name) {
      el = renderer.createElement(elDef.name, elDef.ns);
    } else {
      el = renderer.createComment('');
    }
    const parentEl = getParentRenderElement(view, renderHost, def);
    if (parentEl) {
      renderer.appendChild(parentEl, el);
    }
  } else {
    el = renderer.selectRootElement(rootSelectorOrNode);
  }
  if (elDef.attrs) {
    for (let i = 0; i < elDef.attrs.length; i++) {
      const [ns, name, value] = elDef.attrs[i];
      renderer.setAttribute(el, name, value, ns);
    }
  }
  return el;
}


export function createComponentView(
    parentView: ViewData, nodeDef: NodeDef, viewDef: ViewDefinition, hostElement: any): ViewData {
  const rendererType = nodeDef.element !.componentRendererType;
  let compRenderer: Renderer2;
  if (!rendererType) {
    compRenderer = parentView.root.renderer;
  } else {
    compRenderer = parentView.root.rendererFactory.createRenderer(hostElement, rendererType);
  }
  return createView(
      parentView.root, compRenderer, parentView, nodeDef.element !.componentProvider, viewDef);
}

猜你喜欢

转载自blog.csdn.net/nj_kevin_peng/article/details/78750370