Angular 学习之路 02 - 项目结构

上一章我们已经安装好 Angular CLI,下面来创建一个示例工程,了解 Angular CLI 的基本使用。

Angular CLI 可以帮我们生成开箱即用的项目框架,其具体命令是:

ng new demo

这里,开头的ng说明这是一个 Angular CLI 命令;之后的new说明是要新建项目;项目名就是最后的 demo。

按下回车之后,Angular CLI 会询问我们几个问题:

  1. Would you like to add Angular routing? - 你想要添加 Angular 路由模块吗?为简单起见,这里我们选择“否”,输入N即可。
  2. Which stylesheet format would you like to use? (Use arrow keys) - 使用方向键选择使用哪一个 CSS 预处理器,可选择的是 CSS、SCSS、Sass、Less 以及 Stylus。现在我们直接按下回车,选择默认的 CSS 即可。
asr-ng-new-demo

最后按下回车之后,Angular CLI 会帮我们生成完整的项目框架——包括项目的源代码文件模板、符合最佳实践的项目结构以及各种配置文件等。最后,Angular CLI 会自动运行npm install,安装项目所需要的各种依赖。这个安装过程会比较漫长,需要耐心等待一段时间。当提示出现“Successfully initialized git.”时,表示项目已经创建完成。如果有错误,需要检查安装过程或者网络连接等。

ng new提供了很多参数,可以帮助我们对整个生成过程进行设置。比如,如果我们只需要生成完整的项目架构,不要进行依赖的安装(比如我们只想了解文件结构),那么只需要添加--skip-install参数:

ng new demo --skip-install

项目创建成功,会在当前目录生成一个项目文件夹。这里即是 demo 目录。我们可以进入项目目录,查看 CLI 为我们生成的项目文件。

项目根目录包含 e2e、node_modules 和 src 三个子文件夹,以及若干配置文件。下面我们简单介绍下这些配置文件以及文件夹的作用。

.browserslistrc:保证 Angular 的浏览器兼容性。

.editorconfig:编辑器设置的通用配置。editorconfig 试图提供一种跨编辑器的配置方案,比如规定代码如何缩进、使用空格还是 tab 等。在 editorconfig 站点可以找到详细配置方法。

.gitignore:Git 忽略文件,用于配置哪些文件不需要提交到 Git 中。

angular.json:Angular CLI 配置文件。注意,该文件只是 Angular CLI 的配置文件,而不是 Angular 的配置文件。

karma.conf.js:karma 测试框架的配置文件。

package.json:npm 配置文件,列出了项目所有的依赖以及一些额外的信息,比如执行脚本等。另外,与此相关的,我们还有一个 package-lock.json 文件,用于记录项目依赖的版本号。

README.md:项目描述文件。

tsconfig.app.jsontsconfig.base.jsontsconfig.jsontsconfig.spec.json:TypeScript 配置文件。TypeScript 配置文件可以继承,因此,tsconfig.app.json 和 tsconfig.spec.json 都是继承了 tsconfig.base.json。tsconfig.app.json 用于编译源代码;tsconfig.spec.json 用于编译测试用例。tsconfig.json 则用于编辑器和 TypeScript 编译器,进而改善开发体验,并不在编译过程中使用。

tslint.jsontslint 配置文件。tslint 是一个静态代码分析工具,用于检测 TypeScript 代码质量,以便提升可读性、可维护性等。

e2e:该文件夹中包含用于 protractor 进行端对端测试的文件。protractor 是一个测试框架,允许我们不在真实的浏览器中进行测试。

node_modules:项目的所有依赖都会由 npm 下载并保存在这个文件夹中。

src:项目的所有源代码。

package.json 的作用类似于 maven 的 pom.xml。我们可以使用文件编辑器打开该文件:

{
  "name": "demo",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~10.0.6",
    "@angular/common": "~10.0.6",
    "@angular/compiler": "~10.0.6",
    "@angular/core": "~10.0.6",
    "@angular/forms": "~10.0.6",
    "@angular/platform-browser": "~10.0.6",
    "@angular/platform-browser-dynamic": "~10.0.6",
    "@angular/router": "~10.0.6",
    "rxjs": "~6.5.5",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1000.5",
    "@angular/cli": "~10.0.5",
    "@angular/compiler-cli": "~10.0.6",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.0.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~3.3.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~3.9.5"
  }
}

有关 package.json 的详细介绍已经超出了本文的内容。这里仅简单介绍一下。

package.json 是一种带有固定格式的 JSON 文件。其中,nameversion分别是项目的名字和版本号,这里即项目名为 demo,版本为 0.0.0。scripts是自定义的命令,这里的命令可以使用npm run来执行。例如第一个ng,就可以使用npm run ng执行。有关scripts部分的相关介绍,可以参考这篇文章。之后的private表示该项目是一个私有项目,不允许被推送到 NPM 中心。dependencies部分是该项目的依赖;devDependencies部分是该项目的开发依赖。可以这样理解:前者是项目运行时所需要的包,后者是开发时所需要的包(例如测试时使用的包等)。有关二者的详细区别,可以参考网上很多解释文章。

