Angular如何构建和运行


84

只想了解Angular如何在后台构建和运行?

以下是我到目前为止所了解的。想知道我是否错过了什么。

Angular如何构建

使用TypeScript对Angular应用程序进行编码后,我们使用Angular CLI命令来构建应用程序。

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

内部流程

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

2. 反过来,Webpack调用TypeScript加载程序,该加载程序会提取.tsAngular项目中的所有文件,然后将它们转换为JavaScript,即转换为.js浏览器可以理解的文件。

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

  • 查看编译器

  • 模块编译器

有关构建的问题

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

Angular CLI首先调用以TypeScript =>编写的Angular内置编译器,然后调用TypeScript Transpiler =>,然后调用Webpack进行捆绑并存储在dist/目录中。

Angular如何运行

构建完成后,我们所有应用程序的组件,服务,模块等都将转换为JavaScript .js文件,该文件用于在浏览器中运行Angular应用程序。

Angular Docs中的语句

  1. 当您使用AppComponent类进行引导时(在main.ts中),Angular<app-root>在中index.html查找,找到它,实例化AppComponent实例,并将其呈现在<app-root>标记中。

  2. 当用户在应用程序中移动时,Angular会创建,更新和销毁组件。

跑步问题

尽管main.ts在上面的语句中使用它来解释引导过程,但是Angular应用程序不是使用JavaScript.js文件引导或启动的吗?

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

有谁知道所有零件在深度上如何装配在一起?

Answers:


89

(当我说Angular时,我指的是Angular 2+,如果我提到angular 1,则会明确地说出angular-js)。

前奏:令人困惑

Angular,也许更准确地说是angular-cli,已经将构建过程中涉及的许多Java趋势工具合并在一起。确实会引起一些混乱。

为了进一步混淆,该术语 compile令人通常在angular-js中使用,指代获取模板的伪html并将其转换为DOM元素的过程。那是编译器所做工作的一部分,只是较小部分的一部分。

首先,不需要使用TypeScript,angular-cli或Webpack来运行Angular。回答您的问题。我们应该看一个简单的问题:“什么是Angular?”

Angular:它是做什么的?

我们将看到这一部分可能会引起争议。 Angular提供的服务的核心是依赖注入机制,可跨Javascript,HTML和CSS进行工作。 您分别编写所有小片段,并在每个小片段中遵循Angular的规则引用其他片段。然后,Angular完全以某种方式进行编织。

要(稍微)更加具体:

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

需要注意的一件事可能是,Angular对Javascript文件如何引用其他Javascript文件(例如import关键字)不承担任何责任。这是由Webpack处理的。

编译器做什么?

既然您知道了Angular是什么,我们就可以讨论编译器的作用。我将避免过于技术性,主要是因为我无知。但是,在依赖项注入系统中,通常必须使用某种元数据来表达您的依赖项(例如,类如何说I can be injectedMy lifetime is blahYou can think of me as a Component type of instance)。在Java中,Spring最初是使用XML文件来完成的。Java后来采用了注释,它们已成为表达元数据的首选方式。C#使用属性来表示元数据。

Javascript没有很好的机制来公开此内置元数据。angular-js进行了尝试,虽然还不错,但是有很多规则无法轻易检查并且有些混乱。Angular支持两种指定元数据的方法。您可以编写纯Javascript并手动指定元数据,这有点类似于angular-js,并且只需遵循规则并编写额外的样板代码即可。或者,您可以切换到TypeScript,恰好发生这种情况,@它具有用于表示元数据的修饰符(这些符号)。

因此,这里是我们最终可以到达编译器的地方。编译器的工作是获取该元数据并创建属于您的应用程序的工作系统。您专注于所有部分和所有元数据,编译器将构建一个大型的互连应用程序。

编译器是如何做到的?

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

  • 运行时: TypeScript编译器运行时,它将获取所有装饰器信息,并将其推入附加到装饰后的类,方法和字段的Javascript代码中。在您index.html引用的main.js对象中调用了该bootstrap方法。该方法将传递给顶层模块。

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

  • AOT: Angular提供了一种在构建时完成大部分工作的机制,而不是在运行时进行所有工作。这几乎总是使用webpack插件完成的(它必须是最受欢迎但鲜为人知的npm软件包之一)。它在打字稿编译运行之后运行,因此它基本上看到与运行时编译器相同的输入。AOT编译器会像运行时编译器一样构建您的应用程序,但随后将其保存回Javascript。

