GettiNG started with Angular

Best practices when starting a new project

@seangwright
seangwright

2018/02/06

At a high level

  1. Conventions, formatting and tooling
     
  2. Project architecture
     
  3. 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!
         
  • 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!
         
  • 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'
        
        
  • Consistent component/directive/service/module file creation
    • 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
         
  • 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 }

Questions,

thoughts,

concerns?

Links

Links

Links

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!)
    • Feature modules, Core/Application module and Shared module
       
  • 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
  • Remove floating semver in package.json
    • Use package management tooling to guarantee reproducible dev environment and builds
      • package-lock.json
      • yarn.lock
        
        
  • 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
         
  • 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

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
           
  • 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
  • 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
         
  • 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
         
  • 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

Links

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