yesod-static-1.5.1.1: Static file serving subsite for Yesod Web Framework.

Safe Haskell | None
Language | Haskell98

Yesod.EmbeddedStatic

Contents

- Subsite
- Generators
- Orphan instances

Description

A subsite which serves static content which is embedded at compile time.

At compile time, you supply a list of files, directories, processing functions (like javascript minification), and even custom content generators. You can also specify the specific relative locations within the static subsite where these resources should appear. The `mkEmbeddedStatic` function then computes the resources and embeds them directly into the executable at compile time, so that the original files do not need to be distributed along with the executable. The content is also compressed and hashed at compile time, so that during runtime the compressed content can be sent directly on the wire with the appropriate HTTP header. The precomputed hash is used for an ETag so the client does not redownload the content multiple times. There is also a development mode which does not embed the contents but recomputes it on every request. A simple example using an embedded static subsite is static-embed.hs.

To add this to a scaffolded project, replace the code in `Settings/StaticFiles.hs` with a call to `mkEmbeddedStatic` with the list of all your generators, use the type `EmbeddedStatic` in your site datatype for `getStatic`, update the route for `/static` to use the type `EmbeddedStatic`, use `embedStaticContent` for `addStaticContent` in `Foundation.hs`, use the routes generated by `mkEmbeddedStatic` and exported by `Settings/StaticFiles.hs` to link to your static content, and finally update `Application.hs` use the variable binding created by `mkEmbeddedStatic` which contains the created `EmbeddedStatic`.

It is recommended that you serve static resources from a separate domain to save time on transmitting cookies. You can use `urlParamRenderOverride` to do so, by redirecting routes to this subsite to a different domain (but the same path) and then pointing the alternative domain to this server. In addition, you might consider using a reverse proxy like varnish or squid to cache the static content, but the embedded content in this subsite is cached and served directly from memory so is already quite fast.

Synopsis

- data EmbeddedStatic
- embeddedResourceR :: [Text] -> [(Text, Text)] -> Route EmbeddedStatic
- mkEmbeddedStatic :: Bool -> String -> [Generator] -> Q [Dec]
- embedStaticContent :: Yesod site => (site -> EmbeddedStatic) -> (Route EmbeddedStatic -> Route site) -> (ByteString -> Either a ByteString) -> AddStaticContent site
- module Yesod.EmbeddedStatic.Generators

# Subsite

data EmbeddedStatic #

The subsite for the embedded static file server.

Instances

RenderRoute EmbeddedStatic # |
Associated Types data Route EmbeddedStatic :: * # Methods renderRoute :: Route EmbeddedStatic -> ([Text], [(Text, Text)]) #
ParseRoute EmbeddedStatic # |
Methods parseRoute :: ([Text], [(Text, Text)]) -> Maybe (Route EmbeddedStatic) #
Eq (Route EmbeddedStatic) # |
Methods (==) :: Route EmbeddedStatic -> Route EmbeddedStatic -> Bool # (/=) :: Route EmbeddedStatic -> Route EmbeddedStatic -> Bool #
Read (Route EmbeddedStatic) # |
Methods readsPrec :: Int -> ReadS (Route EmbeddedStatic) # readList :: ReadS [Route EmbeddedStatic] # readPrec :: ReadPrec (Route EmbeddedStatic) # readListPrec :: ReadPrec [Route EmbeddedStatic] #
Show (Route EmbeddedStatic) # |
Methods showsPrec :: Int -> Route EmbeddedStatic -> ShowS # show :: Route EmbeddedStatic -> String # showList :: [Route EmbeddedStatic] -> ShowS #
data Route EmbeddedStatic # |
data Route EmbeddedStatic = EmbeddedResourceR [Text] [(Text, Text)] | EmbeddedWidgetR Text

embeddedResourceR :: [Text] -> [(Text, Text)] -> Route EmbeddedStatic #

Construct a route to an embedded resource.

mkEmbeddedStatic #

Arguments

:: Bool | development?
-> String | variable name for the created `EmbeddedStatic`
-> [Generator] | the generators (see Yesod.EmbeddedStatic.Generators)
-> Q [Dec] |

Creates an `EmbeddedStatic` by running, at compile time, a list of generators. Each generator produces a list of entries to embed into the executable.

This template haskell splice creates a variable binding holding the resulting `EmbeddedStatic` and in addition creates variable bindings for all the routes produced by the generators. For example, if a directory called static has the following contents:

- js/jquery.js
- css/bootstrap.css
- img/logo.png

then a call to

    #ifdef DEVELOPMENT
    #define DEV_BOOL True
    #else
    #define DEV_BOOL False
    #endif
    mkEmbeddedStatic DEV_BOOL "myStatic" [embedDir "static"]

will produce variables

    myStatic :: EmbeddedStatic
    js_jquery_js :: Route EmbeddedStatic
    css_bootstrap_css :: Route EmbeddedStatic
    img_logo_png :: Route EmbeddedStatic

embedStaticContent #

Arguments

:: Yesod site |
=> (site -> EmbeddedStatic) | How to retrieve the embedded static subsite from your site
-> (Route EmbeddedStatic -> Route site) | how to convert an embedded static route
-> (ByteString -> Either a ByteString) | javascript minifier
-> AddStaticContent site |

Use this for `addStaticContent` to have the widget static content be served by the embedded static subsite. For example,

    import Yesod
    import Yesod.EmbeddedStatic
    import Text.Jasmine (minifym)

    data MySite = { ..., getStatic :: EmbeddedStatic, ... }

    mkYesod "MySite" [parseRoutes|
    ...
    /static StaticR EmbeddedStatic getStatic
    ...
    |]

    instance Yesod MySite where
        ...
        addStaticContent = embedStaticContent getStatic StaticR mini
            where mini = if development then Right else minifym
        ...

# Generators

module Yesod.EmbeddedStatic.Generators

# Orphan instances

Yesod master => YesodSubDispatch EmbeddedStatic (HandlerT master IO) # |
Methods yesodSubDispatch :: YesodSubRunnerEnv EmbeddedStatic (HandlerSite (HandlerT master IO)) (HandlerT master IO) -> Application #