Deployment

In previous chapters, our main focus was on the development part of the application. We’ve seen the result: we have a slick web application that we can run locally. However, eventually we will need to deploy it to a server so that more people are able to

  • PDF / 173,638 Bytes
  • 12 Pages / 504 x 720 pts Page_size
  • 14 Downloads / 206 Views

DOWNLOAD

REPORT


Deployment In previous chapters, our main focus was on the development part of the application. We’ve seen the result: we have a slick web application that we can run locally. However, eventually we will need to deploy it to a server so that more people are able to access it. In this chapter, we will turn our focus into the deployment part of the application. We will first learn to build the application for production and then finally deploy it with Docker.

Building Application for Production Our application requires some external resources to be able to run correctly, for example, images and SQL migration files. This needs to be taken into consideration when building an application that is easily shippable. In addition to that, we also want to use many tools that statically analyze our code for common Haskell pitfalls. This helps to prevent trivial issues from appearing in production. In this section we will look into code quality tools and how to package our external resources, along with application binary.

GHC Compiler Flags The first tool that we will look at for ensuring our code quality is not exactly a tool, but rather some flags in our compiler. GHC comes with functionalities that would warn of common mistakes in Haskell source code. We just need to enable that by specifying the correct flags. Add the following lines at the root of your package.yaml file for enabling them: ghc-options: - -Wall - -Werror - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints © Ecky Putrady 2018 E. Putrady, Practical Web Development with Haskell, https://doi.org/10.1007/978-1-4842-3739-7_12

261

Chapter 12

Deployment

The -Wall flag enables GHC to warn for basic, common mistakes. Some examples of warning produced with this flag are unused imports, usage of tabs, and unused variables. The -Wincomplete-record-updates flag checks for a record update that might fail at runtime. Let’s see an example code: data A   = B { x :: Int }   | C f :: A -> A f a = a { x = 10 } In the preceding example, the code will compile just fine. However, if f is called with C, then the program will crash at runtime. With -Wincomplete-record-updates enabled, this code will produce a warning. -Wincomplete-uni-patterns checks for incomplete pattern matching in lambda expressions. For example, the following code will produce a warning if this flag is enabled: a = \[] -> 2 -Wredundant-constraints checks for constraints that are unnecessary. For example: f :: (Monad m, MonadIO m) => m () In the preceding example, Monad constraint is unnecessary because MonadIO already implies Monad constraint Unfortunately, this flag does not detect redundant constraints in type if we use ConstraintKinds language pragma. For example, the following code does not produce any warning: type Repo m = (Monad m, MonadIO m) f :: Repo m => m () -Werror turns any warning into a fatal error during compilation. This effectively causes the build to fail if there is any warning in our code. Without enabling this flag, the warnings will all just be pri