Embedding
Instead of always shipping the frontend files alongside your binary it is also possible to embed all the web-content into your saucer application. The easiest way to accomplish this is to use the saucer-cli.
Pre-Requisites
- A built version of your website (that should consist of
.html
,.js
, ... files)
Automated Embedding
Recommended Usage
We recommend to use the saucer-cli within your package.json
build script.
Simply add @saucer-dev/cli
as a dependency (i.e. pnpm install @saucer-dev/cli
) and then conduct the following changes:
{
// ...
"scripts": {
"build": "<deploy normally> && saucer embed <output-folder>"
}
// ...
}
CLI Usage
As we've seen above, the CLI simply consumes a given folder and produces C++ headers which handle the embedding.
You can also install the CLI globally.
This can be achieved by installing it as a global npm package: npm i -g @saucer-dev/cli
.
If you now want to embed some specific files simply place them into a single directory ("out" in the example below).
out
├── 404.html
├── icon.webp
├── index.html
├── logos
└── _next
├── data
│ └── I0JjY_SsFNIFkY51LHHZ8
│ └── index.json
├── I0JjY_SsFNIFkY51LHHZ8
└── static
├── chunks
│ ├── 617-62e76ca49feff4cf.js
│ ├── ef6529d7-eceeabab9e91fbfa.js
│ ├── framework-4556c45dd113b893.js
│ ├── main-8622cd0e77d03013.js
│ ├── pages
│ │ ├── _app-21ef9ef16725f9ba.js
│ │ ├── _error-a4ba2246ff8fb532.js
│ │ └── index-5206a6595f9ffd08.js
│ ├── polyfills-0d1b80a048d4787e.js
│ └── webpack-c491b2a411a4f8fa.js
└── I0JjY_SsFNIFkY51LHHZ8
├── _buildManifest.js
└── _ssgManifest.js
And then use the saucer-cli
to generate the required embedding files.
saucer embed <source> [<destination>]
saucer embed "out"
Using the Embedding Files
After running the embed command through the cli, a folder named "embedded"
- unless otherwise specified - will be generated.
Now simply consume this folder as a include directory.
target_include_directories(${PROJECT_NAME} PRIVATE "path/to/generated/folder")
Now it's only a matter of including the header in your code and calling embed
on the webview.
To serve the files simply call serve
and specify the file name.
#include <saucer/smartview.hpp>
#include <output_folder/all.hpp>
int main()
{
auto app = saucer::application::acquire({
.id = "embedding",
});
saucer::smartview smartview{{
.application = app,
}};
smartview.set_title("Hello World!");
smartview.expose("add_ten", [](int i)
{
return i + 10;
});
smartview.set_url("https://google.com");
smartview.embed(saucer::embedded::all());
smartview.serve("index.html");
smartview.show();
app->run();
return 0;
}
Manual Embedding
The CLI tool seen above will include all embedded files verbatim into your binary.
If you wish to have more control over how embedded files are loaded you can do so by manually creating the saucer::embedded_file
s.
The example below demonstrates how to embed a file that will load the given resource from a server lazily.
#include <saucer/smartview.hpp>
#include <cpr/cpr.h>
int main()
{
auto app = saucer::application::acquire({
.id = "embedding",
});
saucer::smartview smartview{{
.application = app,
}};
smartview.embed({{"index.html", saucer::embedded_file{
.content = saucer::stash<>::lazy(
[]()
{
auto req = cpr::Get(cpr::Url{"..."});
return saucer::make_stash(req.text);
}),
.mime = "text/html",
}}});
smartview.serve("index.html");
smartview.show();
app->run();
return 0;
}
Once the webview requests to load the index.html
the given GET request will be started.
Subsequent requests to load the index.html
will re-use the initial result. For more information on saucer::stash
see custom schemes.
Calling webview::embed
multiple times will merge the given files with the already embedded ones. Thus you can safely use the CLI-approach and lazy load only some files.