NgModulesのドキュメント読む
前回のスタイルガイドに続き、ドキュメント読んで気になる箇所を抜粋。
- NgModules
- Angular modularity
- The root AppModule
- Bootstrapping in main.ts
- Declare directives and components
- Service providers
- Import supporting modules
- Resolve directive conflicts
- Feature modules
- Lazy-loading modules with the router
- Shared modules
- The Core module
- Cleanup
- Configure core services with CoreModule.forRoot
- Prevent reimport of the CoreModule
- Conclusion
NgModules
- NgModuleのコンセプトをチュートリアル形式で説明したもの
Angular modularity
@NgModule
のmetadata- モジュールクラスは必ず1つある (root module)
The root AppModule
Bootstrapping in main.ts
Declare directives and components
Service providers
Modules are a great way to provide services for all of the module’s components.
The Dependency Injection page describes the Angular hierarchical dependency-injection system and how to configure that system with providers at different levels of the application’s component tree.
(Dependency Injectionも後で読む)
- モジュールはアプリケーションのroot dependency injectorにprovidersを追加し、servicesをアプリケーションのどこからでも利用可能にする
Import supporting modules
BrowserModule
をimportするとCommonModule
もimportされるCommonModule
はngIf
,ngFor
などを宣言している
Application-scoped providers
- serviceをmoduleに登録すると application-scoped になる (どこからでもinjectできるようになる)
- アーキテクチャ的には
ContactService
は他のドメインで利用することはないので、injectできないようにしたい - Angularは意図的に module-scoping mechanism を提供していない
Read more in the How do I restrict service scope to a module? section of the NgModule FAQs page.
Resolve directive conflicts
Feature modules
- モジュールは他のモジュールで宣言されているcomponents, directives, またはpipesへのアクセスを継承しない
Lazy-loading modules with the router
src/app/app-routing.module.ts
export const routes: Routes = [ { path: '', redirectTo: 'contact', pathMatch: 'full'}, { path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' }, { path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' } ];
- routerについてはRouting & Navigation
cotact
routeは Contact featureのrouting moduleで設定- routerにより
ContactComponent
に遷移する場合、publicにする必要はない (exportする必要はない)ContactComponent
はselectorも必要としない
Shared modules
src/app/src/app/shared/shared.module.ts
@NgModule({ imports: [ CommonModule ], declarations: [ AwesomePipe, HighlightDirective ], exports: [ AwesomePipe, HighlightDirective, // re-exports the CommonModule and FormsModule CommonModule, FormsModule ] })
SharedModule
をimportすればCommonModule
,FormsModule
もimportされるようになるCommonModule
がimportされているのは、SharedModule
が必要としているから
Do not specify app-wide singleton providers in a shared module. A lazy-loaded module that imports that shared module makes its own copy of the service.
The Core module
CoreModule
は一度だけimportされるAppRoot
moduleがimportする
Cleanup
Configure core services with CoreModule.forRoot
- 慣例で、
forRoot
のstatic methodはserviceの提供と設定を同時に実行する- serviceの設定オブジェクトを受け取り、
ModuleWithProviders
を返す
- serviceの設定オブジェクトを受け取り、
More precisely, Angular accumulates all imported providers before appending the items listed in @NgModule.providers. This sequence ensures that whatever you add explicitly to the AppModule providers takes precedence over the providers of imported modules.
src/app/core/user.service.ts (constructor)
constructor(@Optional() config: UserServiceConfig) { if (config) { this._userName = config.userName; } }
src/app/core/core.module.ts (forRoot)
static forRoot(config: UserServiceConfig): ModuleWithProviders { return { ngModule: CoreModule, providers: [ {provide: UserServiceConfig, useValue: config } ] }; }
src/app//app.module.ts (imports)
imports: [ BrowserModule, ContactModule, CoreModule.forRoot({userName: 'Miss Marple'}), AppRoutingModule ],
Prevent reimport of the CoreModule
src/app/core/core.module.ts
constructor (@Optional() @SkipSelf() parentModule: CoreModule) { if (parentModule) { throw new Error( 'CoreModule is already loaded. Import it in the AppModule only'); } }
Conclusion
Angular4スタイルガイド読む
Angular公式のStyle Guideから気になった箇所を抜粋したものです。
Style GuideとNgModulesについての公式ドキュメントを読んだら、実際のアプリを作るときの大枠がある程度整理できました。
ドキュメントはそれなりに長いですが、命名規則など、Angular CLIを利用して入れば特に意識しなくても実現できている箇所も多いです。
- Style Guide
Style Guide
Single responsibility
Consider limiting files to 400 lines of code.
Consider limiting to no more than 75 lines.
Naming
Coding conventions
Constants
Do declare variables with const if their values should not change during the application lifetime.
Interfaces
Do name an interface using upper camel case.
Consider naming an interface without an I prefix.
Consider using a class instead of an interface.
Application structure and Angular modules
All of the app’s code goes in a folder named
src
. All feature areas are in their own folder, with their own Angular module.All third party vendor scripts are stored in another folder and not in the
src
folder.
LIFT
Locate
Identify
Consider creating sub-folders when a folder reaches seven or more files.
T-DRY
Why? Being DRY is important, but not crucial if it sacrifices the other elements of LIFT. That’s why it’s called T-DRY.
Overall structural guidelines
https://angular.io/guide/styleguide#file-tree
Folders-by-feature structure
Do create an Angular module for each feature area.
Shared feature module
Avoid providing services in shared modules. Services are usually singletons that are provided once for the entire application or in a particular feature module.
Do import all modules required by the assets in the
SharedModule
; for example,CommonModule
andFormsModule
.Avoid specifying app-wide singleton providers in a
SharedModule
. Intentional singletons are OK. Take care.Why? A lazy loaded feature module that imports that shared module will make its own copy of the service and likely have undesireable results.
Core feature module
Consider collecting numerous, auxiliary, single-use classes inside a core module to simplify the apparent structure of a feature module.
Do gather application-wide, single use components in the CoreModule. Import it once (in the AppModule) when the app starts and never import it anywhere else. (e.g. NavComponent and SpinnerComponent).
Prevent re-import of the core module
Do guard against reimporting of CoreModule and fail fast by adding guard logic.
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string) { if (parentModule) { throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`); } }
Components
Member sequence
Do place properties up top followed by methods.
Do place private members after public members, alphabetized.
Delegate complex component logic to services
Do limit logic in a component to only that required for the view. All other logic should be delegated to services.
/* avoid */ private hideSpinner() { // hide the spinner }
Directives
HostListener/HostBinding decorators versus host metadata
Consider preferring the @HostListener and @HostBinding to the host property of the @Directive and @Component decorators.
Services
Providing a service
Do provide services to the Angular injector at the top-most component where they will be shared.
Why? When providing the service to a top level component, that instance is shared and available to all child components of that top level component.
Data Services
Lifecycle hooks
Appendix
Angular4さわる
これは何か
新機能開発をAngular4で作り始めました。その時に調べたことのメモです。
Angular CLI使っています。
前提知識
調べたことメモ
Angular CLI
- 本家 README
ng new
- new · angular/angular-cli Wiki · GitHub
- 例: scssを利用したプロジェクトを始めたい
ng new [name] --style=scss
ng serve
ng generate
- 便利、基本的にファイルはこれで生成しています
- generate · angular/angular-cli Wiki · GitHub
Autoprefixer
環境変数
上記ページ以外にもWikiのstoriesからいろいろ確認できます。
stories · angular/angular-cli Wiki · GitHub
IE9, IE10, IE11対応
src/polyfills.ts
- 必要なpolyfillが用意されている
(最初はコメントアウトされている)
- 必要なpolyfillが用意されている
ビルド
- build · angular/angular-cli Wiki · GitHub
-dev
-prod
はメタフラグ- base urlを変えたい
--base-href
SCSS
- 本家
- Angular - linkComponent Styles
- Special selectors
:host
to target styles in the element that hosts the component
- View encapsulation
- Special selectors
- Angular - linkComponent Styles
- Bootstrap 4
npm install bootstrap@4.0.0-alpha.6 --save
- SCSS with Angular-cli - Qiita
VS Codeエクステンション
- Angular Language Service - Visual Studio Marketplace
- テンプレートでも、コンポーネントメンバーの補完が可能になります
-
- 自分の環境でも個別Htmlファイルの場合、うまく動いてくれませんでした
- Angular 2+ Snippets - TypeScript, Html, ngRx, Angular Flex Layout & Testing - Visual Studio Marketplace
- AngularJSのコードを書くとAngularのコードをサジェストしてくれます
よかったチュートリアル
- The Ultimate Angular CLI Reference Guide — SitePoint
- Angular 2 Tutorial: Create a CRUD App with Angular CLI — SitePoint
- Understanding Component Architecture: Refactoring an Angular App — SitePoint
- Angular and RxJS: Create an API Service to Talk to a REST Backend — SitePoint
Angular CLIを利用したチュートリアルのシリーズです。
Githubにコードがあります。
GitHub - sitepoint-editors/angular-todo-app: Todo app for Angular2+
画像を内接リサイズにする
css - Resize to fit image in div, and center horizontally and vertically - Stack Overflow
transform
とposition: absolute
を利用します。
前の記事のアスペクト比を保つcssを利用するとこんな感じです。
object-fit
というプロパティを利用すればもっと簡単でした。(でもIEには対応していない)
object-fit - CSS | MDN
アスペクト比を保つ
「padding-topに%を設定すると、包括しているブロックの幅を基準にする」という仕様を利用します。
以下のコードは、アスペクト比を4:3にする場合。
.a43 { border: 1px solid #000; width: 160px; position: relative; } .a43:before { content: ''; display: block; /* アスペクト比 4:3 */ padding-top:75%; } .a43-inner { position: absolute; top: 0; }
<div class="a43"> <div class="a43-inner"> foo<br> bar </div> </div>
AngularでBugsnagを利用
Angular4始めました。
Angularでエラーをインターセプトする場合はこんな感じ。
import { ErrorHandler, Injectable} from '@angular/core'; import { environment } from '../environments/environment'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { constructor() { Bugsnag.releaseStage = = environment.production ? 'production' : 'develop'; } handleError(error) { Bugsnag.notifyException(error); throw error; } } // --- @NgModule({ providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }] }) export class AppModule { }
VS Codeでタイトルバーの色変更
複数のプロジェクトやライブラリをみる場合に便利。
画像の例は、自分の仕事とAngularとBootstrap4を開いている場合。
// Place your settings in this file to overwrite default and user settings. { "workbench.colorCustomizations": { "titleBar.activeBackground": "#1976d2" } }