只是想了解Angular是如何在幕后构建和运行的?

以下是我迄今为止的理解.我想知道我是否错过了什么.

How Angular builds

在使用TypeScript编写Angular应用程序之后,我们使用Angular CLI命令来构建应用程序.

ng build命令将应用程序编译到输出目录中,构建工件将存储在dist/目录中.

Internal Process

1. Angular CLI运行Webpack来构建和绑定所有JavaScript和CSS代码.

2.反过来,Webpack调用TypeScript加载程序,该加载程序获取Angular项目中的所有.ts个文件,然后将它们传输到JavaScript,即浏览器可以理解的.js文件.

This post称Angular有两个编译器:

  • 视图编译器

  • 模块编译器

Questions on builds

调用构建过程的顺序是什么?

Angular CLI first calls Angular built-in compiler written in TypeScript => then calls the TypeScript Transpiler => then calls the Webpack to bundle and store in the dist/ directory.

How Angular runs

构建完成后,我们的应用程序的所有组件、服务、模块等将传输到JavaScript .js个文件中,用于在浏览器中运行Angular应用程序.

Angular Docs份声明

  1. 使用AppComponent类(在main.ts中) bootstrap 时,Angular在index.html中查找<app-root>,找到它,实例化AppComponent的一个实例,并在<app-root>标记中呈现它.

  2. Angular在用户移动应用程序时创建、更新和销毁组件.

Questions on runs

虽然上面的语句中使用了main.ts来解释 bootstrap 过程,但Angular应用程序不是 bootstrap 的还是使用JavaScript .js文件启动的?

不是所有上述语句都是在运行时使用JavaScript .js文件完成的吗?

有人知道所有部件是如何在深度上结合在一起的吗?

推荐答案

(When I say Angular I mean Angular 2+ and will explicitly say angular-js if I am mentioning angular 1).

序曲:令人困惑

Angular,可能更准确地说,Angular cli已经将构建过程中涉及的许多Javascript趋势工具合并在一起.这确实会引起一些困惑.

为了进一步加深混淆,angular js中经常使用术语compile来表示获取模板的伪html并将其转换为DOM元素的过程.这是编译器工作的一部分,只是其中一个较小的部分.

首先,运行angular不需要使用TypeScript、angular cli或Webpack.回答你的问题.我们应该看一个简单的问题:"什么是Angular ?"

角:它是做什么的?

这一部分可能会引起争议,我们将拭目以待.At its core, the service that Angular provides, is a dependency injection mechanism which works across Javascript, HTML, and CSS..你把所有的小片段单独写下来,在每个小片段中,你都遵循Angular的规则来引用其他片段.然后以某种方式编织起来.

更具体地说:

  • 模板允许将HTML连接到Javascript组件中.这允许用户对DOM本身的输入(例如单击按钮)输入到Javascript组件中,还允许Javascript组件中的变量控制DOM中的 struct 和值.
  • Javascript类(包括Javascript组件)需要能够访问它们所依赖的其他Javascript类的实例(例如,classic 依赖注入).BookListComponent需要BookListService的实例,而BookListService可能需要BookListPolicy或类似的实例.这些类中的每一个都有不同的生存期(例如,服务通常是单例的,组件通常不是单例的),Angular必须管理所有这些生存期、组件的创建以及依赖项的连接.
  • CSS规则需要以这样的方式加载,即它们只应用于DOM的一个子集(组件的样式是该组件的本地样式).

需要注意的一件可能很重要的事情是,Angular不负责Javascript文件如何引用其他Javascript文件(例如import关键字).这是由Webpack负责的.

编译器做什么?

现在你知道了Angular是做什么的,我们可以讨论一下编译器是做什么的.我会避免太过技术化,主要是因为我无知.然而,在一个类中,你通常有一些依赖关系,比如说,You can think of me as a Component type of instance是如何表达你的依赖关系的.在Java中,Spring最初是通过XML文件实现的.Java后来采用了注释,它们已成为表示元数据的首选方式.C#使用属性来表示元数据.

Javascript没有很好的机制来公开这种内置的元数据.angular js做了一次try ,结果不错,但有很多规则不容易判断,而且有点混乱.对于Angular,有两种受支持的指定元数据的方法.您可以编写纯Javascript并手动指定元数据,这有点类似于angular js,只需遵循规则并编写额外的代码即可.或者,您可以切换到TypeScript,正如它所发生的那样,它有用于表示元数据的装饰符(这@个符号).