这样做的好处不仅在于可以节省编译本身所需的CPU时间,而且还可以减少应用程序的大小。

具体答案

Angular CLI首先调用用Typescript =>编写的内置编译器angular,然后调用Typescript Transpiler =>,然后调用Webpack捆绑并存储在dist /目录中。

不会。AngularCLI调用Webpack(Angular CLI的真正服务是配置Webpack。运行时,ng build它仅是启动Webpack的代理)。Webpack首先调用Typescript编译器,然后调用有角度的编译器(假定为AOT),同时同时捆绑代码。

尽管以上声明中使用main.ts来解释引导过程,但是不是使用Javascript .js文件引导或启动了角度应用程序吗?

我不确定你在这里问什么。 main.ts将被翻译成Javascript。该Javascript将包含bootstrap对Angular的入口的调用。当bootstrap完成后,你将有你的全角应用程序运行。

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

查看编译器

模块编译器

老实说,我只是在这里声称无知。我认为,从我们的角度来看,我们可以将其视为一个大型编译器。

有谁知道所有零件在深度上如何装配在一起?

我希望以上内容对此感到满意。

不要@我:Angular所做的不只是依赖注入

当然。它可以进行路由,查看构建,更改检测以及所有其他内容。编译器实际上会生成用于视图构建和更改检测的Javascript。当我说这只是依赖注入时,我撒了谎。但是,依赖项注入是核心,足以驱动其余的答案。

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

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

另一方面,它并没有真正将您的代码转换为不同的表示形式。取而代之的是采用一堆不同的代码,并将它们织入一个更大的系统的可消耗部分。引导过程然后(如果需要,在编译之后)将这些片段插入并将其插入Angular核心。


感谢您的详细回答。在接受您的答案之前,我对您的Statement The compiler does actually generate Javascript中的视图构建和更改检测有所怀疑。这不是说谎。那是编译器不是吗?而angular进行依赖注入。
shaijut

1
是的对不起 我所指的谎言是“ Angular提供的服务的核心是依赖注入机制”,因为Angular这样做并不是全部,甚至不是所有编译器都这样做。
佩斯'18

如果Angular被抽象为具有组件,指令,服务等功能的新“语言”。它可以称为编译器。将Angular语言编译为原始js和html。
克里斯·鲍

10

让我从头开始。

在我的应用程序中,我直接从运行应用程序Webpack

为了构建和运行该应用程序,我们使用webpack --progresswebpack-dev-server --inline命令package.json,如下所示

"scripts": {
    "serve": "webpack-dev-server --inline ",
    "build": "webpack --progress"

  }

当我们运行webpack --progress命令时,它将开始读取webpack.config.js文件,并在其中找到入口,如下所示。

module.exports = {
    devtool: 'source-map',
    entry: './src/main.ts',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.ts$/,
                loaders: ['awesome-typescript-loader', 'angular2-template-loader'],
                exclude: [/\.(spec|e2e)\.ts$/]
            },
            /* Embed files. */
            {
                test: /\.(html|css)$/,
                loader: 'raw-loader',
                exclude: /\.async\.(html|css)$/
            },
            /* Async loading. */
            {
                test: /\.async\.(html|css)$/,
                loaders: ['file?name=[name].[hash].[ext]', 'extract']
            },
        ]
    },
    resolve: {
        extensions: ['.ts', '.js']
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
}   

然后读取所有Typescript文件并根据tsconfig.json文件中声明的规则进行编译,然后将其转换为相应的.js文件和映射文件。

如果它运行时没有任何编译错误,它将bundle.js使用我们在Webpack输出部分中声明的名称创建文件。

现在,让我解释一下为什么使用装载机。

awesome-typescript-loader,angular2-template-loader 我们使用这些加载器在Typescript文件中声明的基础上编译tsconfig.json文件,angular2-template-loader在Angular 2 Component元数据中搜索templateUrlstyleUrls声明内部,并将路径替换为相应的要求声明。

resolve: {
        extensions: ['.ts', '.js']
    }

我们使用上面的“解析”部分告诉我们Webpack要转换TypescriptJavaScript文件

plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]

