How to host Static Assets on Darklang
Darklang supports hosting your static assets.
Our static assets service is designed to be simple, easy to understand, as well as composable and configurable. As such, a static assets deploy uploads your assets to our cloud CDN, and we provide powerful tools in Darklang to serve and configure them.
A GitHub Action to automate this process is now available thanks to one of our fantastic community members, Greg Brimble!
Simple Use Case
Note: You can see the finished product at https://darklang.com/a/sample-static-assets
We have a single page app, written in react. It talks to our API, written in Darklang. Now we’d like to deploy that app so that customers can use it too. This also works in a similar way for Vue applications, with a few caveats called out in line.
Here’s how we want our app to work:
- we have an API, served from
/api/
/
serves ourindex.html
page from our assetsindex.html
should point to our static assets host to fetch other assets
We’ll focus on the last two things we want our app to do in this document.
At a high level, here are the steps:
- deploy the assets using the dark-cli app
- load the index page
- configure your react app
Deploying Assets
We have a command-line app to allow you to deploy your assets.
Installation
-
Go to https://dark-cli.storage.googleapis.com/index.html, and download the appropriate binary for macOS, Windows, or Linux.
-
On macOS or Linux,
chmod +x dark-cli-apple
or
chmod +x dark-cli-linux
to make it executable.
-
To confirm it works, run it with
-—help
:macOS:
./dark-cli-apple --help
Linux:
./dark-cli-linux --help
Windows:
./dark-cli.exe --help
-
On some versions of macOS, you may get one of the the following popups:
to resolve this, press
Ok
orCancel
and openSystem Preferences -> Security & Privacy -> General
.Press
Allow Anyway
and repeat step 3.
Configure your client
At the moment, our CDN does not support the use of absolute URLs in the
generated files. For example, if your CSS file links an image at
/static/myimage.png
, that file will not load. You need to use relative URLs
instead, in this case ./myimage.png
.
Your index.html
likely loads other assets, such as app.css
or app.js
. For
speed, you will load these directly from the Darklang CDN, not via your Darklang
handler. As such, we’ll need to make some edits to your assets to ensure they’re
always pointing at the CDN for other assets.
During the deployment of the assets, our backend replaces the string
DARK_STATIC_ASSETS_BASE_URL
in all of your assets with the actual URL of this
deployment.
When not using a framework, prefix asset paths with Darklang's magic string, for example:
<img src="DARK_STATIC_ASSETS_BASE_URL/logo.svg" />
In React, when compiling your react application, you can use PUBLIC_URL
:
PUBLIC_URL=DARK_STATIC_ASSETS_BASE_URL npm run build
If using Angular, you can run the following command:
ng build --prod --deploy-url DARK_STATIC_ASSETS_BASE_URL/
If using Vue, you likely want to set PUBLIC_PATH
instead:
PUBLIC_PATH=DARK_STATIC_ASSETS_BASE_URL
Additionally, Vue assumes relative paths. If you are having an issue with your
assets, check to make sure that index.html
has not added leading path notation
(/PUBLIC_PATH
). If it has, you can manually remove and redeploy. More on using
this for Vue here:
Deploy
-
To deploy, select the directory you want to upload. In this case, we’ll use React’s default directory
build
. -
Run:
# The single quotes - around mypass help protect against shell escaping and interpolation.
# If your password contains a single quote or a backslash don't forget to escape it with a \
./dark-cli-apple --canvas myusername-mycanvas --password 'mypass' --user myusername build
(If you want to avoid shell escaping issues entirely, we also support putting
your creds in ~/.netrc
; the format for that is documented at
https://ec.haxx.se/usingcurl/usingcurl-netrc
for machine darklang.com
).
On success, we’ll show you the deploy hash, a URL, and a long URL. These are where your static assets now live! You can see your static assets in the Routing table in your canvas:
Set up your App to Load your Assets
If your SPA framework generates an index.html
, or you write one yourself, you
can load that for the /
route in Darklang.
- Add a handler for
/
to load yourindex.html
page usingStaticAssets::serveLatest "index.html"
. - If you’re using client-side routing, you can also add a handler serving
index.html
for/:rest
which will be a catch-all handler for any URL (besides/
) that doesn’t have another handler defined for it. This will allow your users to load your assets from any of your app’s URLs.
You can copy and paste this example from https://darklang.com/a/sample-static-assets.
Implementing a Fallback in the Case of a 404
If you’re looking to serve a fallback asset, you can use a match statement:
Advanced: Feature Flags and Continuous Delivery
We’ve shown you how to deploy new assets that appear immediately. However, you often want to control the rollout of those assets, perhaps seeing them yourself, or only showing them to users who have opted into beta features. As a result, it is easy to use Darklang Static Assets with feature flags.
Instead of calling HttpClient::serveLatest
, you can call HttpClient::serve
,
and use the deploy hash from your command line.
Reference
Functions
urlFor <deployHash : String> <file : String> -> String
- Returns a URL to a file for the current canvas and the given
deployHash
: StaticAssets::urlFor "o6vs1aqcbx" "foo.html"
->"https://ismith-staticassets.darksa.com/stgbcg3kez_zb9-wlbtgta563t8/o6vs1aqcbx/foo.html"
- Returns a URL to a file for the current canvas and the given
urlForLatest <file : String> -> String
- Returns a URL to a file for the current canvas and the latest deploy:
StaticAssets::urlForLatest "foo.html"
->"https://ismith-staticassets.darksa.com/stgbcg3kez_zb9-wlbtgta563t8/o6vs1aqcbx/foo.html"
fetch <deployHash : String> <file : String> -> String
- Returns the contents of a file for the current canvas and the given
deployHash
: StaticAssets::fetch "o6vs1aqcbx" "foo.html"
->"<html><body>Hello, world!</body></html>"
- Returns the contents of a file for the current canvas and the given
fetchLatest <file : String> -> String
- Returns a URL to a file for the current canvas and the latest deploy:
StaticAssets::fetchLatest "foo.html"
->"<html><body>Hello, world!</body></html>"
serve <deployHash : String> <file : String> -> String
- Returns the contents of a file for the current canvas and the given
deployHash
: StaticAssets::serve "o6vs1aqcbx" "foo.html"
-> responds with the filefoo.html
and the headers that the static assets CDN provided
- Returns the contents of a file for the current canvas and the given
serveLatest <file : String> -> String
- Returns a URL to a file for the current canvas and the latest deploy:
StaticAssets::serveLatest "foo.html"
-> responds with the filefoo.html
and the headers that the static assets CDN provided
Command line reference
./dark-cli-apple
error: The following required arguments were not provided:
<paths>
--canvas <canvas>
--password <password>
--user <user>
USAGE:
dark-cli-apple [FLAGS] <paths> --canvas <canvas> --password <password> --user <user>