使用Angular CLI的6个最佳实践及专业技巧
我们在新建前端项目时,常常会为项目的代码结构以及技术选型(如gunt,gulp,webpack,systemjs等等)绞尽脑汁。
Angular CLI为我们开发Angular应用提供了一个标准的项目模板。
项目模板里包含了
- 完整的测试:包括unit测试,e2e测试
- 多环境构建,提供了develop和production这两种基本的构建
- 还提供了一系列代码开发工具,如ng generate
标准的项目模板大大节省了我们构建项目以及开发的时间。但在开发过程中我们还是有些地方要注意改进。下面是6个关于使用Angular CLI的最佳实践以及专业技巧。
1、架构方面
模块划分
我们至少要把应用划分为三个模块:
- CoreModule:核心模块,此模块主要包含服务类,这些服务类需要使用单例模式实现。
- SharedModule:共享模块,此模块主要包含了那些在多个模块中使用的代码,如指令。但是这些代码不能依赖于其他业务模块。
- FeatureModule:特性模块,多个功能则需要对应多个特性模块
模块创建
使用Angular CLI创建模块
ng generate module core
它会创建一个core目录,我们需要在core目录下创建index.ts文件。index.ts文件主要用于导出CoreModule以及提供其他模块使用的service服务类。
模块懒加载
我们在加载app时,理论上只需要先加载一个特性模块,其他的特性模块则是根据不同的url请求在按需加载。这样会大大加快app的加载速度。
CoreModule示例
/* 3rd party libraries */
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
/* 导入服务类 */
import { SomeSingletonService } from './some-singleton/some-singleton.service';
@NgModule({
imports: [
CommonModule,
HttpClientModule,
],
declarations: [],
providers: [
/* 对外提供的服务类 */
SomeSingletonService
]
})
export class CoreModule {
/* 只允许CoreModule被AppModule导入 */
constructor (
@Optional() @SkipSelf() parentModule: CoreModule
) {
if (parentModule) {
throw new Error('CoreModule is already loaded. Import only in AppModule');
}
}
}
SharedModule示例
/* 3rd party libraries */
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MdButtonModule } from '@angular/material';
import { SomeCustomComponent } from './some-custom/some-custom.component';
@NgModule({
imports: [
/* angular相关模块*/
CommonModule,
FormsModule,
/* 3rd party components */
MdButtonModule,
],
declarations: [
SomeCustomComponent
],
exports: [
/* angular相关模块 */
CommonModule,
FormsModule,
/* 3rd party components */
MdButtonModule,
/* 自定义组件/指令/pipe */
SomeCustomComponent
]
})
export class SharedModule { }
2、给app和environment起别名
我们在import一个类,如果类的层次很深,类似于:
import { SomeService } from '../../../core/subpackage1/subpackage2/some.service'
由于使用了相对路径来引用依赖,如果文件路径发生了改变,依赖修改起来就很麻烦。
可以使用别名来替换相对路径导入依赖,修改结果如下:
import { SomeService } from "@app/core"
和使用相对路径引用依赖相比,这样就显得简短得多。
修改方法如下
1、新增index.ts
在每一个文件夹里添加index.ts文件,把需要对外暴露的声明重新导入,类似于:
export * from './core.module';
export * from './auth/auth.service';
export * from './user/user.service';
export * from './some-singleton-service/some-singleton.service';
2、修改typescript.config.json
添加baseUrl和paths
{
"compilerOptions": {
"...": "reduced for brevity",
"baseUrl": "src",
"paths": {
"@app/*": ["app/*"],
"@env/*": ["environments/*"]
}
}
}
这样我们就使用模块如@app/core,来引入相应的声明,而非使用相对路径。如果需要修改文件路径,只要修改对应的index.ts文件即可,只要不更改模块,就不需要修改依赖于此文件的地方。
3、使用Sass
Sass支持变量,function,mixins等功能,官方的Angular Material的组件也是使用它,建议项目也使用Sass。
使用Angular CLI创建项目设置style为scss
ng new --style scss
4、production构建
Angular CLI提供了很多可选的参数让我们很灵活地构建产品包。
Angular 5
ng build --prod
Angular 5之前版本
ng build --prod --build-optimizer
--build-optimizer:在Angular 5是默认打开的,Angular 5之前的版本建议也打开,但需要在构建命令手动打开
--prod表示默认使用一些对产品包有用的参数。具体参考:ng build
在package.json新增构建脚本:
"build:prod": "ng build --prod --optimizer"
5、使用Headless Chrome测试
添加--browser ChromeHeadless到测试脚本里
在package.json添加脚本如下:
"test": "ng test --browser ChromeHeadless --single-run"
"watch": "ng test --browser ChromeHeadless"
6、标准化日志提交以及自动生成changlog
这里主要介绍 standard-version。只要我们按照Conventional Commits specification 规范写提交日志,standard-version会自动帮我们更新CHANGELOG.md
日志格式:
<type>[optional scope]: <description>
[optional body]
[optional footer]
type:表示日志的类型,日志类型包括:fix(修复bug),feat(新功能)和BREAKING CHANGE
scope:主要是用来提供一些额外的上下文信息,它用括号括起来,可选。
description:描述,它在冒号后面
body和footer:我们也可以添加一些body说明以及footer脚尾,换行隔开,可选。
示例:
fix(dependency): multiple versions of rxjs in single project (TS90010)
BREAKING CHANGE: rxjs is now peerDependency instead of dependency
closes #1
standard-vesion的安装
npm install -D standard-version --save-dev
standard-version使用
在package.json添加脚本如下:
"release": "standard-version"
如需要推送到git和发布到npm仓库
"release": "standard-version && git push — follow-tags origin master && npm publish"