Performance Improvements in Interactive Web Maps Using WebAssembly
In today's web landscape, a seamless user experience reigns supreme. Single-Page Applications (SPAs) constantly push the boundaries of browser capabilities. However, with growing data complexity and user interactions, traditional JavaScript code can sometimes struggle to keep up. This is where WebAssembly (WASM) steps in, offering a powerful tool to enhance frontend performance.
This blog explores our experience using WASM with a React application to significantly improve the performance of a map component built with React Leaflet.
About the Use Case
As part of a grid monitoring use case, we have integrated a map that displays various grid elements using React Leaflet. The map includes the following components:
In addition to the above, users can view detailed information about Substations and Transformers. We implemented these features to provide a smooth and responsive user experience.
What is WASM and How Does It Enhance Frontend Performance?
Think of WASM as a way to inject a shot of speed into your web app. It allows you to write the most demanding parts of your code in a super-fast language like C++. This C++ code then gets compiled into WASM modules that the browser can understand and execute nearly as fast as native code on the user's machine.
Here's how WASM brings the power to the app:
WASM and SQLite: Boosting Performance Together
We didn't just use WASM by itself in our use case. We combined WASM with SQLite, a strong database system, to enhance the rendering of the React Leaflet map and unlock additional benefits for the application:
Recommended by LinkedIn
Implementing WASM in Our React Application
Let's see how WASM can be applied to a practical scenario: a grid monitoring use case built with React Leaflet, a popular JavaScript library for interactive maps.
Makefile
# Compiler
CXX = emcc
# Flags
CXXFLAGS = -O3 -gsource-map
# Directories
SRC_DIR = cpp
OBJ_DIR = obj
OUTPUT_DIR = public/wasm
# Source files
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS))
# Output files
MODULE_NAME = ${SRC_DIR}/BrtWasm.cpp
OUTPUT_JS = $(OUTPUT_DIR)/wasm-module.js
OUTPUT_WASM = $(OUTPUT_DIR)/wasm-module.wasm
EXPORT_NAME = BrtWasm
# Targets
all: $(OUTPUT_JS)
$(OUTPUT_JS): $(OBJS)
$(CXX) --bind $(OBJS) $(MODULE_NAME) -o $(OUTPUT_JS) -O3 -gsource-map -s FETCH=1 -s WASM=1 -s USE_SQLITE3=1 -s "EXPORTED_RUNTIME_METHODS=['ccall']" -s NO_EXIT_RUNTIME=1 -s ASSERTIONS=1 -s AGGRESSIVE_VARIABLE_ELIMINATION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 --profiling -s 'EXPORT_NAME="$(EXPORT_NAME)"' -s 'ENVIRONMENT="web"' -s FORCE_FILESYSTEM=1
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@mkdir -p $(OBJ_DIR)
$(CXX) -c $< -o $@ $(CXXFLAGS) -I$(SRC_DIR)
clean:
rm -rf $(OBJ_DIR) $(OUTPUT_JS) $(OUTPUT_WASM)
.PHONY: all clean
let brtWasmModuleInstance = null;
const initializeBrtWasm = async () => {
if (!brtWasmModuleInstance) {
try {
brtWasmModuleInstance = await import("../wasm/wasm-module");
console.log("Module created!");
} catch (error) {
console.error("Error initializing BrtWasm module:", error);
throw error;
}
}
return brtWasmModuleInstance;
};
Advantages of WASM Integration: Enhancing Grid Monitoring Use Case Performance
By integrating WASM, our use case experiences several significant improvements:
Conclusion
WASM offers a powerful solution to overcome performance limitations in web applications, particularly those dealing with large datasets or complex calculations. By leveraging WASM's capabilities, you can significantly enhance the performance and user experience of your web applications.
We hope our experience inspires you to consider WASM for your frontend performance needs. If you have any questions or would like to share your experiences, feel free to leave a comment below. Happy coding!
Very informative
Good to know!