GettiNG started with Angular
Best practices when starting a new project
@seangwright
seangwright


2018/02/06
At a high level
- Conventions, formatting and tooling
- Project architecture
- Application infrastructure

Conventions, formatting and tooling
or
How I
learned to
stop worrying
about
tabs vs spaces
and
love programming
again


From this▲to this▼
- Develop the Angular application outside of your backend project
- Put it in its own repository
- Can be versioned / deployed separately
- Doesn't confuse the tooling
- Treats it as a real application
- Javascript developers are people too!
- Javascript developers are people too!
- Use VS Code for the best experience
- Both as a team and a developer
- Workspace settings live in the repo
-
\.vscode\.settings.json
-
- Strong support for extensions used in Angular projects, well regarded by the front-end dev community
- Use tooling to kill disagreements!
- VS Code extensions: TSLint, Prettier, Editorconfig, SCSS IntelliSense
-
\.vscode\.extensions.json
-
- 'Strict' Typescript settings in tsconfig.json
- Editor and compilation checks
- 'Format on Save' + Prettier = no need to reformat someone else's code
- Let Prettier be the bad guy!
- Let Prettier be the bad guy!
- VS Code extensions: TSLint, Prettier, Editorconfig, SCSS IntelliSense
- Naming and syntax conventions
- Singular for features/modules, singular or plural for components/services/directives (plural can be tricky)
- Component and directive prefix of 2 or 3 characters (keeps templates readable)
- Use Angular style commit messages
- Examples
-
'feat(notification.service): add display param'
-
'refactor(order models): rename couponId to couponCodeId'
-
- Examples
- Consistent component/directive/service/module file creation
- See: Project Architecture - Use Angular CLI
- See: Project Architecture - Use Angular CLI
- Absolute paths for ES Modules
- Helps in refactoring (moving files around or renaming)
- Easier to organize alphabetically
- See: Project Architecture - Keep a flat file structure
- * caveats
- Do not use null!
- Javascript already has undefined
- 1 option is better than 2 used randomly
- Explicitly type a field/method/variable as undefined if it can be
- See: below
- See: below
- Assign default values everywhere you can
- Helps prevent annoying errors
- "Cannot read property 'name' of undefined"
- Null is the 'billion dollar mistake'
- Choose intelligent defaults and be consistent with them
- '' for string
- 0 for number
- [] for arrays
- Predicatable and work well in expressions
- if (user.id || user.name) { // do something }
- Predicatable and work well in expressions
- Helps prevent annoying errors
Questions,
thoughts,
concerns?
Links
- VS Code https://code.visualstudio.com/
- Extensions
- Prettier https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
- Angular Language Service https://marketplace.visualstudio.com/items?itemName=Angular.ng-template
- Editorconfig https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig
- SCSS IntelliSense https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-scss
- TSLint https://marketplace.visualstudio.com/items?itemName=eg2.tslint
Links
- TSConfig schema http://json.schemastore.org/tsconfig
- Angular commit messages https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
- Codelyzer https://github.com/mgechev/codelyzer
Links
- Prettier + TSLint sometimes causes issues (they both want control)
- tslint-config-prettier https://github.com/alexjoverm/tslint-config-prettier
- tslint-config-prettier https://github.com/alexjoverm/tslint-config-prettier
- In the past there have been issues with Angular + 'Strict' tsconfig
- tslint-consistent-codestyle https://github.com/ajafff/tslint-consistent-codestyle
- tslint-consistent-codestyle https://github.com/ajafff/tslint-consistent-codestyle
- Null 'billion dollar mistake' https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
Project Architecture
Planning and consistency!
... because building things is hard enough already

or
- Follow the Angular Style Guide
- It's not the final word but it's a great place to start
- Take what works for your team and skip what doesn't but learn from other's mistakes
- Same goes for this talk! (meta!)
- Take what works for your team and skip what doesn't but learn from other's mistakes
- Feature modules, Core/Application module and Shared module
- It's not the final word but it's a great place to start
- Keep a flat file structure as long as possible
- Don't add hierarchy with less than 20 files
- You can always move files as the app grows
- See: Conventions, formatting and tooling - Absolute paths for ES Modules
- * caveats
- See: Conventions, formatting and tooling - Absolute paths for ES Modules
- Remove floating semver in package.json
- Use package management tooling to guarantee reproducible dev environment and builds
-
package-lock.json
-
yarn.lock
-
- Use package management tooling to guarantee reproducible dev environment and builds
- Use yarn?
- Faster installs (+) but extra toolchain piece (-)
- Decide before starting your project and run
-
ng set --global packageManager=yarn
-
- Maintain your application version
- 1 source of truth (package.json is a nice place)
- Use to deploy the version with and embed in your app
- See below: Enhance the CLI build process
- Enhance the CLI build process
- Use pre/post hooks in npm scripts to simplify commands
- Create a folder to contain all your build infrastructure
- You don't need Gulp/Grunt, just Node
- Assuming NodeJS v8.x for dev environment
- Typescript
- Async/await for file system access
- Helpful packages
- fs-extra, colors, pjson, ts-node, dateformat, tar
- Generate pre-build
- version.ts, version.json
- Generate post-build
- v.<version>.txt, .tar.gz
- Can be used to build more complex pre/post assets
- i18n build process support
- Set custom host for your app
- http://localhost:4200 is ok for a demo
- But http://client-app-accounting.company.io is better
- Helps when logging request Origin / Referrer
- Helps when logging request Origin / Referrer
- Use proxies if integrating with an API
- No need to change API Uri base on environment
- Can re-write set-cookie headers
Questions,
thoughts,
concerns?
Links
- Angular Style Guide https://angular.io/guide/styleguide
- Core Module(s) https://angular.io/guide/styleguide#core-feature-module
- Core Module(s) https://angular.io/guide/styleguide#core-feature-module
- Absolute paths for ES Module imports https://github.com/angular/angular-cli/issues/5875#issuecomment-323809855
- Yarn https://yarnpkg.com/lang/en/docs/install/
- Build process https://github.com/sgwatgit/gettiNG-started-with-angular
- Proxies https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md
Application Infrastructure
Let's get into some code
(the weeds)

or
- Lazy load everything
- The CLI makes this easy
- Helps break up your app into logical bundles
- Both architecturally and on the filesystem when deployed
- Users only pay for what they want
- Sensitive (admin only) code isn't downloaded for users that don't have access
- Add a debug.service.ts
- Replaces calls to console.<X>()
- Track calls in codebase with CodeLens
- Toggle on/off at runtime with localStorage
- Off by default with production builds
- Type unions can replace Enums and magic strings
- Great for common messages displayed in UI
- Helpful for content managers (BA / Product owner) to centralize messaging for review
- Becomes a resource string dictionary
- Extends to i18n integration
- Still gives type support! Typescript FTW!

- RxJS Lettable operators
- Import only what you need
- Combined with tsconfig noUnusedLocals
- See: Conventions, formatting and tooling - 'Strict' Typescript settings
- See: Conventions, formatting and tooling - 'Strict' Typescript settings
- Combined with tsconfig noUnusedLocals
- Import only what you need
- Use ES Modules for helper functions
- Don't need formality of DI if they don't have state
- Easy to import, only available where needed
- See: parameterize, serialize, buildDefaultForm
- Keep hardcoded environment values in environment files
- Use XHR request, pre-app init, for config values deployed out of band from Angular build process
- Can be helpful to manage ENV values in CI/CD
- Use XHR request, pre-app init, for config values deployed out of band from Angular build process
- Avoid base classes / inheritance
- If necessary, then keep the API thin otherwise you restrict flexibility as your app grows and use-cases change
- Create a utility.service.ts to contain all base helper services
- Examples
- debug.service.ts
- notification.service.ts
- session.service.ts (auth / user state)
- Helps prevent app-wide changes to base constructor
- Examples
- Use Observable management patterns
- ngUnsubscribe for complex Observable management in Components
- Use shareReplay operator and/or async pipe for simpler cases
- Client-side application updates
- Consider browser caching
- How to force client app updates when the backend API changes?
- Figure out user experience and implementation architecture for updating
- Modals vs buttons? Can user delay updates?
- Process transparent to user?
- How often to check for updates on server?
- Test the update process, experience across browsers!
- Take steps on server side
- Cache headers on index.html
- Embed version in app
- See: Application architecture - Maintain your application version
- Use global error handler to store/report errors to API
- Don't access global Document or Window objects
- Angular API probably provides a way around this
- If you need too, create wrapper WindowRef/DocumentRef services
- Can be swapped out during SSR
- Can be swapped out during SSR
- Create IEnvironment interface to keep environment files in sync
- Use feature module 'root' components
- Easy to apply styling / UI for all components / routes in a feature
- Helps handle Angular router caching components when route changes
Questions,
thoughts,
concerns?
Links
- Lazy loading https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html
- String literal type unions in Typescript https://blog.mariusschulz.com/2016/03/31/string-literal-types-in-typescript
- RxJS lettable operators https://blog.angularindepth.com/rxjs-understanding-lettable-operators-fe74dda186d3
Links
- Observables management
- publishReplay, shareReplay
- ngUnsubscribe pattern https://stackoverflow.com/a/41177163/939634
- With decorator https://github.com/NetanelBasal/angular2-take-until-destroy
- With base component/class https://stackoverflow.com/a/43579849/939634
- Global error handler https://angular.io/api/core/ErrorHandler
Thanks!
Now, let's look at code (if there's still time)
GettiNG started with Angular
By Sean Wright
GettiNG started with Angular
Best practices when starting a new Angular project
- 811