插件部分用于注入第三方框架或文件。在我的代码中,我使用它来注入index.html目标文件夹。

 devtool: 'source-map',

上一行用于Typescript在浏览器中查看文件并调试它,该文件主要用于开发人员代码。

 loader: 'raw-loader'

上面raw-loader的用于加载.html.css文件,并将它们与Typescript文件。

最后,当我们运行webpack-dev-server --inline时,它将创建自己的服务器并启动应用程序,如web-pack.config.js我们提到目标文件夹和入口点的文件中提到。

Angular大多数应用程序的2个入口处main.ts,我们提到了初始引导程序模块(例如app.module),该模块包含完整的应用程序信息,例如整个应用程序的所有指令,服务,模块,组件和路由实现。

注意: 许多人都怀疑为什么index.html只启动应用程序,即使他们没有提到任何地方。答案是,当Webpackserve命令运行时,它会创建自己的服务,index.html如果没有提到任何默认页面,则默认情况下会加载。

我希望所提供的信息对某些人有所帮助。


1
赞赏您尝试进行的解释,如果您能以更清晰的顺序方式进行解释,那就更好了。因此,您不Angular CLI用于构建Angular应用程序,而Webpack直接使用它吗?
shaijut

5

Angular如何构建?

Angular CLI呼叫Webpack,当Webpack击中.ts它通过其关闭,以文件的TypeScript编译器,其具有编译一个输出变压器Angular模板

因此构建顺序为:

Angular CLI=> Webpack=>TypeScript编译器=>TypeScript编译Angular器在编译时调用编译器。

Angular如何运行?

Angular引导并使用Javascript文件运行。

引导过程实际上是运行时,发生在打开浏览器之前。这将我们带入下一个问题。

因此,如果引导过程与Javascript文件一起发生,那么AngularDocs为什么使用main.tsTypeScript文件来解释引导过程?

Angular文档只是讨论.ts文件,因为这就是源。

这是简短的答案。欣赏是否有人可以深入回答。

感谢在聊天中回答我的问题的@ Toxicable


2

这个答案可能迟到了,但是最近有一个关于这个话题的好话题,它是从一个初学者的角度开始的,并且深入。我不会尝试用我的话语来总结或指出这个线程中的错误信息,而是将Kara Erickson的视频链接到:Angular的工作原理

她是Angular框架的技术负责人,并且在以下方面做得非常不错:

  • Angular框架的主要部分是什么
  • 编译器如何工作,产生什么
  • 什么是“组件定义”
  • 什么是应用程序引导程序,它如何工作

1
谢谢您的贡献:),谢谢。
shaijut

1

那么,如果引导过程与Javascript文件一起发生,那么Angular Docs为什么使用main.ts TypeScript文件来解释引导过程?

这是main.ts转换后的.js版本的一部分,该版本ng build尚未丑化和缩小,您希望初学者理解此代码吗?看起来不是很复杂吗?

Object(__WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__["a" /* platformBrowserDynamic */])().bootstrapModule(__WEBPACK_IMPORTED_MODULE_2__app_app_module__["a" /* AppModule */])
    .catch(function (err) { return console.log(err); });

并且ng build --prod --build-optimizer为了使代码最优化而使代码丑陋和最小化,生成的包是紧凑的并且是位不可读的格式。

webpackJsonp([1],{0:function(t,e,n){t.exports=n("cDNt")},"1j/l":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var r=Array.isArray||function(t){return t&&"number"==typeof t.length}},"2kLc

而main.ts文件是人类可读且清晰的文件,这就是为什么angular.io使用main.ts来解释angular应用程序的引导过程。Angular:为什么选择TypeScript?除此之外,如果您曾经是一个如此出色的框架的作者,那么您将采用什么方法使框架流行并易于使用?您是不是要进行简洁明了的解释,而不是复杂的解释?我同意angular.io文档缺乏深入的解释,虽然它不是很好,但是据我所知,他们正在努力使它变得更好。


1

Angular 9+使用AOT(提前编译),这意味着它将散布在各个文件中的所有位,即组件(.ts + .html + .css),模块(.ts)并构造浏览器可理解的JavaScript,并在运行时下载并由浏览器执行。

在Angular 9之前,是JIT(及时编译),它按照浏览器的要求对代码进行编译。

有关详细信息,请参阅:Angular AOT Documentaiton

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.