1.3 项目结构与启动流程 项目结构指 CLI 生成工程的目录分工;启动流程指从浏览器加载页面、执行引导文件、创建组件树到首次渲染完成的链路。看懂这两件事,报错时才能迅速定位层级,也才能理解变更检测的检查对象——组件树——是怎么被建出来的。 上一节环境已就绪并写出了第一个组件,本节把镜头拉远:整个项目由哪些部分组成、main 文件里的两行代码如何牵出一整棵树。 本节要拿下什么 脚手架生成的一堆文件不是装饰品,本节要拿下它们在启动链路里各自的位置与职责: 说出工作区、应用工程、源码目录三层的职责边界。 解释配置文件各自管什么:构建、TypeScript 编译、测试与浏览器兼容。 逐行理解引导文件,描述从 bootstrap 到根组件渲染的五个步骤。
项目结构指 CLI 生成工程的目录分工;启动流程指从浏览器加载页面、执行引导文件、创建组件树到首次渲染完成的链路。看懂这两件事,报错时才能迅速定位层级,也才能理解变更检测的检查对象——组件树——是怎么被建出来的。
上一节环境已就绪并写出了第一个组件,本节把镜头拉远:整个项目由哪些部分组成、main 文件里的两行代码如何牵出一整棵树。
脚手架生成的一堆文件不是装饰品,本节要拿下它们在启动链路里各自的位置与职责:
一个新项目的源码层大致如此(以当代版本为参考):
order-dashboard/ ├── src/ 应用源码的唯一老家 │ ├── app/ 所有组件、服务、路由的存放地 │ │ ├── app.component.* 根组件,四件套 = 类 + 模板 + 样式 + 测试 │ │ ├── app.config.ts 应用级配置:路由、注入器提供者 │ │ └── app.routes.ts 路由表 │ ├── main.ts 引导文件,一切的起点 │ ├── index.html 宿主页面,只有一个自定义标签 │ └── styles.scss 全局样式 ├── angular.json CLI 工程配置:构建目标、资源、测试配置 ├── tsconfig.json TypeScript 编译选项,含严格模式开关 └── package.json 依赖与脚本
两个容易忽视但重要的点。其一,angular.json 里的 budgets(预算)配置会在产物超限时直接让构建失败,防止包体积悄悄膨胀。其二,tsconfig 的严格模式默认开启,后面模板类型检查正是依赖它,这也是下一节 TypeScript 的伏笔。
组件文件通常拆成四个同名文件:类逻辑、模板、样式、测试。这个约定让"找某个组件的模板"变成机械动作,团队里任何人接手都不需要问路。
打开 main 文件,当代 standalone 应用的引导只有几行:
// main.ts:浏览器加载后执行的第一个应用文件 import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { appConfig } from './app/app.config'; // 引导根组件:传入组件类与应用级配置 bootstrapApplication(AppComponent, appConfig) .catch(err => console.error(err)); // 引导失败时兜底输出,别让页面白屏无声无息
从这两行到屏幕出画,完整链路分五步:

链路五步还能直接当排错速查表用:白屏且控制台无报错,问题多半在第 1 步之前——脚本路径或打包配置错了;报"找不到 provider",卡在第 2 步,应用级配置漏注册了服务;模板语法错误在构建期就会拦下,能走到运行期才炸的多是第 4 步的组件树构建(循环引用、缺失导入);界面出画但数据空白,则要查第 5 步的绑定表达式。报错信息落在哪一步,就到哪一步的配置里找——比整页翻代码快得多,这也是读懂启动链路最实际的红利。
背景:理解启动链路不能只靠读,要在浏览器里亲眼看到。
操作:打开开发者工具控制台,在 main 引导前临时加一行 console.log('boot start'),在根组件构造函数里加一行日志,刷新页面观察输出顺序;再在 Sources 面板给根组件构造函数下断点,查看调用栈。
结果:日志顺序为 boot start → 根组件构造 → 子组件构造;断点调用栈里能看到 framework 引导相关函数的名字。
解读:构造顺序是父先子后(自顶向下建树),而首轮变更检测同样自顶向下——这就是第 3 章会讲到的"单向数据流"在生命周期里的体现。
变式:在控制台手写 setTimeout(() => console.log('tick'), 0),配合 Angular 的调试工具能看到定时器回调后执行了一轮检查——第三方脚本能唤醒框架检查的直接证据。
骨架清楚了,下一节补上最后一块地基:TypeScript 类型系统如何为这棵树上的数据流护航。