Expand description
§actix-web static files as resources support
§Legal
Dual-licensed under MIT or the Unlicense.
§Features
- Embed static resources in single self-contained executable
- Serve static resources in
actix-web - Install dependencies with npm package manager
- Run custom
npmrun commands (such as webpack) - Support for npm-like package managers (yarn)
- Support for angular-like routers
§Compatibility notes
actix-web-static-filesis compatible withactix-webversion4.x.y.static-fileswith version0.2.xis default.static-fileswith version0.3.xis recommended for new projects or when you want to use the latest features and improvements. It is enabled with featurestatic-files-03. Examples also referencestatic-fileswith version0.3.x.
§Usage
§Use-case 1: Static resources folder
Create folder with static resources in your project (for example static):
cd project_dir
mkdir static
echo "<p>Hello, world\!</p>" > static/index.htmlAdd to Cargo.toml dependencies related to actix-web-static-files:
[dependencies]
actix-web = "4"
actix-web-static-files = { version = "4.1", features = ["static-files-03"] }
static-files = "0.3.1"
[build-dependencies]
static-files = "0.3.1"
[dev-dependencies]
reqwest.workspace = true
assert_cmd.workspace = trueAdd build.rs with call to bundle resources:
use static_files::resource_dir;
fn main() -> std::io::Result<()> {
resource_dir("./static").build()
}Include generated code in src/main.rs:
use actix_web::{App, HttpServer};
use actix_web_static_files::ResourceFiles;
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let listen = std::env::var("LISTEN").unwrap_or_else(|_| "127.0.0.1:8081".into());
let server = HttpServer::new(|| {
let generated = generate();
App::new().service(ResourceFiles::new("/", generated))
})
.bind(listen)?;
if let Some(addr) = server.addrs().first() {
println!("{:05}", addr.port());
}
let handle = actix_web::rt::spawn(server.run());
handle.await?
}Run the server:
cargo runRequest the resource:
$ curl -v http://localhost:8080/
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8080 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
>
< HTTP/1.1 200 OK
< content-length: 20
< content-type: text/html
< etag: "14:606a2226"
< date: Sun, 23 May 2021 19:46:42 GMT
<
* Connection #0 to host localhost left intact
<p>Hello, world!</p>* Closing connection 0See also:
- Static resources folder with index.html example
- Another example with same resources but using own defined function
§Use-case 2: package.json - npm managed folder
Create folder with static resources in your project (for example static):
cd project_dir
mkdir static_packages
cd static_packages
echo '{}' > package.json
# install your npm dependencies (here we use fontawesome as an example)
npm install --save-dev @fortawesome/fontawesome-freeAdd generated folder to ignore file of your version control system (here: git):
cd project_dir
echo "static_packages/node_modules" >> .gitignoreAdd dependencies and build-dependencies in Cargo.toml same way as in the first use-case.
Add build.rs with call to bundle resources:
use static_files::npm_resource_dir;
fn main() -> std::io::Result<()> {
npm_resource_dir("./static_packages")?.build()
}Include generated code in main.rs same way as in the first use-case.
Reference resources in your HTML (static/index.html):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="/static/@fortawesome/fontawesome-free/css/all.css">
<script defer src="/static/@fortawesome/fontawesome-free/js/all.js"></script>
<title>Hi</title>
</head>
<body>
<i class="fas fa-thumbs-up"></i>
</body>
</html>§Use-case 3: package.json - WebPack usage
Create folder with static resources in your project (for example web), install required packages and webpack:
cd project_dir
mkdir -p web/src
cd web
echo -e "node_modules\ndist" > .gitignore
echo '{}' > package.json
# install lodash for usage in example
npm install --save lodash
# install webpack npm dependencies
npm install webpack webpack-cli html-webpack-plugin clean-webpack-plugin --save-devAdd web/webpack.config.js:
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "actix-web-static-files WebPack",
}),
],
output: {
filename: "main.js",
path: process.env.OUT_DIR
? path.resolve(process.env.OUT_DIR, "web", "dist", "bundle")
: path.resolve(__dirname, "dist", "bundle"),
},
};Add web/src/index.js:
import _ from 'lodash';
function component() {
const element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());Modify web/package.json by adding “scripts” sections:
{
"dependencies": {
"lodash": "^4.17.21"
},
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"html-webpack-plugin": "^5.2.0",
"webpack": "^5.24.2",
"webpack-cli": "^4.5.0"
},
"scripts": {
"build": "webpack"
}
}Add to Cargo.toml dependency to actix-web-static-files as in the first use case.
Add build.rs with call to bundle resources:
use static_files::NpmBuild;
fn main() -> std::io::Result<()> {
unsafe {
std::env::set_var("NODE_OPTIONS", "--openssl-legacy-provider");
}
NpmBuild::new("web")
.install()?
.run("build")?
.target("web/dist/bundle")
.change_detection()
.to_resource_dir()
.build()
}Include generated code in src/main.rs:
use actix_web::{App, HttpServer};
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let listen = std::env::var("LISTEN").unwrap_or_else(|_| "127.0.0.1:8084".into());
let server = HttpServer::new(|| {
let generated = generate();
App::new().service(actix_web_static_files::ResourceFiles::new("/", generated))
})
.bind(listen)?;
if let Some(addr) = server.addrs().first() {
println!("{:05}", addr.port());
}
let handle = actix_web::rt::spawn(server.run());
handle.await?
}Run the server:
cargo runRequest the resource:
$ curl -v http://localhost:8080
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8080 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
>
< HTTP/1.1 200 OK
< content-length: 199
< content-type: text/html
< etag: "c7:5e403845"
< date: Sun, 09 Feb 2020 16:51:45 GMT
<
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>actix-web-static-files WebPack</title>
</head>
<body>
<script type="text/javascript" src="main.js"></script></body>See also:
§Use-case 4: yarn package manager
We can use another package manager instead of npm. For example, to use yarn add .executable("yarn") to NpmBuild call:
use static_files::NpmBuild;
fn main() -> std::io::Result<()> {
NpmBuild::new("web")
.executable("yarn")
.install()?
.run("build")?
.target("web/dist/bundle")
.change_detection()
.to_resource_dir()
.build()
}See also:
§Use-case 5: Angular-like applications
If you are using Angular as frontend, you may want to resolve all not found calls via index.html of the frontend application. To do this call the method resolve_not_found_to_root after the resource creation.
use actix_web::{middleware::Logger, App, HttpServer};
use actix_web_static_files::ResourceFiles;
use angular_example_frontend::generate;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init();
HttpServer::new(move || {
let generated = generate();
App::new()
.wrap(Logger::default())
.service(ResourceFiles::new("/", generated).resolve_not_found_to_root())
})
.bind("127.0.0.1:8080")?
.run()
.await
}Remember to place you static resource route after all other routes in this case.
You can check the complete example Angular Router Sample.
Modules§
Structs§
- Resource
Files - Static resource files handling
Enums§
Traits§
- Resource
File - Resource file with static data and metadata.
- Resource
Files Collection - Basic abstraction for a dictionary of resources.