├── .gitignore
├── rust-toolchain.toml
├── crates
├── vite-rs
│ ├── examples
│ │ ├── vite-project-folder
│ │ │ ├── public
│ │ │ │ └── test.txt
│ │ │ ├── .gitignore
│ │ │ ├── app
│ │ │ │ ├── index.ts
│ │ │ │ ├── pack1.ts
│ │ │ │ ├── index.html
│ │ │ │ ├── vite.svg
│ │ │ │ └── index.css
│ │ │ ├── tsconfig.node.json
│ │ │ ├── vite.config.ts
│ │ │ ├── .eslintrc.cjs
│ │ │ ├── tsconfig.json
│ │ │ └── package.json
│ │ ├── custom_ctrl_c_handler.rs
│ │ └── basic_usage.rs
│ ├── test_projects
│ │ ├── normal_usage_test
│ │ │ ├── public
│ │ │ │ └── test.txt
│ │ │ ├── .gitignore
│ │ │ ├── app
│ │ │ │ ├── index.ts
│ │ │ │ ├── pack1.ts
│ │ │ │ ├── index.html
│ │ │ │ ├── vite.svg
│ │ │ │ └── index.css
│ │ │ └── vite.config.ts
│ │ ├── recompilation_test
│ │ │ ├── app
│ │ │ │ ├── test.txt
│ │ │ │ └── vite.config.ts
│ │ │ ├── .gitignore
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ │ └── main.rs
│ │ ├── ctrl_c_handling_test
│ │ │ ├── file.txt
│ │ │ ├── vite.config.ts
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ │ └── main.rs
│ │ ├── custom_output_dir_test
│ │ │ ├── file.txt
│ │ │ ├── Cargo.toml
│ │ │ ├── vite.config.ts
│ │ │ ├── src
│ │ │ │ └── main.rs
│ │ │ └── Cargo.lock
│ │ ├── custom_dev_server_port_test
│ │ │ ├── vite.config.ts
│ │ │ └── index.html
│ │ ├── tsconfig.node.json
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── experiments
│ │ ├── renaming_bundles_feature
│ │ │ ├── renaming_bundles
│ │ │ │ ├── script.js
│ │ │ │ ├── public
│ │ │ │ │ └── script.js
│ │ │ │ └── vite.config.ts
│ │ │ ├── renaming_bundles.rs
│ │ │ └── README.md
│ │ ├── README.md
│ │ └── detecting_locally_running_vite_dev_server
│ │ │ └── README.md
│ ├── script
│ │ └── list_vite_processes.sh
│ ├── src
│ │ └── lib.rs
│ ├── Cargo.toml
│ └── tests
│ │ ├── ctrl_c_handling_test.rs
│ │ ├── dev_server_port_test.rs
│ │ ├── recompilation_test.rs
│ │ └── normal_usage_test.rs
├── vite-rs-axum-0-8
│ ├── tests
│ │ ├── util
│ │ │ ├── mod.rs
│ │ │ └── run_project.rs
│ │ ├── ctrl_c_handling_test.rs
│ │ └── basic_usage_test.rs
│ ├── examples
│ │ └── basic_usage
│ │ │ ├── app
│ │ │ ├── public
│ │ │ │ ├── file.txt
│ │ │ │ └── test.css
│ │ │ ├── App.tsx
│ │ │ ├── index.html
│ │ │ ├── tsconfig.node.json
│ │ │ ├── script.tsx
│ │ │ ├── vite.config.ts
│ │ │ ├── package.json
│ │ │ └── tsconfig.json
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ └── main.rs
│ ├── test_projects
│ │ ├── basic_usage_test
│ │ │ ├── app
│ │ │ │ ├── public
│ │ │ │ │ ├── file.txt
│ │ │ │ │ └── test.css
│ │ │ │ ├── App.tsx
│ │ │ │ ├── index.html
│ │ │ │ ├── tsconfig.node.json
│ │ │ │ ├── script.tsx
│ │ │ │ ├── vite.config.ts
│ │ │ │ ├── package.json
│ │ │ │ └── tsconfig.json
│ │ │ └── README.md
│ │ └── ctrl_c_handling_test
│ │ │ ├── app
│ │ │ ├── public
│ │ │ │ ├── file.txt
│ │ │ │ └── test.css
│ │ │ ├── App.tsx
│ │ │ ├── index.html
│ │ │ ├── tsconfig.node.json
│ │ │ ├── script.tsx
│ │ │ ├── vite.config.ts
│ │ │ ├── package.json
│ │ │ └── tsconfig.json
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ └── main.rs
│ ├── src
│ │ ├── lib.rs
│ │ ├── vite_tower_service.rs
│ │ └── vite_serve.rs
│ ├── Cargo.toml
│ └── README.md
├── vite-rs-embed-macro
│ ├── src
│ │ ├── hash_utils.rs
│ │ ├── syn_utils.rs
│ │ ├── vite
│ │ │ ├── build
│ │ │ │ ├── vite_manifest.rs
│ │ │ │ └── file_entry.rs
│ │ │ └── mod.rs
│ │ └── lib.rs
│ ├── Cargo.toml
│ └── Cargo.lock
├── vite-rs-interface
│ ├── Cargo.toml
│ └── src
│ │ └── lib.rs
└── vite-rs-dev-server
│ ├── Cargo.toml
│ └── src
│ ├── util.rs
│ └── lib.rs
├── .vscode
└── settings.json
├── COPYRIGHT
├── docs
├── OLD_OUTPUT_DIR_WARNING.md
└── OLD_ASYNC_WARNING.md
├── Cargo.toml
├── LICENSE-MIT
├── .github
└── workflows
│ └── test.yml
└── LICENSE-APACHE
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | node_modules
3 | dist
4 | .vite
--------------------------------------------------------------------------------
/rust-toolchain.toml:
--------------------------------------------------------------------------------
1 | [toolchain]
2 | channel = "stable"
3 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/public/test.txt:
--------------------------------------------------------------------------------
1 | test
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/tests/util/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod run_project;
2 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/public/test.txt:
--------------------------------------------------------------------------------
1 | test
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/recompilation_test/app/test.txt:
--------------------------------------------------------------------------------
1 | asdf
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/ctrl_c_handling_test/file.txt:
--------------------------------------------------------------------------------
1 | some asset 123
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "rust-analyzer.cargo.features": [""]
3 | }
4 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/public/file.txt:
--------------------------------------------------------------------------------
1 | some asset 123
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | !dist/.gitkeep
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/custom_output_dir_test/file.txt:
--------------------------------------------------------------------------------
1 | some asset 123
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | !dist/.gitkeep
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/public/file.txt:
--------------------------------------------------------------------------------
1 | some asset 123
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/public/file.txt:
--------------------------------------------------------------------------------
1 | some asset 123
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/recompilation_test/.gitignore:
--------------------------------------------------------------------------------
1 | app/dist/
2 | !app/dist/.gitkeep
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/renaming_bundles_feature/renaming_bundles/script.js:
--------------------------------------------------------------------------------
1 | console.log("private");
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/renaming_bundles_feature/renaming_bundles/public/script.js:
--------------------------------------------------------------------------------
1 | console.log("public");
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod vite_serve;
2 | mod vite_tower_service;
3 |
4 | pub use vite_serve::{CacheStrategy, ViteServe};
5 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/README.md:
--------------------------------------------------------------------------------
1 | This directory holds the ViteJS project for the `basic_usage_test.rs` test.
2 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/public/test.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: black;
3 | color: white;
4 | font-family: Arial, sans-serif;
5 | padding: 42px;
6 | }
7 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/app/index.ts:
--------------------------------------------------------------------------------
1 | const div = document.createElement('div')
2 |
3 | div.innerHTML = 'Hello from vite-rs!'
4 |
5 | document.body.appendChild(div)
6 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/app/index.ts:
--------------------------------------------------------------------------------
1 | const div = document.createElement('div')
2 |
3 | div.innerHTML = 'Hello from vite-rs!'
4 |
5 | document.body.appendChild(div)
6 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const App = () => {
4 | return Test;
5 | };
6 |
7 | export default App;
8 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/public/test.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: black;
3 | color: white;
4 | font-family: Arial, sans-serif;
5 | padding: 42px;
6 | }
7 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const App = () => {
4 | return Test;
5 | };
6 |
7 | export default App;
8 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/public/test.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: black;
3 | color: white;
4 | font-family: Arial, sans-serif;
5 | padding: 42px;
6 | }
7 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const App = () => {
4 | return Test;
5 | };
6 |
7 | export default App;
8 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/app/pack1.ts:
--------------------------------------------------------------------------------
1 | const test = (() => {
2 | console.log('This is a test')
3 |
4 | const a: number = 3
5 |
6 | return a
7 | })()
8 |
9 | const num = test
10 |
11 | console.log('NUM: ', num)
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/recompilation_test/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "recompilation_test"
3 | version = "0.1.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | vite-rs = { path = "../../" }
9 |
10 | [workspace]
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/recompilation_test/src/main.rs:
--------------------------------------------------------------------------------
1 | #[derive(vite_rs::Embed)]
2 | #[root = "./app"]
3 | struct Assets;
4 |
5 | fn main() {
6 | for asset in Assets::iter() {
7 | println!("{}", asset);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/app/pack1.ts:
--------------------------------------------------------------------------------
1 | const test = (() => {
2 | console.log('This is a test')
3 |
4 | const a: number = 3
5 |
6 | return a
7 | })()
8 |
9 | const num = test
10 |
11 | console.log('NUM: ', num)
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/custom_dev_server_port_test/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 |
3 | export default defineConfig({
4 | build: {
5 | rollupOptions: {
6 | input: ["index.html"],
7 | },
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/custom_output_dir_test/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "ctrl_c_handling_test"
3 | version = "0.1.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | vite-rs = { path = "../../" }
9 |
10 | [workspace]
11 |
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/README.md:
--------------------------------------------------------------------------------
1 | # Unsupported Features
2 |
3 | This directory holds tests for features that are not supported and attempts to document in writing or code why it is difficult or unreasonable to support them given the trajectory of the crate/community.
4 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/ctrl_c_handling_test/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 |
3 | export default defineConfig({
4 | build: {
5 | rollupOptions: {
6 | input: "file.txt",
7 | },
8 | manifest: true,
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/crates/vite-rs-embed-macro/src/hash_utils.rs:
--------------------------------------------------------------------------------
1 | use sha2::{Digest, Sha256};
2 |
3 | pub fn get_content_hash(content: &[u8]) -> String {
4 | let mut hasher = Sha256::new();
5 | hasher.update(content);
6 | let hash = hasher.finalize();
7 | format!("{:X}", hash)
8 | }
9 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/custom_output_dir_test/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 |
3 | export default defineConfig({
4 | build: {
5 | rollupOptions: {
6 | input: "file.txt",
7 | },
8 | outDir: "./custom-output-dir/dist",
9 | manifest: true,
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/custom_output_dir_test/src/main.rs:
--------------------------------------------------------------------------------
1 | #[derive(vite_rs::Embed)]
2 | #[root = "."]
3 | #[output = "./custom-output-dir/dist"]
4 | struct Assets;
5 |
6 | fn main() {
7 | let _guard = Assets::start_dev_server(true);
8 |
9 | std::thread::sleep(std::time::Duration::from_secs(12));
10 | }
11 |
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/renaming_bundles_feature/renaming_bundles/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 |
3 | export default defineConfig({
4 | build: {
5 | rollupOptions: {
6 | input: { bundle: "./script.js" },
7 | },
8 | manifest: true,
9 | },
10 | publicDir: "public",
11 | });
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/custom_dev_server_port_test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Custom Dev Server Port Test
6 |
7 |
8 | Custom Dev Server Port Test
9 | It works!
10 |
11 |
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World
5 |
6 |
7 |
8 | Loading...
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite-rs-tests",
3 | "private": true,
4 | "type": "module",
5 | "scripts": {
6 | "vite": "vite"
7 | },
8 | "devDependencies": {
9 | "@types/node": "^22.4.0",
10 | "glob": "^11.0.0",
11 | "typescript": "^5.2.2",
12 | "vite": "^5.2.0"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World
5 |
6 |
7 |
8 | Loading...
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World
5 |
6 |
7 |
8 | Loading...
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/script.tsx:
--------------------------------------------------------------------------------
1 | import React, { lazy } from "react";
2 | import ReactDOM from "react-dom/client";
3 |
4 | (async () => {
5 | const App = await lazy(() => import("./App"));
6 |
7 | ReactDOM.createRoot(document.body).render(
8 |
9 |
10 |
11 | );
12 | })();
13 |
--------------------------------------------------------------------------------
/crates/vite-rs/script/list_vite_processes.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Tests if any vite dev servers are running, printing the PID and args of the process.
4 | #
5 | # This script was built for unix-like operation systems in mind.
6 | # It likely won't work on Windows.
7 |
8 | ps aux | grep -v grep | grep -v 'list_vite_processes.sh' | grep vite | tr -s " " | cut -d' ' -f2,11-
9 |
--------------------------------------------------------------------------------
/COPYRIGHT:
--------------------------------------------------------------------------------
1 | Copyright 2024 Haris Khan
2 |
3 | Licensed under the Apache License, Version 2.0 or the MIT license
5 | , at your
6 | option. All files in the project carrying such notice may not be
7 | copied, modified, or distributed except according to those terms.
8 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/recompilation_test/app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import path from "path";
3 | import { globSync } from "glob";
4 |
5 | export default defineConfig(() => ({
6 | build: {
7 | rollupOptions: {
8 | input: globSync(path.resolve(__dirname, "*.txt")),
9 | },
10 | manifest: true,
11 | },
12 | }));
13 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/script.tsx:
--------------------------------------------------------------------------------
1 | import React, { lazy } from "react";
2 | import ReactDOM from "react-dom/client";
3 |
4 | (async () => {
5 | const App = await lazy(() => import("./App"));
6 |
7 | ReactDOM.createRoot(document.body).render(
8 |
9 |
10 |
11 | );
12 | })();
13 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/script.tsx:
--------------------------------------------------------------------------------
1 | import React, { lazy } from "react";
2 | import ReactDOM from "react-dom/client";
3 |
4 | (async () => {
5 | const App = await lazy(() => import("./App"));
6 |
7 | ReactDOM.createRoot(document.body).render(
8 |
9 |
10 |
11 | );
12 | })();
13 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | build: {
7 | rollupOptions: {
8 | input: ["index.html"],
9 | },
10 | },
11 | server: {
12 | hmr: {
13 | port: 21012,
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | build: {
7 | rollupOptions: {
8 | input: ["index.html"],
9 | },
10 | },
11 | server: {
12 | hmr: {
13 | port: 21012,
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | build: {
7 | rollupOptions: {
8 | input: ["index.html"],
9 | },
10 | },
11 | server: {
12 | hmr: {
13 | port: 21012,
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "basic_usage"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 | axum = { version = "0.8", features = ["macros"] }
8 | tokio = { version = "1", default-features = false, features = ["macros", "rt-multi-thread"] }
9 | vite-rs = { path = "../../../vite-rs" }
10 | vite-rs-axum-0-8 = { path = "../../" }
11 |
12 | [workspace]
13 |
--------------------------------------------------------------------------------
/crates/vite-rs/src/lib.rs:
--------------------------------------------------------------------------------
1 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
2 | #[cfg(feature = "ctrlc")]
3 | #[cfg(not(doctest))] // for some reason, the cfgs above don't apply to doc tests
4 | pub use vite_rs_dev_server::ctrlc;
5 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
6 | pub use vite_rs_dev_server::{self, ViteProcess};
7 | pub use vite_rs_embed_macro::Embed;
8 |
9 | pub use vite_rs_interface::*;
10 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 |
3 | export default defineConfig({
4 | build: {
5 | rollupOptions: {
6 | input: ["app/index.html", "app/pack1.ts"],
7 | },
8 | manifest: true, // **IMPORTANT**: this is required.
9 | outDir: "./dist", // this is the default value
10 | },
11 | publicDir: "./public", // this is the default value
12 | });
13 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "dependencies": {
10 | "vite": "^6.3.5"
11 | },
12 | "devDependencies": {
13 | "@vitejs/plugin-react": "^4.5.2",
14 | "react": "^19.1.0",
15 | "react-dom": "^19.1.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "dependencies": {
10 | "vite": "^6.3.5"
11 | },
12 | "devDependencies": {
13 | "@vitejs/plugin-react": "^4.5.2",
14 | "react": "^19.1.0",
15 | "react-dom": "^19.1.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/crates/vite-rs-interface/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "vite-rs-interface"
3 | version.workspace = true
4 | description.workspace = true
5 | repository.workspace = true
6 | readme.workspace = true
7 | authors.workspace = true
8 | keywords.workspace = true
9 | categories.workspace = true
10 | license.workspace = true
11 | edition.workspace = true
12 | homepage.workspace = true
13 |
14 | [dependencies]
15 |
16 | [features]
17 | debug-prod = []
18 | content-hash = []
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "dependencies": {
10 | "vite": "^6.3.5"
11 | },
12 | "devDependencies": {
13 | "@vitejs/plugin-react": "^4.5.2",
14 | "react": "^19.1.0",
15 | "react-dom": "^19.1.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/ctrl_c_handling_test/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "ctrl_c_handling_test"
3 | version = "0.1.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | vite-rs = { path = "../../", default-features = false }
9 | ctrlc = { optional = true, version = "3.4.4", features = ["termination"] }
10 |
11 | [features]
12 | default = []
13 | custom-ctrl-c-handler = ["ctrlc"]
14 | builtin-ctrl-c-handler = ["vite-rs/ctrlc"]
15 |
16 | [workspace]
17 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | build: {
7 | rollupOptions: {
8 | input: ['app/index.html', 'app/pack1.ts'],
9 | },
10 | manifest: true, // **IMPORTANT**: this is required.
11 | outDir: './dist', // this is the default value
12 | },
13 | publicDir: './public', // this is the default value
14 | })
15 |
--------------------------------------------------------------------------------
/docs/OLD_OUTPUT_DIR_WARNING.md:
--------------------------------------------------------------------------------
1 | # Note: this is no longer the case since ViteJS's default emptyOutDir option is set to true, we assume it's safe to create the directory for you.
2 |
3 | > `Output directory 'path/to/dist' does not exist. Please create it. rust-analyzer macro-error`
4 |
5 | For release builds, this library requires you to manually create a dist folder (where the compiled assets are outputted by Vite). You should make this directory in your CI steps and also locally if you do --release builds.
6 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vite-rs
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vite-rs
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "ctrl_c_handling_test"
3 | version = "1.0.0"
4 | edition = "2024"
5 | publish = false
6 |
7 | [[bin]]
8 | name = "axum_test"
9 | path = "src/main.rs"
10 |
11 | [dependencies]
12 | axum = { version = "0.8", features = ["macros"] }
13 | ctrlc = { version = "3", features = ["termination"] }
14 | tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
15 | vite-rs = { path = "../../../vite-rs", version = "0.2.1", default-features = false, features = [
16 | "content-hash",
17 | ] }
18 | vite-rs-axum-0-8 = { path = "../../" }
19 |
20 | [features]
21 |
22 | [workspace]
23 |
--------------------------------------------------------------------------------
/crates/vite-rs-dev-server/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "vite-rs-dev-server"
3 | version.workspace = true
4 | description.workspace = true
5 | repository.workspace = true
6 | readme.workspace = true
7 | authors.workspace = true
8 | keywords.workspace = true
9 | categories.workspace = true
10 | license.workspace = true
11 | edition.workspace = true
12 | homepage.workspace = true
13 |
14 | [dependencies]
15 | reqwest = { version = "0.12", default-features = false, features = [
16 | "blocking",
17 | ] }
18 | command-group = "5.0.1"
19 | lazy_static = "1.4.0"
20 | ctrlc = { optional = true, version = "3.4.4", features = ["termination"] }
21 |
22 | [features]
23 | ctrlc = ["dep:ctrlc"]
24 | debug-prod = []
25 |
--------------------------------------------------------------------------------
/crates/vite-rs-dev-server/src/util.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, TcpListener, ToSocketAddrs},
3 | ops::Range,
4 | };
5 |
6 | fn test_bind(addr: A) -> bool {
7 | TcpListener::bind(addr)
8 | .map(|t| t.local_addr().is_ok())
9 | .unwrap_or(false)
10 | }
11 |
12 | pub fn is_port_free(port: u16) -> bool {
13 | let ipv4 = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port);
14 | let ipv6 = SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, port, 0, 0);
15 |
16 | test_bind(ipv6) && test_bind(ipv4)
17 | }
18 |
19 | pub fn find_free_port(mut range: Range) -> Option {
20 | range.find(|port| is_port_free(*port))
21 | }
22 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | "types": ["node"],
18 |
19 | /* Linting */
20 | "strict": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "noFallthroughCasesInSwitch": true
24 | },
25 | "include": ["src"],
26 | "references": [{ "path": "./tsconfig.node.json" }]
27 | }
28 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | "types": ["node"],
18 |
19 | /* Linting */
20 | "strict": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "noFallthroughCasesInSwitch": true
24 | },
25 | "include": ["src"],
26 | "references": [{ "path": "./tsconfig.node.json" }]
27 | }
28 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | "types": ["node"],
18 |
19 | /* Linting */
20 | "strict": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "noFallthroughCasesInSwitch": true
24 | },
25 | "include": ["src"],
26 | "references": [{ "path": "./tsconfig.node.json" }]
27 | }
28 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | "types": ["node"],
18 |
19 | /* Linting */
20 | "strict": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "noFallthroughCasesInSwitch": true
24 | },
25 | "include": ["src"],
26 | "references": [{ "path": "./tsconfig.node.json" }]
27 | }
28 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = [
4 | "crates/vite-rs",
5 | "crates/vite-rs-axum-0-8",
6 | "crates/vite-rs-dev-server",
7 | "crates/vite-rs-embed-macro",
8 | "crates/vite-rs-interface",
9 | ]
10 |
11 | [workspace.package]
12 | version = "0.2.1"
13 | description = "Uses ViteJS to compile frontend assets and embeds the results into your Rust binary. (Serves from the ViteJS dev server in development.)"
14 | repository = "https://github.com/Wulf/vite-rs"
15 | readme = "README.md"
16 | authors = ["Haris <4259838+Wulf@users.noreply.github.com>"]
17 | keywords = ["vite", "vitejs", "bundler", "swc", "esbuild"]
18 | categories = ["web-programming", "development-tools", "filesystem"]
19 | license = "MIT OR Apache-2.0"
20 | edition = "2021"
21 | homepage = "https://github.com/Wulf/vite-rs"
22 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/examples/basic_usage/src/main.rs:
--------------------------------------------------------------------------------
1 | use axum::Router;
2 | use vite_rs_axum_0_8::ViteServe;
3 |
4 | #[derive(vite_rs::Embed)]
5 | #[root = "./app"]
6 | struct Assets;
7 |
8 | #[tokio::main]
9 | async fn main() {
10 | #[cfg(debug_assertions)]
11 | let _guard = Assets::start_dev_server(true);
12 |
13 | println!("Starting server on http://localhost:3000");
14 |
15 | let _ = axum::serve(
16 | tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(),
17 | Router::new()
18 | .route_service("/", ViteServe::new(Assets::boxed()))
19 | .route_service("/{*path}", ViteServe::new(Assets::boxed()))
20 | .into_make_service(),
21 | )
22 | .await;
23 |
24 | // see `crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test` for an example on how to handle graceful shutdown!
25 | }
26 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/src/vite_tower_service.rs:
--------------------------------------------------------------------------------
1 | use std::convert::Infallible;
2 | use std::future::Future;
3 | use std::pin::Pin;
4 | use std::task::{Context, Poll};
5 |
6 | use axum::body::{Bytes, HttpBody};
7 | use axum::http::request::Request;
8 | use axum::response::Response;
9 | use tower::Service;
10 |
11 | use crate::vite_serve::ViteServe;
12 |
13 | impl Service> for ViteServe
14 | where
15 | B: HttpBody + Send + 'static,
16 | {
17 | type Response = Response;
18 | type Error = Infallible;
19 | type Future = Pin> + Send>>;
20 |
21 | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> {
22 | Poll::Ready(Ok(()))
23 | }
24 |
25 | fn call(&mut self, req: Request) -> Self::Future {
26 | let svc = self.clone();
27 | Box::pin(async move { Ok(svc.serve(req).await) })
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "vite-rs-axum-0-8"
3 | version.workspace = true
4 | description.workspace = true
5 | repository.workspace = true
6 | readme.workspace = true
7 | authors.workspace = true
8 | keywords.workspace = true
9 | categories.workspace = true
10 | license.workspace = true
11 | edition.workspace = true
12 | homepage.workspace = true
13 |
14 | [dependencies]
15 | vite-rs-interface = { path = "../vite-rs-interface", features = [
16 | "content-hash",
17 | ], version = "0.2.1" }
18 | axum = { version = "0.8", default-features = false }
19 | tower = "0.5"
20 |
21 | [dev-dependencies]
22 | nix = { version = "0.29.0", features = ["signal"] } # for tests
23 | reqwest = { version = "0.12.7", features = ["blocking"] } # for tests
24 | vite-rs = { path = "../vite-rs", version = "0.2.1", default-features = false, features = [
25 | "ctrlc",
26 | "content-hash",
27 | ] } # for tests
28 | # http = "1.3.1" # for tests
29 | tokio = { version = "1", features = ["macros", "rt-multi-thread"] } # for tests
30 |
31 | [features]
32 | debug-prod = ["vite-rs-interface/debug-prod"]
33 |
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/renaming_bundles_feature/renaming_bundles.rs:
--------------------------------------------------------------------------------
1 | #[derive(vite_rs::Embed)]
2 | #[root = "./tests/renaming_bundles"]
3 | struct Assets;
4 |
5 | #[test]
6 | pub fn test() {
7 | #[cfg(debug_assertions)]
8 | let _guard = Assets::start_dev_server(true);
9 |
10 | #[cfg(debug_assertions)]
11 | std::thread::sleep(std::time::Duration::from_secs(2));
12 |
13 | #[cfg(not(debug_assertions))]
14 | Assets::iter().for_each(|asset| {
15 | println!("(renaming_bundles) asset: '{:?}'", asset);
16 | });
17 |
18 | ensure_public_script();
19 | ensure_script_is_renamed_to_bundle();
20 | }
21 |
22 | fn ensure_public_script() {
23 | let file = Assets::get("script.js").unwrap();
24 |
25 | let content = std::str::from_utf8(&file.bytes).unwrap();
26 |
27 | assert_eq!(content, "console.log(\"public\");");
28 | }
29 |
30 | fn ensure_script_is_renamed_to_bundle() {
31 | let file = Assets::get("bundle.js").unwrap();
32 |
33 | let content = std::str::from_utf8(&file.bytes).unwrap();
34 |
35 | assert_eq!(content, "console.log(\"private\");");
36 | }
37 |
--------------------------------------------------------------------------------
/crates/vite-rs-embed-macro/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "vite-rs-embed-macro"
3 | version.workspace = true
4 | description.workspace = true
5 | repository.workspace = true
6 | readme.workspace = true
7 | authors.workspace = true
8 | keywords.workspace = true
9 | categories.workspace = true
10 | license.workspace = true
11 | edition.workspace = true
12 | homepage.workspace = true
13 |
14 | [lib]
15 | proc-macro = true
16 |
17 | [dependencies]
18 | vite-rs-dev-server = { path = "../vite-rs-dev-server", version = "0.2.1" }
19 |
20 | syn = { version = "2", default-features = false, features = [
21 | "derive",
22 | "parsing",
23 | "proc-macro",
24 | "printing",
25 | ] }
26 | quote = "1"
27 | proc-macro2 = "1"
28 | walkdir = "2.5.0"
29 | mime_guess = "2.0.4"
30 | serde_json = "1.0.116"
31 | serde = { version = "1.0.199", features = ["derive"] }
32 | chrono = { version = "0.4", default-features = false, features = ["alloc"] }
33 | sha2 = { optional = true, version = "0.10", default-features = false }
34 |
35 | [features]
36 | default = []
37 | debug-prod = []
38 | ctrlc = []
39 | content-hash = ["sha2"]
40 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-react-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview",
11 | "vite_rs:start": "npm run dev",
12 | "vite_rs:build": "npm run build"
13 | },
14 | "dependencies": {
15 | "react": "^18.2.0",
16 | "react-dom": "^18.2.0"
17 | },
18 | "devDependencies": {
19 | "@types/node": "^20.12.7",
20 | "@types/react": "^18.2.66",
21 | "@types/react-dom": "^18.2.22",
22 | "@typescript-eslint/eslint-plugin": "^7.2.0",
23 | "@typescript-eslint/parser": "^7.2.0",
24 | "@vitejs/plugin-react": "^4.2.1",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.0",
27 | "eslint-plugin-react-refresh": "^0.4.6",
28 | "typescript": "^5.2.2",
29 | "vite": "^5.2.0"
30 | },
31 | "prettier": {
32 | "semi": false,
33 | "singleQuote": true,
34 | "trailingComma": "all"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Haris Khan
4 |
5 | Permission is hereby granted, free of charge, to any
6 | person obtaining a copy of this software and associated
7 | documentation files (the "Software"), to deal in the
8 | Software without restriction, including without
9 | limitation the rights to use, copy, modify, merge,
10 | publish, distribute, sublicense, and/or sell copies of
11 | the Software, and to permit persons to whom the Software
12 | is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice
16 | shall be included in all copies or substantial portions
17 | of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
20 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
21 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
23 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
26 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 | DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/renaming_bundles_feature/README.md:
--------------------------------------------------------------------------------
1 | # Note: this was moved to 'unsupported'. At the moment, we can't rename bundles in development mode since that would require parsing the vite config file. Currently, this crate attempts to be low-touch and tries to avoid relying on the vite configuration.
2 |
3 | # Renaming Bundles
4 |
5 | When the vite config has a hash for rollupOptions.input, the `Asset::get()` method should use the key used as the entrypoint name.
6 |
7 | **Why?** This is useful when dealing with naming conflicts between entrypoints and public files served from the `viteConfig.publicDir` option.
8 |
9 | # Example
10 |
11 | ### Directory structure
12 |
13 | ```
14 | .
15 | ├── public
16 | │ └── script.js
17 | ├── script.js // name clash with public/script.js
18 | └── vite.config.ts
19 | ```
20 |
21 | ### `vite.config.ts`
22 |
23 | ```typescript
24 | import { defineConfig } from "vite";
25 |
26 | export default defineConfig({
27 | build: {
28 | rollupOptions: {
29 | input: { bundle: "./script.js" },
30 | },
31 | manifest: true,
32 | },
33 | publicDir: "./public",
34 | });
35 | ```
36 |
37 | ### Rust usage
38 |
39 | ```rust
40 | #[vite_rs::Embed]
41 | #[root = "./tests/renaming_bundles"]
42 | struct Assets;
43 |
44 | fn main() {
45 | let bundle = Assets::get("bundle.js");
46 | let script = Assets::get("script.js");
47 |
48 | // ...
49 | }
50 |
51 | ```
52 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/ctrl_c_handling_test/src/main.rs:
--------------------------------------------------------------------------------
1 | #[derive(vite_rs::Embed)]
2 | #[root = "."]
3 | struct Assets;
4 |
5 | fn main() {
6 | #[cfg(not(debug_assertions))]
7 | {
8 | panic!("This binary should not be run in release mode.");
9 | }
10 |
11 | #[cfg(debug_assertions)]
12 | {
13 | #[cfg(all(
14 | not(feature = "builtin-ctrl-c-handler"),
15 | not(feature = "custom-ctrl-c-handler")
16 | ))]
17 | {
18 | panic!("You need to enable one of the 'builtin-ctrl-c-handler' or 'custom-ctrl-c-handler' features to run this test.");
19 | }
20 |
21 | ///
22 | /// Feature: Built-in ctrl-c handling
23 | ///
24 |
25 | #[cfg(feature = "builtin-ctrl-c-handler")]
26 | let _guard = Assets::start_dev_server(true);
27 |
28 | ///
29 | /// Feature: Custom ctrl-c handling
30 | ///
31 |
32 | #[cfg(feature = "custom-ctrl-c-handler")]
33 | let _guard = Assets::start_dev_server();
34 |
35 | #[cfg(feature = "custom-ctrl-c-handler")]
36 | ctrlc::set_handler(move || {
37 | println!("Custom handler called!");
38 |
39 | Assets::stop_dev_server();
40 |
41 | std::process::exit(0);
42 | })
43 | .expect("Could not set ctrl-c handler.");
44 |
45 | std::thread::sleep(std::time::Duration::from_secs(12));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/app/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/app/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/vite-project-folder/app/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/crates/vite-rs/test_projects/normal_usage_test/app/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/crates/vite-rs/experiments/detecting_locally_running_vite_dev_server/README.md:
--------------------------------------------------------------------------------
1 | # Detecting a locally-running Vite dev server
2 |
3 | _This is a thought experiment_.
4 |
5 | Imagine a user wants to run a ViteJS dev server locally instead of having the `cargo run` manage its lifecycle. Perhaps for debugging reasons.
6 |
7 | This one-off scenario could be supported by checking if a ViteJS dev server is running on the configured port; however, this behaviour is problematic given that a vite dev server running for another app on that port would serve unexpected content.
8 |
9 | So, perhaps, it's not such a good idea.
10 |
11 | The question becomes: can we confirm that the vite dev server is running for the project specified by `#[root = "path/to/project"]`?
12 |
13 | ```rust
14 | #[vite_rs::Embed]
15 | #[root = "path/to/project"]
16 | struct Assets;
17 |
18 | fn main() {
19 | #[cfg(debug_assertions)]
20 | {
21 | const port = Asset::get_dev_server_port();
22 |
23 | let expected_signature = Asset::get_dev_server_signature();
24 |
25 | if vite_rs_dev_server::is_vite_dev_server_running(port, expected_signature) {
26 | println!("Dev server is running!");
27 | } else {
28 | println!("Dev server is not running!");
29 | }
30 | }
31 | }
32 | ```
33 |
34 | Note: `get_dev_server_signature` and `is_vite_dev_server_running(port, signature)` are the implementation details we're interested in here.
35 | The signature has to be something that the vite dev server can provide, and it would be unique to the project.
36 |
--------------------------------------------------------------------------------
/crates/vite-rs/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "vite-rs"
3 | version.workspace = true
4 | description.workspace = true
5 | repository.workspace = true
6 | readme.workspace = true
7 | authors.workspace = true
8 | keywords.workspace = true
9 | categories.workspace = true
10 | license.workspace = true
11 | edition.workspace = true
12 | homepage.workspace = true
13 |
14 | [[example]]
15 | name = "basic_usage"
16 | path = "examples/basic_usage.rs"
17 |
18 | [[example]]
19 | name = "custom_ctrl_c_handler"
20 | path = "examples/custom_ctrl_c_handler.rs"
21 |
22 | [dev-dependencies]
23 | nix = { version = "0.29.0", features = ["signal"] } # for tests
24 | reqwest = { version = "0.12.7" } # for tests
25 | command-group = { version = "5.0.1" } # for tests
26 | ctrlc = { version = "3.4.4" } # for examples and tests
27 | sha2 = "0.10.9" # for tests
28 |
29 | [dependencies]
30 | vite-rs-embed-macro = { path = "../vite-rs-embed-macro", version = "0.2.1" }
31 | vite-rs-dev-server = { path = "../vite-rs-dev-server", version = "0.2.1" }
32 | vite-rs-interface = { path = "../vite-rs-interface", version = "0.2.1" }
33 |
34 | [features]
35 | default = ["ctrlc", "content-hash"]
36 | ctrlc = ["vite-rs-dev-server/ctrlc", "vite-rs-embed-macro/ctrlc"]
37 | debug-prod = [
38 | "vite-rs-interface/debug-prod",
39 | "vite-rs-dev-server/debug-prod",
40 | "vite-rs-embed-macro/debug-prod",
41 | ]
42 | content-hash = [
43 | "vite-rs-interface/content-hash",
44 | "vite-rs-embed-macro/content-hash",
45 | ]
46 |
--------------------------------------------------------------------------------
/crates/vite-rs-axum-0-8/tests/util/run_project.rs:
--------------------------------------------------------------------------------
1 | fn test_project_path(test_project_name: &str) -> std::path::PathBuf {
2 | let workspace_dir =
3 | std::env::var("CARGO_MANIFEST_DIR").expect("Could not determine workspace directory.");
4 |
5 | // for some reason, the current directory is not the root workspace directory, but instead
6 | // the `crates/vite-rs-axum-0-8` directory when running the tests.
7 | //
8 | // let's make sure this comment is correct by doing this assertion:
9 | assert!(workspace_dir.ends_with("crates/vite-rs-axum-0-8"));
10 |
11 | let test_project_path =
12 | std::path::PathBuf::from_iter(&[&workspace_dir, "test_projects", test_project_name]);
13 |
14 | test_project_path
15 | }
16 |
17 | pub fn run(
18 | test_project_name: &str,
19 | release_build: bool,
20 | feature_flags: Vec<&str>,
21 | ) -> std::process::Child {
22 | assert!(std::process::Command::new("cargo")
23 | .arg("build")
24 | .args(if release_build {
25 | vec!["--release"]
26 | } else {
27 | vec![]
28 | })
29 | .args(feature_flags)
30 | .current_dir(test_project_path(test_project_name))
31 | .status()
32 | .expect("Failed to compile test project.")
33 | .success());
34 |
35 | std::process::Command::new("cargo")
36 | .arg("run")
37 | .current_dir(test_project_path(test_project_name))
38 | .spawn()
39 | .expect("Failed to run test project.")
40 | }
41 |
42 | #[cfg(unix)]
43 | pub fn stop(mut child: std::process::Child) {
44 | assert!(child.kill().is_ok());
45 | assert!(child.wait().is_ok());
46 | }
47 |
--------------------------------------------------------------------------------
/crates/vite-rs-interface/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Production File
2 | #[cfg(any(not(debug_assertions), feature = "debug-prod"))]
3 | #[derive(Debug, Clone)]
4 | /// File retrieved from a ViteJS-compiled project
5 | pub struct ViteFile {
6 | pub bytes: ::std::borrow::Cow<'static, [u8]>,
7 | pub last_modified: Option<&'static str>,
8 | pub content_type: &'static str,
9 | pub content_length: u64,
10 | #[cfg(feature = "content-hash")]
11 | /// SHA-256 hash of the file contents.
12 | pub content_hash: &'static str,
13 | }
14 |
15 | // Production Struct Trait
16 | /// Note: this is used to allow dynamic usage of embedded asset structs.
17 | #[cfg(any(not(debug_assertions), feature = "debug-prod"))]
18 | pub trait GetFromVite: Send + Sync + 'static {
19 | fn get(&self, file_path: &str) -> Option;
20 | fn clone_box(&self) -> Box;
21 | }
22 |
23 | // Development File
24 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
25 | #[derive(Debug, Clone)]
26 | /// File retreived from the ViteJS dev server
27 | pub struct ViteFile {
28 | pub bytes: Vec,
29 | pub last_modified: Option,
30 | pub content_type: String,
31 | pub content_length: u64,
32 | #[cfg(feature = "content-hash")]
33 | /// Note: in development mode, this is a weak hash returned by the ViteJS dev server.
34 | pub content_hash: String,
35 | }
36 |
37 | // Development Struct Trait
38 | /// Note: this is used to allow dynamic usage of embedded asset structs.
39 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
40 | pub trait GetFromVite: Send + Sync + 'static {
41 | fn get(&self, file_path: &str) -> Option;
42 | fn clone_box(&self) -> Box;
43 | }
44 |
--------------------------------------------------------------------------------
/docs/OLD_ASYNC_WARNING.md:
--------------------------------------------------------------------------------
1 | # Note: this is no longer the case and the warning has been removed from the main readme. We keep this checked-in for historic reasons.
2 |
3 | # Async usage warning
4 |
5 | **This applies to #[cfg(debug_assertions)] only:**
6 |
7 | In development mode, we use a blocking `reqwest` client to retrieve files from the ViteJS dev server. This has the consequence that usage of `YourStruct::get("./some/asset.html")` will need to be wrapped in a `tokio::task::spawn_blocking` in async environments. See https://docs.rs/reqwest/latest/reqwest/blocking/index.html for more information. Here's the particular excerpt:
8 |
9 | > [**Module reqwest::blocking**](https://docs.rs/reqwest/latest/reqwest/blocking/index.html)
10 | >
11 | > [...] If the immediate context is only synchronous, but a transitive caller is async, consider changing that caller to use [`tokio::task::spawn_blocking`](https://docs.rs/tokio/1.37.0/tokio/task/fn.spawn_blocking.html) around the calls that need to block.
12 |
13 | ### Async example (tokio)
14 |
15 | ```rust
16 | #[vite_rs::Embed]
17 | #[input = "./assets"]
18 | struct Assets;
19 |
20 | #[tokio::main]
21 | async fn main() {
22 | // DEV example:
23 | #[cfg(debug_assertions)]
24 | {
25 | let asset = tokio::task::spawn_blocking(|| {
26 | Assets::get("index.html")
27 | }).await.unwrap();;
28 |
29 | println!("{}", asset);
30 | }
31 |
32 |
33 | // PROD example:
34 | #[cfg(not(debug_assertions))]
35 | {
36 | let asset = Assets::get("index.html");
37 | println!("{}", asset);
38 | }
39 | }
40 | ```
41 |
42 | ### Why doesn't `vite_rs` use an async `reqwest` client and make the `::get()` fn async?
43 |
44 | The `rust_embed` crate doesn't do this, and we wanted to keep the API consistent with that crate.
45 |
--------------------------------------------------------------------------------
/crates/vite-rs-embed-macro/src/syn_utils.rs:
--------------------------------------------------------------------------------
1 | use syn::{Data, Expr, ExprLit, Fields, Lit, Meta, MetaNameValue};
2 |
3 | /// Find all pairs of the `name = "value"` attribute from the derive input
4 | pub fn find_attribute_values(ast: &syn::DeriveInput, attr_name: &str) -> Vec {
5 | ast.attrs
6 | .iter()
7 | .filter(|value| value.path().is_ident(attr_name))
8 | .filter_map(|attr| match &attr.meta {
9 | // `name = "value"`
10 | Meta::NameValue(MetaNameValue {
11 | value:
12 | Expr::Lit(ExprLit {
13 | lit: Lit::Str(val), ..
14 | }),
15 | ..
16 | }) => Some(val.value()),
17 | // `name = 123`
18 | Meta::NameValue(MetaNameValue {
19 | value:
20 | Expr::Lit(ExprLit {
21 | lit: Lit::Int(val), ..
22 | }),
23 | ..
24 | }) => Some(val.base10_digits().to_string()),
25 | // other
26 | _ => None,
27 | })
28 | .collect()
29 | }
30 |
31 | /// Returns an Err if the DeriveInput is not a unit struct
32 | ///
33 | /// # Example
34 | ///
35 | /// ```ignore
36 | /// #[derive(vite_rs::Embed)]
37 | /// struct MyStruct;
38 | /// ```
39 | ///
40 | /// Instead of:
41 | ///
42 | /// ```ignore
43 | /// #[derive(vite_rs::Embed)]
44 | /// struct MyStruct {
45 | /// field: String,
46 | /// }
47 | /// ```
48 | pub fn ensure_unit_struct(ast: &syn::DeriveInput) -> syn::Result<()> {
49 | match ast.data {
50 | Data::Struct(ref data) => match data.fields {
51 | Fields::Unit => {}
52 | _ => {
53 | return Err(syn::Error::new_spanned(
54 | ast,
55 | "Embed can only be derived for unit structs",
56 | ))
57 | }
58 | },
59 | _ => {
60 | return Err(syn::Error::new_spanned(
61 | ast,
62 | "Embed can only be derived for unit structs",
63 | ))
64 | }
65 | };
66 |
67 | Ok(())
68 | }
69 |
--------------------------------------------------------------------------------
/crates/vite-rs-embed-macro/src/vite/build/vite_manifest.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | #[allow(dead_code, non_snake_case)]
4 | #[derive(serde::Deserialize)]
5 | pub struct ViteManifestEntry {
6 | /// Script content to load for this entry
7 | pub file: String,
8 |
9 | /// Script content to lazy-load for this entry
10 | pub dynamicImports: Option>, // using `import(..)`
11 |
12 | /// Style content to load for this entry
13 | pub css: Option>, // using import '*.css'
14 |
15 | /// If true, eager-load this content
16 | pub isEntry: Option,
17 |
18 | /// If true, lazy-load this content
19 | pub isDynamicEntry: Option, // src: String, /* => not necessary :) */
20 | // assets: Option>, /* => these will be served by the server! */
21 | }
22 |
23 | pub type ViteManifest = HashMap;
24 |
25 | pub fn load_vite_manifest(path: &str) -> ViteManifest {
26 | let manifest_json_str = std::fs::read_to_string(path).unwrap();
27 |
28 | parse_vite_manifest_json_str(&manifest_json_str)
29 | }
30 |
31 | pub fn parse_vite_manifest_json_str(manifest_json: &str) -> ViteManifest {
32 | let manifest_json = serde_json::from_str(manifest_json).expect("failed to parse vite manifest");
33 |
34 | let mut manifest: ViteManifest = HashMap::new();
35 |
36 | match manifest_json {
37 | serde_json::Value::Object(obj) => {
38 | obj.keys().for_each(|manifest_key| {
39 | let details = obj.get(manifest_key).unwrap();
40 |
41 | let manifest_entry = serde_json::from_value::(details.clone())
42 | .expect(
43 | "invalid vite manifest (or perhaps the vite-rs parser isn't up-to-date!)",
44 | );
45 |
46 | manifest.insert(manifest_key.to_string(), manifest_entry);
47 | });
48 | // done parsing manifest
49 | }
50 | _ => {
51 | panic!("invalid vite manifest (or perhaps the vite-rs parser isn't up-to-date!)");
52 | }
53 | }
54 |
55 | manifest
56 | }
57 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | pull_request:
4 | push:
5 | branches:
6 | - main
7 | jobs:
8 | format:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions-rs/toolchain@v1
12 | with:
13 | toolchain: stable
14 | - uses: actions/checkout@master
15 | - run: rustup component add rustfmt
16 | - run: cargo fmt --all -- --check
17 | test:
18 | runs-on: ${{ matrix.os }}
19 | continue-on-error: ${{ matrix.experimental }}
20 | strategy:
21 | fail-fast: false
22 | matrix:
23 | os: [ubuntu-latest, macOS-latest] # todo: add 'windows-latest'
24 | rust: [stable]
25 | experimental: [false]
26 | # Note: We're no longer reliant on nightly, so we can remove this.
27 | # Keeping it here for future reference.
28 | #
29 | # # include:
30 | # # # Test on stable -- we expect this to fail, but we want to know when it starts working!
31 | # # - rust: stable
32 | # # os: ubuntu-latest
33 | # # experimental: true
34 | steps:
35 | - uses: actions-rs/toolchain@v1
36 | with:
37 | toolchain: ${{ matrix.rust }}
38 | - uses: actions/checkout@master
39 | - name: Install npm packages for examples & tests
40 | run: |
41 | (cd ./crates/vite-rs/test_projects && npm ci)
42 | (cd ./crates/vite-rs-axum-0-8/test_projects/basic_usage_test/app && npm ci)
43 | (cd ./crates/vite-rs-axum-0-8/test_projects/ctrl_c_handling_test/app && npm ci)
44 | (cd ./crates/vite-rs-axum-0-8/examples/basic_usage/app && npm ci)
45 | (cd ./crates/vite-rs/examples/vite-project-folder && npm ci)
46 | - name: Run tests # note: this step also compiles examples, but does not run them.
47 | run: |
48 | # VITE-RS
49 | cargo test -p vite-rs
50 | cargo test -p vite-rs --release
51 |
52 | # AXUM
53 | cargo test -p vite-rs-axum-0-8
54 | cargo test -p vite-rs-axum-0-8 --release
55 | - name: Run/compile examples
56 | run: |
57 | # VITE-RS
58 | cargo run -p vite-rs --example basic_usage
59 | cargo run -p vite-rs --example basic_usage --release
60 | cargo run -p vite-rs --example custom_ctrl_c_handler
61 | cargo run -p vite-rs --example custom_ctrl_c_handler --release
62 |
63 | # AXUM
64 | (cd ./crates/vite-rs-axum-0-8/examples/basic_usage && cargo build)
65 | (cd ./crates/vite-rs-axum-0-8/examples/basic_usage && cargo build --release)
66 |
--------------------------------------------------------------------------------
/crates/vite-rs/examples/custom_ctrl_c_handler.rs:
--------------------------------------------------------------------------------
1 | use vite_rs::Embed;
2 |
3 | #[derive(Embed)]
4 | #[root = "./examples/vite-project-folder"]
5 | struct Assets;
6 |
7 | fn main() {
8 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
9 | // We use an RAII guard to gracefully exit the dev server
10 | let _guard = Assets::start_dev_server(false);
11 |
12 | ctrlc::try_set_handler(|| {
13 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
14 | Assets::stop_dev_server();
15 | std::process::exit(0);
16 | })
17 | .unwrap();
18 |
19 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
20 | {
21 | println!("Waiting for the dev server to start (2 second)");
22 | std::thread::sleep(std::time::Duration::from_secs(2));
23 | }
24 |
25 | let file = Assets::get("app/index.html").unwrap();
26 | let file_content = std::str::from_utf8(&file.bytes).unwrap();
27 |
28 | println!("Reading index.html:");
29 | println!("{}", file_content);
30 |
31 | #[cfg(all(debug_assertions, not(feature = "debug-prod")))]
32 | assert_eq!(
33 | strip_space(file_content),
34 | strip_space(
35 | r#"
36 |
37 |
38 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | vite-rs
53 |
54 |
55 |
56 |
57 |
58 | "#
59 | )
60 | );
61 |
62 | #[cfg(any(not(debug_assertions), feature = "debug-prod"))]
63 | assert_eq!(
64 | strip_space(file_content),
65 | strip_space(
66 | "\n\n\n\n\n\nvite-rs\n\n\n\n\n\n\n