MVP Bundling is now implemented
This commit gets bundling to the point where it can be used now TODO: - Get ESBuild Stdout/stderr to not pop up in psb output - figure out how to split off map files so I'm not shunting them into script tags
This commit is contained in:
parent
8082f95491
commit
b3808f4136
4 changed files with 62 additions and 18 deletions
|
|
@ -29,7 +29,7 @@ library
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
exposed-modules: Markdown HTML Logger IR Logger.Shake Psb.Main Utilities Utilities.FilePath Utilities.Action Utilities.Javascript Utilities.CSS Templates Types Config Utilities.Bundling
|
exposed-modules: Markdown HTML Logger IR Logger.Shake Psb.Main Utilities Utilities.FilePath Utilities.Action Utilities.Javascript Utilities.CSS Templates Types Config Utilities.Bundling
|
||||||
other-modules: Utilities.Parsing
|
other-modules: Utilities.Parsing
|
||||||
build-depends: base >=4.20 && < 4.21, mustache >=2.4.2, shake >= 0.19.8, deriving-aeson >= 0.2.9, aeson, text >= 2.1.2, time, unordered-containers, yaml, megaparsec >= 9.7.0, transformers >= 0.6.2, css-syntax >= 0.1.0.2
|
build-depends: base >=4.20 && < 4.21, mustache >=2.4.2, shake >= 0.19.8, deriving-aeson >= 0.2.9, aeson, text >= 2.1.2, time, unordered-containers, yaml, megaparsec >= 9.7.0, transformers >= 0.6.2, bytestring
|
||||||
default-extensions: ApplicativeDo DataKinds NamedFieldPuns DerivingVia LambdaCase TypeApplications DeriveGeneric OverloadedRecordDot NamedFieldPuns DuplicateRecordFields DisambiguateRecordFields FlexibleInstances
|
default-extensions: ApplicativeDo DataKinds NamedFieldPuns DerivingVia LambdaCase TypeApplications DeriveGeneric OverloadedRecordDot NamedFieldPuns DuplicateRecordFields DisambiguateRecordFields FlexibleInstances
|
||||||
|
|
||||||
test-suite test-markdown-parse
|
test-suite test-markdown-parse
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import Text.Megaparsec (errorBundlePretty)
|
||||||
import Text.Mustache (ToMustache (toMustache))
|
import Text.Mustache (ToMustache (toMustache))
|
||||||
import Types
|
import Types
|
||||||
import Utilities.Action (getPublishedPosts, isDraft', markdownToHtml, markdownToPost, now, psbProgress)
|
import Utilities.Action (getPublishedPosts, isDraft', markdownToHtml, markdownToPost, now, psbProgress)
|
||||||
import Utilities.Bundling (bundled)
|
import Utilities.Bundling (BuildOracleVariant (CSS, Javascript), bundled)
|
||||||
import qualified Utilities.CSS as CSS
|
import qualified Utilities.CSS as CSS
|
||||||
import Utilities.FilePath (indexHtmlOutputPath, indexHtmlSourcePaths, isMarkdownPost, urlConvert)
|
import Utilities.FilePath (indexHtmlOutputPath, indexHtmlSourcePaths, isMarkdownPost, urlConvert)
|
||||||
import qualified Utilities.Javascript as JS
|
import qualified Utilities.Javascript as JS
|
||||||
|
|
@ -78,7 +78,6 @@ buildRules = do
|
||||||
postsRule
|
postsRule
|
||||||
rss
|
rss
|
||||||
bundled
|
bundled
|
||||||
pure ()
|
|
||||||
|
|
||||||
-- css_resources
|
-- css_resources
|
||||||
-- js_resources
|
-- js_resources
|
||||||
|
|
@ -130,6 +129,8 @@ markdownPost src = do
|
||||||
post <- readMarkdownPost src
|
post <- readMarkdownPost src
|
||||||
let rPost = fromPost post
|
let rPost = fromPost post
|
||||||
postHtml <- applyTemplate "post.html" rPost
|
postHtml <- applyTemplate "post.html" rPost
|
||||||
|
css_bundle <- Shake.askOracle CSS
|
||||||
|
js_bundle <- Shake.askOracle Javascript
|
||||||
|
|
||||||
time <- Utilities.Action.now
|
time <- Utilities.Action.now
|
||||||
-- Shake.putInfo $ T.unpack $ urlConvert target
|
-- Shake.putInfo $ T.unpack $ urlConvert target
|
||||||
|
|
@ -138,7 +139,9 @@ markdownPost src = do
|
||||||
{ pageTitle = rPostTitle rPost,
|
{ pageTitle = rPostTitle rPost,
|
||||||
pageContent = postHtml,
|
pageContent = postHtml,
|
||||||
pageNow = time,
|
pageNow = time,
|
||||||
pageUrl = urlConvert target
|
pageUrl = urlConvert target,
|
||||||
|
pageBundleCss = map T.pack css_bundle,
|
||||||
|
pageBundleJs = map T.pack js_bundle
|
||||||
}
|
}
|
||||||
applyTemplateAndWrite "default.html" page target
|
applyTemplateAndWrite "default.html" page target
|
||||||
|
|
||||||
|
|
@ -154,13 +157,17 @@ home =
|
||||||
let posts' = map fromPost posts
|
let posts' = map fromPost posts
|
||||||
html <- applyTemplate "home.html" $ HM.singleton "posts" posts'
|
html <- applyTemplate "home.html" $ HM.singleton "posts" posts'
|
||||||
time <- Utilities.Action.now
|
time <- Utilities.Action.now
|
||||||
|
css_bundle <- Shake.askOracle CSS
|
||||||
|
js_bundle <- Shake.askOracle Javascript
|
||||||
-- Shake.putInfo $ T.unpack $ urlConvert target
|
-- Shake.putInfo $ T.unpack $ urlConvert target
|
||||||
let page =
|
let page =
|
||||||
Page
|
Page
|
||||||
{ pageTitle = T.pack "Home",
|
{ pageTitle = T.pack "Home",
|
||||||
pageContent = html,
|
pageContent = html,
|
||||||
pageNow = time,
|
pageNow = time,
|
||||||
pageUrl = urlConvert target
|
pageUrl = urlConvert target,
|
||||||
|
pageBundleCss = map T.pack css_bundle,
|
||||||
|
pageBundleJs = map T.pack js_bundle
|
||||||
}
|
}
|
||||||
applyTemplateAndWrite "default.html" page target
|
applyTemplateAndWrite "default.html" page target
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,10 @@ data Page = Page
|
||||||
pageContent :: Text,
|
pageContent :: Text,
|
||||||
-- build time
|
-- build time
|
||||||
pageNow :: Text,
|
pageNow :: Text,
|
||||||
--
|
pageUrl :: Text,
|
||||||
pageUrl :: Text
|
-- from Bundles
|
||||||
|
pageBundleCss :: [Text],
|
||||||
|
pageBundleJs :: [Text]
|
||||||
}
|
}
|
||||||
deriving (Show, Generic)
|
deriving (Show, Generic)
|
||||||
deriving (ToJSON) via PrefixedSnake "page" Page
|
deriving (ToJSON) via PrefixedSnake "page" Page
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,27 @@
|
||||||
{-# LANGUAGE DeriveAnyClass #-}
|
{-# LANGUAGE DeriveAnyClass #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
|
||||||
module Utilities.Bundling
|
module Utilities.Bundling
|
||||||
( bundled,
|
( bundled,
|
||||||
|
BuildOracleVariant
|
||||||
|
( CSS,
|
||||||
|
Javascript
|
||||||
|
),
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import Config (buildDir, cssGlobs, jsGlobs, outputDir)
|
import Config (buildDir, cssGlobs, jsGlobs, outputDir)
|
||||||
import Development.Shake (Action, RuleResult, Rules, addOracle, cmd_, command_, getDirectoryFiles, need, (%>))
|
import Data.Aeson
|
||||||
|
import Data.Aeson (decode)
|
||||||
|
import Data.Aeson.Key (toText)
|
||||||
|
import qualified Data.Aeson.KeyMap as KM
|
||||||
|
import qualified Data.ByteString.Lazy as BL
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
import Data.String (IsString (fromString))
|
||||||
|
import Data.Text (Text)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Development.Shake (Action, RuleResult, Rules, addOracle, addOracleCache, cmd_, command_, getDirectoryFiles, need, newCache, readFile', (%>))
|
||||||
import Development.Shake.Classes
|
import Development.Shake.Classes
|
||||||
import Development.Shake.FilePath ((</>))
|
import Development.Shake.FilePath ((</>))
|
||||||
import GHC.Generics (Generic)
|
import GHC.Generics (Generic)
|
||||||
|
|
@ -32,10 +46,13 @@ resource_dir = outputDir </> "resources"
|
||||||
-- indicate completion/fulfill a need directive without rebuilding even when files
|
-- indicate completion/fulfill a need directive without rebuilding even when files
|
||||||
-- are left unchanged, maybe have the need be a $(filename).hash which we compute
|
-- are left unchanged, maybe have the need be a $(filename).hash which we compute
|
||||||
-- ourselves based on the unminified input
|
-- ourselves based on the unminified input
|
||||||
bundled :: Rules (BuildOracleVariant -> Action BuildOutputs)
|
bundled :: Rules ()
|
||||||
bundled = addOracle $ \q -> case q of
|
bundled = do
|
||||||
|
-- TODO: Need to adjust this oracle to split out source maps from js and css files
|
||||||
|
oracle <- addOracleCache $ \q -> case q of
|
||||||
CSS -> bundle_css
|
CSS -> bundle_css
|
||||||
Javascript -> bundle_scripts
|
Javascript -> bundle_scripts
|
||||||
|
pure ()
|
||||||
|
|
||||||
css_dir :: FilePath
|
css_dir :: FilePath
|
||||||
css_dir = resource_dir </> "css"
|
css_dir = resource_dir </> "css"
|
||||||
|
|
@ -52,21 +69,39 @@ css_esbuild_options =
|
||||||
"--metafile=" ++ css_meta_file
|
"--metafile=" ++ css_meta_file
|
||||||
]
|
]
|
||||||
|
|
||||||
|
newtype Metafile = Metafile
|
||||||
|
{ outputs :: Object -- keys are the file paths
|
||||||
|
}
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
|
instance FromJSON Metafile where
|
||||||
|
parseJSON = withObject "Metafile" $ \o ->
|
||||||
|
Metafile <$> o .: "outputs"
|
||||||
|
|
||||||
|
outputPaths :: Metafile -> BuildOutputs
|
||||||
|
outputPaths = map (T.unpack . toText) . KM.keys . outputs
|
||||||
|
|
||||||
|
metafile_outputs :: FilePath -> Action BuildOutputs
|
||||||
|
metafile_outputs metafile_path = do
|
||||||
|
src <- readFile' metafile_path
|
||||||
|
let intermediate = fromJust $ decode $ fromString src
|
||||||
|
pure $ outputPaths intermediate
|
||||||
|
|
||||||
-- need to take an input of resouces/blah.css
|
-- need to take an input of resouces/blah.css
|
||||||
-- and in addition to bundling it
|
-- and in addition to bundling it
|
||||||
bundle_css :: Action BuildOutputs
|
bundle_css :: Action BuildOutputs
|
||||||
bundle_css = do
|
bundle_css = do
|
||||||
need cssGlobs
|
need cssGlobs
|
||||||
css_files <- getDirectoryFiles "" cssGlobs
|
css_files <- getDirectoryFiles "" cssGlobs
|
||||||
cmd_ "esbuild" (generic_esbuild_options ++ css_esbuild_options ++ css_files)
|
cmd_ ("esbuild" :: String) (generic_esbuild_options ++ css_esbuild_options ++ css_files)
|
||||||
pure $ error "TODO: pull the list of files from the meta file"
|
metafile_outputs css_meta_file
|
||||||
|
|
||||||
-- Javascript and typescript
|
-- Javascript and typescript
|
||||||
-- potentially:
|
-- potentially:
|
||||||
-- "--target=es2020"
|
-- "--target=es2020"
|
||||||
-- , "--format=esm"
|
-- , "--format=esm"
|
||||||
js_esbuild_options :: [String]
|
js_esbuild_options :: [String]
|
||||||
js_esbuild_options = ["--outdir=" ++ js_dir, "--splitting", "--metafile=" ++ js_meta_file]
|
js_esbuild_options = ["--outdir=" ++ js_dir, "--splitting", "--format=esm", "--metafile=" ++ js_meta_file]
|
||||||
|
|
||||||
js_meta_file :: FilePath
|
js_meta_file :: FilePath
|
||||||
js_meta_file = buildDir </> "esbuild-js-meta.json"
|
js_meta_file = buildDir </> "esbuild-js-meta.json"
|
||||||
|
|
@ -77,6 +112,6 @@ js_dir = resource_dir </> "js"
|
||||||
bundle_scripts :: Action BuildOutputs
|
bundle_scripts :: Action BuildOutputs
|
||||||
bundle_scripts = do
|
bundle_scripts = do
|
||||||
need jsGlobs
|
need jsGlobs
|
||||||
js_files <- getDirectoryFiles "" cssGlobs
|
js_files <- getDirectoryFiles "" jsGlobs
|
||||||
cmd_ "esbuild" (generic_esbuild_options ++ js_esbuild_options ++ js_files)
|
cmd_ ("esbuild" :: String) (generic_esbuild_options ++ js_esbuild_options ++ js_files)
|
||||||
pure $ error "TODO: pull the list of files from the meta file"
|
metafile_outputs js_meta_file
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue