Snap Framework

repository·master·Indexed 19 days ago

https://github.com/snapframework/snap

A high-performance, modular web development framework and server written in Haskell. It features a unique 'snaplet' API for building composable applications, a high-speed HTTP server with optional libev backend, and an XML-based templating system. The framework utilizes the Handler and Initializer monads for request processing and application setup, employing lenses for scoped state management.

Tokens
1.5K
Snippets
5
Records
11
Agent score
65%

What's inside Snap

  1. Overview of the Snap Framework

    master

    Snap is a high-performance web development framework and server written in Haskell. It is designed to be a comprehensive web toolkit that balances high performance with simplicity and ease of use, even for developers new to Haskell.

    Core components include:

    • High-speed HTTP server: Supports an optional high-concurrency backend via the libev library.
    • Web Programming Monad: Provides a clean and sensible monad for handling web logic.
    • XML-based Templating: An XML-based system for generating HTML that allows binding Haskell functionality to XML tags.
    • Snaplet System: A mechanism for building websites using composable, modular pieces.
  2. Understand the Handler monad and state management

    master

    The Handler monad is the primary way to process requests. It implements the 'Request Local State' goal by acting as a state transformer over the Snap monad.

    To manage composability and state mutation across different scopes (e.g., moving from the top-level application state down to a specific snaplet's state), the framework uses a specialized monad called Lensed (which evolved from LensT).

    Key behaviors:

    • Scoped Mutation: Instead of using simple accessor functions, the framework uses lenses. This allows you to maintain a single top-level state while using a lens to mutate the specific sub-state of the current context.
    • Context Switching: You can change the scope of the current snaplet (and thus the available state) using pattern-matching functions similar to withReader.
  3. How Snaplet design goals shape the framework

    master

    The Snap Framework is built around three core design principles that dictate how you write and compose snaplets:

    1. Request local state: Snaplets can define their own state that is mutable but scoped strictly to the lifecycle of a single request.
    2. Composability: Applications and snaplets are designed to be interchangeable, allowing you to build complex systems by gluing smaller snaplets together.
    3. Availability: Application state is accessible throughout the system without requiring manual threading of state parameters through every function call.
  4. Core components of the Snap Framework

    master

    The Snap Framework consists of two primary architectural pillars:

    • Development Recompilation Library: A library that allows Snap applications to recompile actions on the fly during development mode. This feature incurs no performance penalty when running in production mode.
    • Snaplet API: A specialized API that enables developers to build web applications from small, composable pieces called "snaplets."

    Note on the snap CLI: The command-line utility used for creating initial applications is not part of this package. Since version 1.0, it is provided by the snap-templates package.

  5. Understand the Initializer monad and application reloading

    master

    The Initializer monad is used for two main purposes:

    1. Setup: Defining routes, cleanup actions, reading configuration files, and initializing/interacting with other snaplets.
    2. Application Reloading: Handling the state when an application is reloaded from a browser.

    Key Implementation Details for Developers:

    • Deferred State Modification: Because the top-level state object isn't fully constructed during initialization, you cannot modify other snaplets' states directly. Instead, you construct modifier functions (which form a monoid) that are applied at the end of the initialization process.
    • Status Reporting: When using the Initializer monad, you should use printInfo to communicate status and errors. This ensures that during application reloading, messages are sent to the browser instead of just the server console.
  6. Learn about Snaplets

    master

    To understand the Snaplet architecture and how to build composable web applications, follow this recommended learning path:

    1. Tutorial: Read Tutorial.lhs located in the project_template/tutorial/src directory of the snap-templates package.
    2. Documentation: Generate and read the Haddock documentation.
    3. Examples: Examine the test code, as it functions as a practical example application covering many common use cases.
    4. Deep Dive: Read design.md for insights into the implementation details.
  7. Use the HasHeist type class to simplify Heist API calls

    master

    Normally, to interact with a snaplet like Heist, you must use with or withTop to pass a lens to the desired snaplet. This is necessary to support multiple instances of the same snaplet.

    However, if you have a single instance of Heist and want to avoid manually changing the context every time, you can implement the HasHeist type class. This creates a compile-time association between your application type and the Heist lens, allowing Heist API functions to work without explicit with calls.

    To implement HasHeist, you must use subSnaplet because the class requires a Lens (Snaplet v) (Snaplet (Heist b)) rather than the standard lens provided by mkLabels.

    instance HasHeist App where
        heistLens = subSnaplet heist
  8. Build Snap using Nix

    master

    A Nix shell is provided for the Snap Framework. You can enter the environment using nix-shell. If you use nix-direnv, you can automate the environment loading by creating a .envrc file.

    echo 'use nix' > .envrc && direnv allow
  9. Build Haddock documentation

    master

    You can generate documentation using Cabal:

    • To build documentation for the snap library specifically: cabal haddock snap
    • To build documentation for the entire project including git submodules: cabal haddock-project
    cabal haddock snap
    # or
    cabal haddock-project
  10. Build Snap from source

    master

    To build the Snap Framework from a cloned repository, you must first initialize and update the submodules to ensure all dependencies are at the correct versions, then use Cabal to build the project.

    1. Update submodules: git submodule update --init --recursive
    2. Build all components: cabal build all
    git submodule update --init --recursive
    cabal build all