on 5cde2aa help sign in
default.nix+30−2
since splitsnapshots
unifiedsplit
@@ -2,6 +2,7 @@
2, profiling ? false
2, profiling ? false
3, iosSdkVersion ? "10.2"
3, iosSdkVersion ? "10.2"
4, config ? {}
4, config ? {}
5+, enableWasm ? true
5, reflex-platform-func ? import ./dep/reflex-platform
6, reflex-platform-func ? import ./dep/reflex-platform
6}:
7}:
7let
8let
@@ -85,6 +86,31 @@ in rec {
85 echo "//# sourceMappingURL=all.js.map" >> all.js
86 echo "//# sourceMappingURL=all.js.map" >> all.js
86 ''}
87 ''}
87 '';
88 '';
89+ webabi = pkgs.callPackage ./dep/webabi {};
90+ # wasm-opt seems to have no effect
91+ stripWasm = frontend: pkgs.runCommand "stripWasm" {} ''
92+ mkdir $out
93+ cd $out
94+ ln -s "${frontend}/bin/frontend" frontend.original.wasm
95+ cp "${frontend}/bin/frontend" frontend.wasm
96+ chmod u+rw frontend.wasm
97+ chmod a-x frontend.wasm
98+ ${pkgs.wabt}/bin/wasm-strip frontend.wasm
99+ '';
100+
101+ # The ghcjs and wasm files are put in a single asset, as they need to be in sync and served together.
102+ combinedJsWasmAssets = frontendJs: optimizationLevel: frontendWasm: pkgs.runCommand "combinedJsWasmAssets" {} ''
103+ mkdir $out
104+ cd $out
105+ ${if frontendJs != null then ''
106+ ln -s ${compressedJs frontendJs optimizationLevel}/* .
107+ '' else '' ''}
108+ ${if frontendWasm != null then ''
109+ ln -s ${stripWasm frontendWasm}/* .
110+ ln -s ${webabi}/lib/node_modules/webabi/jsaddleJS/* .
111+ ln -s ${webabi}/lib/node_modules/webabi/build/mainthread_runner.js .
112+ '' else '' ''}
113+ '';
88
114
89 serverModules = {
115 serverModules = {
90 mkBaseEc2 = { nixosPkgs, ... }: {...}: {
116 mkBaseEc2 = { nixosPkgs, ... }: {...}: {
@@ -167,13 +193,13 @@ in rec {
167
193
168 inherit mkAssets;
194 inherit mkAssets;
169
195
170− serverExe = backend: frontend: assets: optimizationLevel: version:
196+ serverExe = backend: frontendJs: assets: optimizationLevel: frontendWasm: version:
171 pkgs.runCommand "serverExe" {} ''
197 pkgs.runCommand "serverExe" {} ''
172 mkdir $out
198 mkdir $out
173 set -eux
199 set -eux
174 ln -s "${if profiling then backend else haskellLib.justStaticExecutables backend}"/bin/* $out/
200 ln -s "${if profiling then backend else haskellLib.justStaticExecutables backend}"/bin/* $out/
175 ln -s "${mkAssets assets}" $out/static.assets
201 ln -s "${mkAssets assets}" $out/static.assets
176− ln -s ${mkAssets (compressedJs frontend optimizationLevel)} $out/frontend.jsexe.assets
202+ ln -s ${mkAssets (combinedJsWasmAssets frontendJs optimizationLevel frontendWasm)} $out/frontend.jsexe.assets
177 echo ${version} > $out/version
203 echo ${version} > $out/version
178 '';
204 '';
179
205
@@ -280,6 +306,7 @@ in rec {
280 lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghcSavedSplices;
306 lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghcSavedSplices;
281 ghc = lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghc;
307 ghc = lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghc;
282 ghcjs = lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghcjs;
308 ghcjs = lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghcjs;
309+ wasm = lib.filter (x: lib.hasAttr x self.combinedPackages) self.shells-ghcjs;
283 };
310 };
284 android = self.__androidWithConfig (self.base + "/config");
311 android = self.__androidWithConfig (self.base + "/config");
285 ios = self.__iosWithConfig (self.base + "/config");
312 ios = self.__iosWithConfig (self.base + "/config");
@@ -305,6 +332,7 @@ in rec {
305 mainProjectOut.ghcjs.frontend
332 mainProjectOut.ghcjs.frontend
306 projectInst.passthru.staticFiles
333 projectInst.passthru.staticFiles
307 projectInst.passthru.__closureCompilerOptimizationLevel
334 projectInst.passthru.__closureCompilerOptimizationLevel
335+ (if enableWasm then mainProjectOut.wasm.frontend else null)
308 version;
336 version;
309 linuxExe = serverOn (projectOut { system = "x86_64-linux"; });
337 linuxExe = serverOn (projectOut { system = "x86_64-linux"; });
310 dummyVersion = "Version number is only available for deployments";
338 dummyVersion = "Version number is only available for deployments";
dep/reflex-platform/github.json+5−5
@@ -1,8 +1,8 @@
1{
1{
2− "owner": "reflex-frp",
2+ "owner": "dfordivam",
3 "repo": "reflex-platform",
3 "repo": "reflex-platform",
4− "branch": "master",
4+ "branch": "ob-1",
5 "private": false,
5 "private": false,
6− "rev": "41be4d952b75515a037318aa344dd6b13ad29cfe",
6+ "rev": "2ab56c00a3d1b5f0c026fa8b339968fab66bdcc3",
7− "sha256": "132yqzyzd3c5fjy7wwnwa5d6pjxv5ap2xz0swwbv3h5pwi8jwv0a"
7+ "sha256": "05ilpykbp6ipzfack54zjkc9dvfdvl134vx2k36d0gvb0nswmlcm"
8−}
8+}
dep/webabi/default.nixnew file+7
@@ -0,0 +1,7 @@
1+# DO NOT HAND-EDIT THIS FILE
2+import ((import <nixpkgs> {}).fetchFromGitHub (
3+ let json = builtins.fromJSON (builtins.readFile ./github.json);
4+ in { inherit (json) owner repo rev sha256;
5+ private = json.private or false;
6+ }
7+))
dep/webabi/github.jsonnew file+6
@@ -0,0 +1,6 @@
1+{
2+ "owner": "WebGHC",
3+ "repo": "webabi",
4+ "rev": "666af48756dc9f49f0320d56731ef355534292c2",
5+ "sha256": "1brs0b0ybfaa0fcw4cbb7vmbpf7x48niv5y5hskvk6s9zgj1yp5j"
6+}
lib/backend/obelisk-backend.cabal+1
@@ -13,6 +13,7 @@ library
13 data-default,
13 data-default,
14 dependent-sum,
14 dependent-sum,
15 dependent-sum-template,
15 dependent-sum-template,
16+ filepath,
16 lens,
17 lens,
17 mtl,
18 mtl,
18 obelisk-asset-serve-snap,
19 obelisk-asset-serve-snap,
lib/backend/src/Obelisk/Backend.hs+86−10
@@ -20,6 +20,7 @@ module Obelisk.Backend
20 , runBackendWith
20 , runBackendWith
21 -- * Configuration of backend
21 -- * Configuration of backend
22 , GhcjsWidgets(..)
22 , GhcjsWidgets(..)
23+ , GhcjsWasmAssets(..)
23 , defaultGhcjsWidgets
24 , defaultGhcjsWidgets
24 -- * all.js script loading functions
25 -- * all.js script loading functions
25 , deferredGhcjsScript
26 , deferredGhcjsScript
@@ -39,6 +40,7 @@ module Obelisk.Backend
39 , getPublicConfigs
40 , getPublicConfigs
40 ) where
41 ) where
41
42
43+import Control.Exception (try)
42import Control.Monad
44import Control.Monad
43import Control.Monad.Except
45import Control.Monad.Except
44import Control.Monad.Fail (MonadFail)
46import Control.Monad.Fail (MonadFail)
@@ -46,6 +48,7 @@ import Data.ByteString (ByteString)
46import qualified Data.ByteString.Char8 as BSC8
48import qualified Data.ByteString.Char8 as BSC8
47import Data.Default (Default (..))
49import Data.Default (Default (..))
48import Data.Dependent.Sum
50import Data.Dependent.Sum
51+import Data.Either (isRight)
49import Data.Functor.Identity
52import Data.Functor.Identity
50import Data.Map (Map)
53import Data.Map (Map)
51import qualified Data.Map as Map
54import qualified Data.Map as Map
@@ -63,6 +66,7 @@ import Snap (MonadSnap, Snap, commandLineConfig, defaultConfig, getsRequest, htt
63 , rqPathInfo, rqQueryString, setContentType, writeBS, writeText
66 , rqPathInfo, rqQueryString, setContentType, writeBS, writeText
64 , rqCookies, Cookie(..) , setHeader)
67 , rqCookies, Cookie(..) , setHeader)
65import Snap.Internal.Http.Server.Config (Config (accessLog, errorLog), ConfigLog (ConfigIoLog))
68import Snap.Internal.Http.Server.Config (Config (accessLog, errorLog), ConfigLog (ConfigIoLog))
69+import System.FilePath ((</>))
66import System.IO (BufferMode (..), hSetBuffering, stderr, stdout)
70import System.IO (BufferMode (..), hSetBuffering, stderr, stdout)
67
71
68data Backend backendRoute frontendRoute = Backend
72data Backend backendRoute frontendRoute = Backend
@@ -73,8 +77,9 @@ data Backend backendRoute frontendRoute = Backend
73data BackendConfig frontendRoute = BackendConfig
77data BackendConfig frontendRoute = BackendConfig
74 { _backendConfig_runSnap :: !(Snap () -> IO ()) -- ^ Function to run the snap server
78 { _backendConfig_runSnap :: !(Snap () -> IO ()) -- ^ Function to run the snap server
75 , _backendConfig_staticAssets :: !StaticAssets -- ^ Static assets
79 , _backendConfig_staticAssets :: !StaticAssets -- ^ Static assets
80+ , _backendConfig_ghcjsAssets :: !StaticAssets -- ^ Frontend ghcjs (and wasm) assets
76− , _backendConfig_ghcjsWidgets :: !(GhcjsWidgets (Text -> FrontendWidgetT (R frontendRoute) ()))
81+ , _backendConfig_ghcjsWidgets :: !(GhcjsWidgets (GhcjsWasmAssets -> FrontendWidgetT (R frontendRoute) ()))
77− -- ^ Given the URL of all.js, return the widgets which are responsible for
82+ -- ^ Given the URL of all.js and wasm files, return the widgets which are responsible for
78 -- loading the script.
83 -- loading the script.
79 } deriving (Generic)
84 } deriving (Generic)
80
85
@@ -92,10 +97,14 @@ data GhcjsWidgets a = GhcjsWidgets
92 -- ^ A script widget, placed in the document body
97 -- ^ A script widget, placed in the document body
93 } deriving (Functor, Generic)
98 } deriving (Functor, Generic)
94
99
100+data GhcjsWasmAssets = GhcjsWasmAssets
101+ { _ghcjsWasmAssets_allJs :: Text
102+ , _ghcjsWasmAssets_wasmPathRoot :: Maybe Text
103+ }
95
104
96-- | Given the URL of all.js, return the widgets which are responsible for
105-- | Given the URL of all.js, return the widgets which are responsible for
97-- loading the script. Defaults to 'preloadGhcjs' and 'deferredGhcjsScript'.
106-- loading the script. Defaults to 'preloadGhcjs' and 'deferredGhcjsScript'.
98−defaultGhcjsWidgets :: GhcjsWidgets (Text -> FrontendWidgetT r ())
107+defaultGhcjsWidgets :: GhcjsWidgets (GhcjsWasmAssets -> FrontendWidgetT r ())
99defaultGhcjsWidgets = GhcjsWidgets
108defaultGhcjsWidgets = GhcjsWidgets
100 { _ghcjsWidgets_preload = preloadGhcjs
109 { _ghcjsWidgets_preload = preloadGhcjs
101 , _ghcjsWidgets_script = deferredGhcjsScript
110 , _ghcjsWidgets_script = deferredGhcjsScript
@@ -132,6 +141,9 @@ defaultStaticAssets = StaticAssets
132 , _staticAssets_unprocessed = "static"
141 , _staticAssets_unprocessed = "static"
133 }
142 }
134
143
144+-- This has both ghcjs and wasm assets.
145+-- The 'unprocessed' is a fallback path, and in case of wasm is invalid (does not contain wasm files)
146+-- For the standard obelisk deployment the unprocessed path would not be used.
135defaultFrontendGhcjsAssets :: StaticAssets
147defaultFrontendGhcjsAssets :: StaticAssets
136defaultFrontendGhcjsAssets = StaticAssets
148defaultFrontendGhcjsAssets = StaticAssets
137 { _staticAssets_processed = "frontend.jsexe.assets"
149 { _staticAssets_processed = "frontend.jsexe.assets"
@@ -167,6 +179,10 @@ renderAllJsPath :: Encoder Identity Identity (R (FullRoute a b)) PageName -> Tex
167renderAllJsPath validFullEncoder =
179renderAllJsPath validFullEncoder =
168 renderObeliskRoute validFullEncoder $ FullRoute_Frontend (ObeliskRoute_Resource ResourceRoute_Ghcjs) :/ ["all.js"]
180 renderObeliskRoute validFullEncoder $ FullRoute_Frontend (ObeliskRoute_Resource ResourceRoute_Ghcjs) :/ ["all.js"]
169
181
182+renderWasmPathRoot :: Encoder Identity Identity (R (FullRoute a b)) PageName -> Text
183+renderWasmPathRoot validFullEncoder =
184+ renderObeliskRoute validFullEncoder $ FullRoute_Frontend (ObeliskRoute_Resource ResourceRoute_Ghcjs) :/ []
185+
170serveObeliskApp
186serveObeliskApp
171 :: (MonadSnap m, HasCookies m, MonadFail m)
187 :: (MonadSnap m, HasCookies m, MonadFail m)
172 => (R appRoute -> Text)
188 => (R appRoute -> Text)
@@ -221,7 +237,7 @@ serveGhcjsApp urlEnc ghcjsWidgets app config = \case
221
237
222-- | Default obelisk backend configuration.
238-- | Default obelisk backend configuration.
223defaultBackendConfig :: BackendConfig frontendRoute
239defaultBackendConfig :: BackendConfig frontendRoute
224−defaultBackendConfig = BackendConfig runSnapWithCommandLineArgs defaultStaticAssets defaultGhcjsWidgets
240+defaultBackendConfig = BackendConfig runSnapWithCommandLineArgs defaultStaticAssets defaultFrontendGhcjsAssets defaultGhcjsWidgets
225
241
226-- | Run an obelisk backend with the default configuration.
242-- | Run an obelisk backend with the default configuration.
227runBackend :: Backend backendRoute frontendRoute -> Frontend (R frontendRoute) -> IO ()
243runBackend :: Backend backendRoute frontendRoute -> Frontend (R frontendRoute) -> IO ()
@@ -233,21 +249,34 @@ runBackendWith
233 -> Backend backendRoute frontendRoute
249 -> Backend backendRoute frontendRoute
234 -> Frontend (R frontendRoute)
250 -> Frontend (R frontendRoute)
235 -> IO ()
251 -> IO ()
236−runBackendWith (BackendConfig runSnap staticAssets ghcjsWidgets) backend frontend = case checkEncoder $ _backend_routeEncoder backend of
252+runBackendWith (BackendConfig runSnap staticAssets ghcjsAssets ghcjsWidgets) backend frontend = case checkEncoder $ _backend_routeEncoder backend of
237 Left e -> fail $ "backend error:\n" <> T.unpack e
253 Left e -> fail $ "backend error:\n" <> T.unpack e
238 Right validFullEncoder -> do
254 Right validFullEncoder -> do
239 publicConfigs <- getPublicConfigs
255 publicConfigs <- getPublicConfigs
256+ enableWasm <- checkWasmFile
240 _backend_run backend $ \serveRoute ->
257 _backend_run backend $ \serveRoute ->
241 runSnap $
258 runSnap $
242 getRouteWith validFullEncoder >>= \case
259 getRouteWith validFullEncoder >>= \case
243 Identity r -> case r of
260 Identity r -> case r of
244 FullRoute_Backend backendRoute :/ a -> serveRoute $ backendRoute :/ a
261 FullRoute_Backend backendRoute :/ a -> serveRoute $ backendRoute :/ a
245 FullRoute_Frontend obeliskRoute :/ a ->
262 FullRoute_Frontend obeliskRoute :/ a ->
246− serveDefaultObeliskApp routeToUrl (($ allJsUrl) <$> ghcjsWidgets) (serveStaticAssets staticAssets) frontend publicConfigs $
263+ serveObeliskApp routeToUrl widgets (serveStaticAssets staticAssets) frontendApp publicConfigs $
247 obeliskRoute :/ a
264 obeliskRoute :/ a
248 where
265 where
249 routeToUrl (k :/ v) = renderObeliskRoute validFullEncoder $ FullRoute_Frontend (ObeliskRoute_App k) :/ v
266 routeToUrl (k :/ v) = renderObeliskRoute validFullEncoder $ FullRoute_Frontend (ObeliskRoute_App k) :/ v
250 allJsUrl = renderAllJsPath validFullEncoder
267 allJsUrl = renderAllJsPath validFullEncoder
268+ mWasmUrls = if enableWasm then Just (renderWasmPathRoot validFullEncoder) else Nothing
269+ widgets = ($ GhcjsWasmAssets allJsUrl mWasmUrls) <$> ghcjsWidgets
270+ frontendApp = GhcjsApp
271+ { _ghcjsApp_compiled = ghcjsAssets
272+ , _ghcjsApp_value = frontend
273+ }
274+ where
275+ checkWasmFile = do
276+ let base = _staticAssets_processed ghcjsAssets
277+ p = "frontend.wasm"
278+ assetType :: (Either IOError ByteString) <- liftIO $ try $ BSC8.readFile $ base </> p </> "type"
279+ pure $ isRight assetType
251
280
252renderGhcjsFrontend
281renderGhcjsFrontend
253 :: (MonadSnap m, HasCookies m)
282 :: (MonadSnap m, HasCookies m)
@@ -263,13 +292,60 @@ renderGhcjsFrontend urlEnc ghcjsWidgets route configs f = do
263
292
264-- | Preload all.js in a link tag.
293-- | Preload all.js in a link tag.
265-- This is the default preload method.
294-- This is the default preload method.
266−preloadGhcjs :: Text -> FrontendWidgetT r ()
295+preloadGhcjs :: GhcjsWasmAssets -> FrontendWidgetT r ()
296+preloadGhcjs (GhcjsWasmAssets allJsUrl mWasm) = case mWasm of
267−preloadGhcjs allJsUrl = elAttr "link" ("rel" =: "preload" <> "as" =: "script" <> "href" =: allJsUrl) blank
297+ Nothing -> elAttr "link" ("rel" =: "preload" <> "as" =: "script" <> "href" =: allJsUrl) blank
298+ Just wasmAssets -> fst (wasmScripts allJsUrl wasmAssets)
268
299
269-- | Load the script from the given URL in a deferred script tag.
300-- | Load the script from the given URL in a deferred script tag.
270-- This is the default method.
301-- This is the default method.
271−deferredGhcjsScript :: Text -> FrontendWidgetT r ()
302+deferredGhcjsScript :: GhcjsWasmAssets -> FrontendWidgetT r ()
303+deferredGhcjsScript (GhcjsWasmAssets allJsUrl mWasm) = case mWasm of
272−deferredGhcjsScript allJsUrl = elAttr "script" ("type" =: "text/javascript" <> "src" =: allJsUrl <> "defer" =: "defer") blank
304+ Nothing -> elAttr "script" ("type" =: "text/javascript" <> "src" =: allJsUrl <> "defer" =: "defer") blank
305+ Just wasmAssets -> snd (wasmScripts allJsUrl wasmAssets)
306+
307+wasmScripts :: Text -> Text -> (FrontendWidgetT r (), FrontendWidgetT r ())
308+wasmScripts allJsUrl wasmRoot = (script preloadScript, script runJsScript)
309+ where
310+ script t = elAttr "script" ("type" =: "text/javascript") $ text t
311+ jsaddleJs = wasmRoot <> "/jsaddle_core.js"
312+ interfaceJs = wasmRoot <> "/jsaddle_mainthread_interface.js"
313+ runnerJs = wasmRoot <> "/mainthread_runner.js"
314+ wasmUrl = wasmRoot <> "/frontend.wasm"
315+
316+ preloadScript =
317+ "add_preload_tag = function (docSrc, docType) { \
318+ \ var link_tag = document.createElement('link'); \
319+ \ link_tag.rel = 'preload'; \
320+ \ link_tag.as = docType; \
321+ \ link_tag.href = docSrc; \
322+ \ document.head.appendChild(link_tag); \
323+ \}; \
324+ \if (typeof(WebAssembly) === 'undefined') { \
325+ \ add_preload_tag('" <> allJsUrl <> "', 'script'); \
326+ \} else { \
327+ \ add_preload_tag('" <> wasmUrl <> "', 'script'); \
328+ \ add_preload_tag('" <> jsaddleJs <> "', 'script'); \
329+ \ add_preload_tag('" <> interfaceJs <> "', 'script'); \
330+ \ add_preload_tag('" <> runnerJs <> "', 'script'); \
331+ \}"
332+
333+ runJsScript =
334+ "add_deferload_tag = function (docSrc) { \
335+ \ var tag = document.createElement('script'); \
336+ \ tag.type = 'text/javascript'; \
337+ \ tag.src = docSrc; \
338+ \ tag.setAttribute = ('defer', 'defer'); \
339+ \ document.body.appendChild(tag); \
340+ \}; \
341+ \if (typeof(WebAssembly) === 'undefined') { \
342+ \ add_deferload_tag('" <> allJsUrl <> "'); \
343+ \} else { \
344+ \ var wasmFile = '" <> wasmUrl <> "'; \
345+ \ add_deferload_tag('" <> jsaddleJs <> "'); \
346+ \ add_deferload_tag('" <> interfaceJs <> "'); \
347+ \ add_deferload_tag('" <> runnerJs <> "'); \
348+ \}"
273
349
274-- | An all.js script which is loaded after waiting for some time to pass. This
350-- | An all.js script which is loaded after waiting for some time to pass. This
275-- is useful to ensure any CSS animations on the page can play smoothly before
351-- is useful to ensure any CSS animations on the page can play smoothly before
lib/executable-config/lookup/obelisk-executable-config-lookup.cabal+1−1
@@ -18,7 +18,7 @@ library
18 build-depends: android-activity
18 build-depends: android-activity
19 ld-options: -landroid
19 ld-options: -landroid
20 else
20 else
21− if impl(ghcjs)
21+ if impl(ghcjs) || arch(wasm32)
22 hs-source-dirs: src-ghcjs, src
22 hs-source-dirs: src-ghcjs, src
23 build-depends: ghcjs-dom
23 build-depends: ghcjs-dom
24 else
24 else
lib/executable-config/lookup/src-ghcjs/Obelisk/ExecutableConfig/Lookup.hs+4−2
@@ -2,11 +2,13 @@
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Obelisk.ExecutableConfig.Lookup where
3module Obelisk.ExecutableConfig.Lookup where
4
4
5+import Control.Monad.IO.Class
6+import Control.Monad.Fail (MonadFail)
5import Data.ByteString (ByteString)
7import Data.ByteString (ByteString)
6import qualified Data.ByteString.Base64 as B64
8import qualified Data.ByteString.Base64 as B64
7import Data.Map (Map)
9import Data.Map (Map)
8import qualified Data.Map as Map
10import qualified Data.Map as Map
9−import Data.Maybe (catMaybes)
11+import Data.Maybe (catMaybes, isJust)
10import Data.Text (Text)
12import Data.Text (Text)
11import qualified Data.Text.Encoding as T
13import qualified Data.Text.Encoding as T
12import Data.Traversable (for)
14import Data.Traversable (for)
@@ -19,7 +21,7 @@ import GHCJS.DOM.NodeList (IsNodeList, item, getLength)
19import GHCJS.DOM.ParentNode (querySelectorAll)
21import GHCJS.DOM.ParentNode (querySelectorAll)
20import GHCJS.DOM.Types (MonadJSM, Node(Node), castTo)
22import GHCJS.DOM.Types (MonadJSM, Node(Node), castTo)
21
23
22−getConfigs :: IO (Map Text ByteString)
24+getConfigs :: (MonadJSM m, MonadFail m) => m (Map Text ByteString)
23getConfigs = do
25getConfigs = do
24 Just doc <- currentDocument
26 Just doc <- currentDocument
25 Just hd <- getHead doc
27 Just hd <- getHead doc
lib/frontend/src/Obelisk/Frontend.hs+11−12
@@ -151,21 +151,20 @@ runFrontend
151 -> Frontend (R route)
151 -> Frontend (R route)
152 -> JSM ()
152 -> JSM ()
153runFrontend validFullEncoder frontend = do
153runFrontend validFullEncoder frontend = do
154+#if defined(ghcjs_HOST_OS) || defined(wasm32_HOST_ARCH)
154 let mode = FrontendMode
155 let mode = FrontendMode
155− { _frontendMode_hydrate =
156+ { _frontendMode_hydrate = True
156−#ifdef ghcjs_HOST_OS
157− True
158−#else
159− False
160−#endif
161− , _frontendMode_adjustRoute =
157+ , _frontendMode_adjustRoute = False
162−#ifdef ghcjs_HOST_OS
158+ }
163− False
159+ doLift = Prelude.id
164#else
160#else
165− True
161+ let mode = FrontendMode
166−#endif
162+ { _frontendMode_hydrate = False
163+ , _frontendMode_adjustRoute = True
167 }
164 }
165+ doLift = liftIO
166+#endif
168− configs <- liftIO Lookup.getConfigs
167+ configs <- doLift Lookup.getConfigs
169 when (_frontendMode_hydrate mode) removeHTMLConfigs
168 when (_frontendMode_hydrate mode) removeHTMLConfigs
170 -- There's no fundamental reason that adjustRoute needs to control setting the
169 -- There's no fundamental reason that adjustRoute needs to control setting the
171 -- initial route and *also* the useHash parameter; that's why these are
170 -- initial route and *also* the useHash parameter; that's why these are
lib/run/src/Obelisk/Run.hs+2−1
@@ -97,9 +97,10 @@ run port serveStaticAsset backend frontend = do
97 Identity r -> case r of
97 Identity r -> case r of
98 FullRoute_Backend backendRoute :/ a -> serveRoute $ backendRoute :/ a
98 FullRoute_Backend backendRoute :/ a -> serveRoute $ backendRoute :/ a
99 FullRoute_Frontend obeliskRoute :/ a ->
99 FullRoute_Frontend obeliskRoute :/ a ->
100− serveDefaultObeliskApp appRouteToUrl (($ allJsUrl) <$> defaultGhcjsWidgets) serveStaticAsset frontend publicConfigs $ obeliskRoute :/ a
100+ serveDefaultObeliskApp appRouteToUrl (($ assetsUrl) <$> defaultGhcjsWidgets) serveStaticAsset frontend publicConfigs $ obeliskRoute :/ a
101 where
101 where
102 appRouteToUrl (k :/ v) = renderObeliskRoute validFullEncoder (FullRoute_Frontend (ObeliskRoute_App k) :/ v)
102 appRouteToUrl (k :/ v) = renderObeliskRoute validFullEncoder (FullRoute_Frontend (ObeliskRoute_App k) :/ v)
103+ assetsUrl = GhcjsWasmAssets allJsUrl Nothing
103 allJsUrl = renderAllJsPath validFullEncoder
104 allJsUrl = renderAllJsPath validFullEncoder
104
105
105 let conf = defRunConfig { _runConfig_redirectPort = port }
106 let conf = defRunConfig { _runConfig_redirectPort = port }
skeleton/frontend/frontend.cabal+2−1
@@ -29,6 +29,7 @@ executable frontend
29 , obelisk-generated-static
29 , obelisk-generated-static
30 , frontend
30 , frontend
31 --TODO: Make these ghc-options optional
31 --TODO: Make these ghc-options optional
32+ if !arch(wasm32)
32− ghc-options: -threaded
33+ ghc-options: -threaded
33 if os(darwin)
34 if os(darwin)
34 ghc-options: -dynamic
35 ghc-options: -dynamic