apollo-rust-client 0.7.0

A Rust client for Apollo configuration center
Documentation
[中文简体]../zh-CN/Design-WASM.md | [中文繁體]../zh-TW/Design-WASM.md
[Back to Home](Home.md)

# WASM Design Considerations

The `apollo-rust-client` is designed to work seamlessly in WebAssembly (WASM) environments, primarily targeting browsers and Node.js. This requires specific design choices and adaptations due to the nature of WASM and its interaction with JavaScript.

## `cfg_if!` and Conditional Compilation

The `cfg_if!` macro is extensively used throughout the codebase to manage platform-specific logic. This allows the library to have a single codebase that can compile differently for `wasm32` targets versus native targets.

Key areas where conditional compilation is applied:

-   **Task Spawning:**
    -   Native: `tokio::spawn` is used to run the background refresh task.
    -   WASM: `wasm_bindgen_futures::spawn_local` is used, as WASM environments (especially browsers) are single-threaded.

-   **`Namespace` Return Type in `Client::namespace()`:**
    -   Native: Returns strongly typed `Namespace` enum to Rust code.
    -   WASM: Returns a `JsValue` wrapping the mapped format (like `Properties` class or raw JSON/YAML objects) directly. The JavaScript bindings generated by `wasm-bindgen` handle the object's lifecycle on the JS side.

-   **`ClientConfig` Constructor:**
    -   Native: Offers `ClientConfig::from_env()` for server-side convenience.
    -   WASM: Exposes a specific `ClientConfig::new(app_id, config_server, cluster)` constructor to JavaScript, as environment variables are not typically used in browser WASM, and file system caching is disabled.

-   **File System Caching:**
    -   All file I/O operations related to caching configuration on disk are conditionally compiled out for WASM targets. The `cache_dir` field in `ClientConfig` and `file_path` in `Cache` are effectively unused in WASM. Instead, browser WASM targets support persistent `localStorage` caching under the key `apollo_cache_{app_id}_{cluster}_{namespace}`.

## `wasm-bindgen`

The `wasm-bindgen` tool and attributes are crucial for creating the JavaScript interface for the library.

-   **`#[wasm_bindgen]`**: This attribute is used on structs (`ClientConfig`, `Client`, `Cache`) and their methods to make them accessible from JavaScript.
    -   For structs, it typically generates JavaScript classes.
    -   For methods, it generates corresponding JavaScript methods on these classes.

-   **`constructor`**:
    -   Specific methods are marked as `#[wasm_bindgen(constructor)]` to serve as constructors when creating objects from JavaScript (e.g., `new ClientConfig(...)`, `new Client(...)`).

-   **Getters and Setters**:
    -   Fields that need to be accessible from JavaScript are often exposed via getter methods (e.g., `#[wasm_bindgen(getter_with_clone)] pub fn app_id(&self) -> String;`) or setter methods if mutable. `getter_with_clone` is used for String fields to return a copy to JavaScript.

-   **Method Exposure**:
    -   Public methods intended for use from JavaScript are marked with `#[wasm_bindgen]`. This includes `Client::namespace()`, `Client::start()`, `Properties::get_string()`, `Properties::get_int()`, etc.

## Memory Management

-   **`free()` Method**:
    -   `wasm-bindgen` generates a `free()` method on the JavaScript side for Rust structs exposed to WASM that are not `Copy` types. It is crucial for JavaScript code to call this `free()` method when the Rust objects (`ClientConfig`, `Client`, `Cache`) are no longer needed.
    -   This releases the memory allocated by Rust on the WebAssembly heap. Failure to do so can lead to memory leaks in the WASM module.
    -   *(Note: The `free()` method itself is not explicitly defined in the Rust code of this library; `wasm-bindgen` provides the necessary bindings and JavaScript glue code for memory deallocation when the JS object is freed.)*

## API Differences

-   **`ClientConfig` Instantiation**: As mentioned, WASM uses a simplified `new ClientConfig(app_id, config_server, cluster)` constructor. Optional fields like `secret`, `label`, and `ip` are set on the instance directly from JavaScript.
-   **WASM properties format delegation**: For properties format namespaces, the returned JS value is an instance of `Properties`, which exposes synchronous methods like `get_string(key: &str) -> Option<String>` and `get_int(key: &str) -> Option<i64>`. These are wrappers around the generic Rust `get_property::<T>()` method, providing direct type conversion for common use cases. Other formats (like JSON) are returned as raw JavaScript objects/values.
-   **Error Handling**: Errors from `async` Rust methods (which return `Result<T, E>`) are typically converted into JavaScript Promises that reject with the error.

## File System

-   While file system-based caching of configurations is entirely disabled for WASM targets, browser environments utilize standard persistent `localStorage` caching to reduce network fetches and improve cold-start times. Serverless or Node.js WASM targets fall back gracefully to in-memory caching.

These design considerations ensure that `apollo-rust-client` can be effectively used in a wide range of JavaScript and WebAssembly applications, providing a consistent core functionality while adapting to the specific constraints and patterns of the WASM environment.