dependenciesdevDependencies无疑是 package.json 的重中之重。二者定义这个项目的所有依赖。它们以键值对的形式,给出了依赖的名字和版本号。依赖的名字很好理解,但版本号就不那么直观。因为这些版本号的前面还有一些奇怪的字符。

要理解这些字符所代表的含义,首先需要知道语义化版本号这一概念。

语义化版本号,即 SemVer,格式固定为 X.Y.Z。X、Y、Z 都是非负整数,禁止在数字前补零,每个数值都是递增的。X、Y、Z 分别规定如下:

  • X:主版本号,当我们做了不兼容或者颠覆性的更新,修改此版本号;
  • Y:次版本号,当我们做了向下兼容的功能性修改,修改此版本号;
  • Z:修订版本号,当我们做了向下兼容的问题修正,修改此版本号。

语义化版本号要求开发者在发布内容时,严格按照上述规定执行。这么做的好处是,依赖库的版本可以比较容易的确定是否兼容。例如,如果 X 有了变化,代表依赖库可能是不兼容的,需要修改我们自己的代码;如果 Y 有了变化,代表依赖库有了新功能,但我们的代码一般不需要修改;如果 Z 有了变化,代表依赖库只是修改了 bug,不影响我们的代码。

既然依赖库的版本可以比较容易的确定是否兼容,那么,语义化版本号可以使用一个范围来确定所依赖的版本。一个范围可以由一个或多个比较器组成;一个比较器则由版本号和比较符构成;多个比较器可以用 || 连接,表示或的关系。语义化版本号定义了 5 个最原始的比较符:

  • <,小于
  • <=,小于等于
  • >,大于
  • >=,大于等于
  • =,等于,当不指定上面四种比较符时,即应用此比较符

例如,>= 1.2.1 < 1.3.0 可以接受 1.2.1、1.2.2、1.2.9、1.2.999 等,但不接受 1.2.0、1.3.0、2.0.0 等;1.2.1 || >= 1.3.0 < 3.0.0 可以接受 1.2.1、1.3.0、1.4.99、2.0.0、2.9.99 等,但不接受 1.2.2、3.0.0、4.0.0 等。

除去这些最基本的比较符,还有一些高级比较符,比如这里的~以及^

~代表的是,如果指定了次版本号,则允许改变修订版本号;如果没有指定次版本号,则只能修改次版本号。例如,~1.2.1 等价于 >= 1.2.1 < 1.3.0;~1.2 等价于 ~1.2.0,即 >= 1.2.0 < 1.3.0;~1 等价于 ~1.0.0,即 >= 1.0.0 < 2.0.0。

^代表的是,不允许修改最左非零数字。例如,^1.2.1 等价于 >= 1.2.1 < 2.0.0;^0.2.1 等价于 >= 0.2.1 < 0.3.0。

因此,package.json 中的"@angular/animations": "~10.0.6"含义就是,对于依赖 @angular/animations,版本号范围是 >= 10.0.6 < 10.1.0。

有关语义化版本号的更详细内容,可以参考其官方文档。如果要了解更多关于 NPM 版本号的范围指定,可以阅读这篇文章

src 目录中有三个子目录:app 中包含了 Angular CLI 生成的一个开箱即用的简单示例程序,默认有五个文件,其中,app.module.ts 是 Angular 的模块 AppModule;以 app.component 开头的四个文件组成一个 Angular 组件 AppComponent。简单来说,AppComponent 属于 AppModule。我们会在后面的章节详细介绍模块和组件。

assets 目录中包含项目所需静态资源,如图片、字体等。

environments 目录中包含为不同构建环境定义的与环境相关的变量的文件。这些构建环境可以是开发环境、生产环境、测试环境等。Angular CLI 默认创建了两个环境,分别是开发环境和生产环境。environments 中的 environments.ts 用于开发环境,environments.prod.ts 则用于生产环境。

各个浏览器对标准的实现程度并不一致,polyfills.ts 文件用于抹平这种浏览器间的标准的不一致性。

styles.css 文件定义了项目的全局样式。

test.ts 是单元测试的主入口。

现在,我们基本介绍完了 Angular CLI 为我们生成的所有文件。虽然有些文件我们不知道具体是做什么用的,以后会一一讲解。

下面我们在项目文件夹中使用命令:

ng serve

当运行出现如下提示时,表示运行成功:

如果运行结果最后不是 Compiled successfully,需要检测是否哪里出了问题。结果里面已经提示我们,使用浏览器打开地址 http://localhost:4200,应该就能访问到 Angular CLI 生成的项目:

现在我们简单介绍了 Angular CLI 生成的所有项目文件,详细讲解了 package.json 的版本语法规定。后面我们将开始详细介绍 Angular 的相关内容。这里建议,先不要关注 Angualr CLI 生成的这些文件的具体语法,只需知道其作用,等到后面开发时使用到的时候再去详细了解。

demo 项目代码已经提交到 gitee:https://gitee.com/devbean/angular-study-road。需要的话可以使用

git clone https://gitee.com/devbean/angular-study-road.git

获取源代码。

Leave a Reply