Angular 架构设计

栏目: JavaScript · 发布时间: 6年前

内容简介:整三天,课也没去上。改得时候特别痛苦,哭了,为什么没有早点发现惰性加载这个东西。

引言

Alice 测试上线,发现包体积太大,加载太慢。决定启用懒加载与预加载加速加载速度。

整三天,课也没去上。改得时候特别痛苦,哭了,为什么没有早点发现惰性加载这个东西。

Angular 架构设计

星期一,重新设计前台架构,重构前台代码。

星期二,分模块加载,启用惰性加载与预加载。

星期三,修改单元测试,添加 provide

星期四,写 PPT

星期五, .NET 考试。

重构前台之后,觉得自己当前设计的架构很合理,遂分享出来,供大家学习交流。

架构

理论

架构理论主要参考外国老哥的一篇文章, Angular (2+): Core vs Shared Modules

Angular 架构设计

CoreModule :核心模块,只被 AppModule 引用,保证全局单例。

ShareModule :共享模块,被各业务模块引用,存储各模块必备的组件、管道以及模板。

实践

CoreModule

核心 Module ,全局只导入一次。

称之为核心,因为没有它应用跑不起来。

Angular 架构设计

核心模块存放拦截器和服务,不过与正常的有些区别。

拦截器

@Injectable()
export class YunzhiInterceptor implements HttpInterceptor {
}
@NgModule({
    imports: [
        NgZorroAntdModule,
        RouterModule
    ],
    providers: [
        {provide: HTTP_INTERCEPTORS, useClass: YunzhiInterceptor, multi: true}
    ]
})
export class CoreModule {
}

服务

@Injectable({
    providedIn: CoreModule
})
export class CollegeService {
}

现在不往 root 里注入了,因为发现有的时候写 root 有人会搞不清楚模块的层级关系,然后就懵圈了。

为了规避这种问题,直接注入到核心模块中,防止有人误解。

norm

其实是想起一个规范的英文的,但是 spec 却被测试给用了,所以就去百度翻译了个放这了。

Angular 架构设计

这个包主要是存储数据规范的。

entity 存储实体,对应后台实体。

target 存储自定义的规范对象,历史的教训告诉我们,如果把所有都放到实体包里,这很糟糕。

page

这个是向小程序抄来的,小组件可以复用,大组件就需要单建目录了,都放一起看着混乱。

Angular 架构设计

分模块加载,每个功能一个单独的模块,模块职责划分清晰。

@NgModule({
    declarations: [
        SetupComponent
    ],
    imports: [
        SetupRouteModule,
        ShareModule
    ]
})
export class SetupModule {
}

模块中就这几行,什么废话都不要写,就声明本模块的组件,并导入本模块的路由和 Share 模块。其他的都不要写,第三方的导入交给 ShareModule 去处理。本模块只负责业务,不负责代码。

ShareModule

Angular 架构设计

全局复用的组件,全局复用的管道,全局复用的验证器,以及其他第三方组件的导入导出。

@NgModule({
    imports: [
        ComponentModule,
        PipeModule,
        RouterModule
    ],
    exports: [
        ComponentModule,
        PipeModule,
        RouterModule
    ]
})
export class ShareModule {
}

规规矩矩,整整洁洁。

Angular 架构设计

ShareModule 的子模块的实现都放在 api 目录里。

子模块示例:

@NgModule({
    declarations: [
        CourseTypePipe,
        SemesterStatusPipe,
        YunzhiGradeStatusPipe,
        YunzhiKlassStatusPipe,
        YunzhiScoreStatusPipe
    ],
    exports: [
        CourseTypePipe,
        SemesterStatusPipe,
        YunzhiGradeStatusPipe,
        YunzhiKlassStatusPipe,
        YunzhiScoreStatusPipe
    ]
})
export class PipeModule {
}

spec

测试目录,为什么单拿出来这个目录,主要是为了解决 Service 的测试数据问题。

Angular 架构设计

本模块存储所有以 .test.service.ts 结尾的测试 service

Angular 架构设计

然后所有的测试 Service 去继承原 Service ,并重写里面的方法,这里的 @Injectable() 注解中不用加 providedIn ,因为没有专业的测试模块,每个测试用例中我们使用 provide 进行注入。

@Injectable()
export class CollegeTestService extends CollegeService {
}

原来直接跑 ng test 特别快,根本看不清楚组件的创建,这两天发现了一个新套路,跑测试的时候上 YouTube 点开个视频看,然后电脑就特别卡,测试跑的时候就慢了。

然后就可以清楚地看到每个测试用例的执行过程,看到每个组件如何创建并显示。也不知道改了哪里,现在 Alice 跑测试的时候最后给出一个 Karma 的测试报告。

Angular 架构设计

直接把错误报出来,也好修改。

测试

测试最后怎么设计的呢?也说不明白,看代码就是了。最近才发现之前的测试用例写得都不正确。

其实一个测试,就是构建了一个测试的模块,该模块和其他模块都相同。

发现很多测试中为了能跑过,直接把公共组件或公共管道写在了 declarations 里,这是不合理的,虽然测试能跑过,但是理论上,这个测试就是测这个的,所以模块中的 declarations 只有它自己。

然后这里的 imports 也是经过反复的测试,导入 BrowserAnimationsModuleHttpClientTestingModuleRouterTestingModuleShareModule 这四个模块,这个测试的所有依赖就都有了,其他的什么都不要导入,看着混乱。

providers 声明本模块中要注入的对象,这里受益于 CoreModule 的设计, Service 都放在了 CoreModule 里,而业务模块是不能导入 CoreModule 的,只能导入 ShareModule ,所以模块中是用不了已有的 Service

所以,乖乖地给我建一个测试的 Service ,然后注入进去。也算是强制组员写测试的一种手段。

describe('SetupComponent', () => {
    let component: SetupComponent;
    let fixture: ComponentFixture<SetupComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [SetupComponent],
            imports: [
                BrowserAnimationsModule,
                HttpClientTestingModule,
                RouterTestingModule,
                ShareModule
            ],
            providers: [
                {
                    provide: UserService,
                    useClass: UserTestService
                }
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SetupComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    it('should create', () => {
        expect(component).toBeTruthy();
    });
});

总结

最佳实践,都是从坑里爬出来后才总结出来的。

Angular 架构设计

Angular 架构设计

上次我感慨 Angular 架构设计难的时候是 426 日,当时只是对 Alice 进行小改,还不到一月,如今一次性对前台做了这么大的改动,坑也踩得多了,爬出坑后,最佳实践,其实就在眼前。

这次的架构设计得很整洁,打完包后也很快,我很满意。

Angular 架构设计

古人学问无遗力,少壮工夫老始成。

纸上得来终觉浅,绝知此事要躬行。

——陆游《冬夜读书示子聿》

以后再设计不能纸上谈兵,要努力去实践,经历得多了,最佳实践自然就出来了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms Unlocked

Algorithms Unlocked

Thomas H. Cormen / The MIT Press / 2013-3-1 / USD 25.00

Have you ever wondered how your GPS can find the fastest way to your destination, selecting one route from seemingly countless possibilities in mere seconds? How your credit card account number is pro......一起来看看 《Algorithms Unlocked》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具