这就是我们最终可以使用编译器的地方.编译器的工作是获取元数据并创建作为应用程序的工件系统.你关注所有的片段和所有的元数据,编译器会构建一个大型的互联应用程序.

编译器是如何做到的?

编译器有两种工作方式,运行时和提前.从这里开始,我假设您正在使用TypeScript:

  • Runtime:当typescript编译器运行时,它会获取所有decorator 信息,并将其放入附加到装饰类、方法和字段的Javascript代码中.在index.html中,你引用了main.js,它调用bootstrap方法.该方法将传递给顶级模块.

bootstrap方法启动运行时编译器,并为其提供对顶层模块的引用.然后,运行时编译器开始对该模块、该模块引用的所有服务、组件等以及所有相关元数据进行爬网,并构建应用程序.

  • AOT: Angular并没有在运行时完成所有工作,而是提供了一种在构建时完成大部分工作的机制.这几乎总是使用a webpack plugin来完成的(这必须是最流行但最鲜为人知的npm包之一).它在typescript编译运行之后运行,因此它看到的输入基本上与运行时编译器相同.AOT编译器会像运行时编译器一样构建应用程序,但会将其保存回Javascript.

这里的优点不仅是可以节省编译本身所需的CPU时间,还可以减少应用程序的大小.

具体答案

Angular CLI First calls angular built in compiler written in Typescript => then calls the Typescript Transpiler => then calls the Webpack to bundle and store in the dist/ directory.

不会.Angular CLI调用Webpack(Angular CLI的真正服务是配置Webpack.当您运行ng build时,它只不过是启动Webpack的代理而已).Webpack首先调用Typescript编译器,然后调用angular编译器(假设为AOT),同时绑定代码.

虽然是主要的.ts在上面的语句中用于解释 bootstrap

我不完全确定你在问什么.main.ts将被转换成Javascript.该Javascript将包含对bootstrap的调用,bootstrap是Angular的入口点.完成bootstrap后,您将运行完整的Angular 应用程序.

这篇文章说Angular有两个编译器:

视图编译器

模块编译器

老实说,我只想在这里说我无知.我认为在我们的水平上,我们可以把它看作一个大的编译器.

有人知道所有部件是如何在深度上结合在一起的吗?

我希望以上内容能满足这一点.

不要@Me:Angular做的不仅仅是依赖注入

当然它可以进行布线、视图构建、变更检测和各种其他工作.编译器实际上会生成用于视图构建和更改检测的Javascript.我撒谎说那只是依赖注射.然而,依赖注入是核心,足以驱动其余答案.

我们应该称之为编译器吗?

它可能会进行大量的解析和词法分析,并最终生成大量代码,因此您可以将其称为编译器.

另一方面,它并不是真正地将代码转换为一种不同的表示形式.相反,它需要一堆不同的代码,并将它们编织成一个更大系统的可消费部分.然后, bootstrap 过程(在编译之后,如果必要的话)将这些片段插入到Angular core中.

Typescript相关问答推荐

了解TS类型参数列表中的分配

angular 17独立使用多个组件(例如两个组件)

typescribe不能使用值来索引对象类型,该对象类型满足具有该值的另一个类型'

对深度对象键/路径进行适当的智能感知和类型判断,作为函数参数,而不会触发递归类型限制器

如何键入函数以只接受映射到其他一些特定类型的参数类型?

如何提取密钥及其对应的属性类型,以供在新类型中使用?

Vue SFC中的多个脚本块共享导入的符号

如何在另一个参数类型中获取一个参数字段的类型?

使用Dockerfile运行Vite React应用程序时访问env变量

已解决:如何使用值类型限制泛型键?

如何在react组件中使用doctype和html标签?

函数重载中的不正确TS建议

基于泛型的条件接口键

Typescript,如何在通过属性存在过滤后重新分配类型?

如何在打字角react 式中补齐表格组

类型脚本中参数为`T`和`t|unfined`的重载函数

有没有一种方法可以提升对象的泛型级别,而对象的值是泛型函数?

Typescript 是否可以区分泛型参数 void?

对象只能使用 Typescript 中另一个对象的键

React router - 如何处理嵌套路由?