Hermes — nó là gì, công cụ JS cho React Native và nguyên lý hoạt động

Tác giả: IT Sectr Đã đăng: 2026-07-06 Thời gian đọc: 9 phút

Hermes là một công cụ JavaScript với biên dịch AOT (Ahead-of-Time), được Meta phát triển cho React Native và tối ưu hóa cho các thiết bị di động có bộ nhớ hạn chế. Theo blog chính thức của Meta Engineering (2022), Hermes giảm thời gian khởi động ứng dụng 20-50% và giảm kích thước bundle 30-40% so với JavaScriptCore. Không giống như V8 hay JSC, Hermes không sử dụng biên dịch JIT trên thiết bị — toàn bộ JavaScript được biên dịch thành bytecode ở giai đoạn xây dựng thông qua Hermes CLI. Điều này đặc biệt quan trọng đối với iOS, nơi biên dịch JIT bị hạn chế bởi chính sách App Store.

Những điểm chính

  • Hermes — công cụ JavaScript với biên dịch AOT, được Meta phát triển cho React Native
  • AOT vs JIT — Hermes biên dịch JS thành bytecode khi xây dựng, không cần JIT trên thiết bị
  • Hiệu suất — khởi động ứng dụng nhanh hơn 20-50%, bundle nhỏ hơn 30-40%
  • Hades GC — bộ thu gom rác có độ trễ thấp, tối ưu cho các kịch bản di động
  • Tiêu chuẩn — ECMAScript 2020+ không hỗ trợ đầy đủ Proxy, BigInt và Reflect

Hermes là gì

Hermes là một công cụ JavaScript mã nguồn mở nhỏ gọn (giấy phép MIT) được Meta tạo ra cho React Native và tối ưu hóa để chạy trên các thiết bị di động có tài nguyên hạn chế. Cải tiến chính của Hermes là từ bỏ biên dịch JIT để chuyển sang AOT (Ahead-of-Time). Trong giai đoạn xây dựng ứng dụng React Native, Metro Bundler chuyển JavaScript đã biên dịch đến Hermes CLI, công cụ này chuyển đổi nó thành bytecode HBC (Hermes ByteCode). Bytecode này được thực thi trực tiếp bởi công cụ mà không cần biên dịch thêm trên thiết bị. Cách tiếp cận này mang lại hiệu suất có thể dự đoán được: không cần làm nóng JIT, không có tạm dừng biên dịch, không tiêu thụ pin thêm. Hermes được thiết kế có tính đến các hạn chế của thiết bị di động: RAM nhỏ (1-4 GB), tiêu thụ điện năng hạn chế và nhu cầu khởi động nguội nhanh. Bản phát hành công khai đầu tiên của Hermes là vào năm 2019 và bắt đầu từ React Native 0.70 (2022), công cụ này đã trở thành tiêu chuẩn trên Android.

Hermes vs JavaScriptCore: so sánh công cụ

JavaScriptCore (JSC) là công cụ WebKit tiêu chuẩn được sử dụng bởi Safari và React Native trước phiên bản 0.70. JSC hỗ trợ biên dịch JIT, mang lại hiệu suất cao cho các hoạt động JavaScript phức tạp. Tuy nhiên, JIT yêu cầu làm nóng: những giây đầu tiên thực thi chậm hơn (chế độ thông dịch), sau đó JIT biên dịch các đường dẫn nóng. Trên iOS, JIT thực tế không khả dụng do chính sách App Store (cấm tạo mã động), vì vậy JSC trên iOS chỉ hoạt động ở chế độ thông dịch — hiệu suất giảm. JSC có kích thước nhị phân lớn hơn (khoảng 10 MB) và tiêu thụ nhiều RAM hơn do cơ sở hạ tầng JIT. Hermes không phụ thuộc vào JIT, cung cấp hiệu suất có thể dự đoán ngay sau khi khởi động (khởi động nguội). JSC hỗ trợ tiêu chuẩn ECMAScript đầy đủ hơn (bao gồm Proxy, BigInt, Reflect), nhưng với chi phí tiêu thụ tài nguyên cao hơn. Đối với các dự án React Native nơi khởi động nguội và kích thước nhỏ là quan trọng — Hermes được ưu tiên hơn. Đối với các dự án có tính toán JS nặng (trò chơi, WebGL) — JSC có thể cung cấp hiệu suất đỉnh cao hơn.

Tham sốHermesJavaScriptCore
Biên dịchAOT (khi xây dựng)JIT + Thông dịch (trên thiết bị)
Khởi động nguộiNhanh hơn 20-50%Mức cơ bản
Kích thước bundleNhỏ hơn 30-40%Mức cơ bản
Tiêu thụ RAMÍt hơn 20-30%Mức cơ bản
ECMAScriptES2020 (hạn chế)ES2022+ (đầy đủ)
JIT trên iOSKhông yêu cầuKhông khả dụng (chỉ thông dịch)
Nhị phân~3 MB~10 MB

Biên dịch AOT: cách hoạt động của biên dịch trước

Biên dịch AOT (Ahead-of-Time) trong Hermes diễn ra qua hai giai đoạn. Ở giai đoạn đầu, Metro Bundler thu thập các tệp JavaScript thành một bundle duy nhất và chuyển nó đến Hermes CLI (tiện ích hermesc). Ở giai đoạn thứ hai, hermesc phân tích cú pháp AST JavaScript, tạo ra biểu diễn trung gian HIR (Hermes Intermediate Representation) và sau đó phát ra bytecode HBC nhị phân. Kết quả là một tệp .hbc chỉ chứa bytecode mà không có JavaScript gốc. Môi trường thực thi Hermes tải HBC trực tiếp, không cần phân tích và biên dịch. Điều này tăng tốc khởi động một cách triệt để: thay vì phân tích hàng nghìn dòng JS (bất đồng bộ), công cụ đọc một định dạng nhị phân đã được biên dịch trước. AOT cũng giảm kích thước: bytecode nhỏ gọn hơn trung bình 30% so với AST JavaScript. Nhược điểm của AOT — không thể thực thi eval, new Function hoặc require động trong thời gian chạy — tất cả các mô-đun phải được biết tại thời điểm xây dựng.

bash
# Cài đặt Hermes CLI độc lập
npm install hermes-engine

# Biên dịch JS sang bytecode HBC
npx hermesc -emit-binary -out bundle.hbc bundle.js

# Thống kê bytecode
npx hermesc -dump-bytecode bundle.hbc  # shows HBC instructions

# Kích thước JS gốc so với HBC
wc -c bundle.js      # 2,300,000 bytes
wc -c bundle.hbc     # 1,450,000 bytes (37% reduction)

Chỉ số hiệu suất của Hermes

Hiệu suất của Hermes được đo bằng ba chỉ số chính: Time-To-Interactive (TTI), kích thước APK/IPA và tiêu thụ RAM. Theo dữ liệu của Meta, trên Android Hermes giảm TTI 34% so với JSC: từ 4,2 giây xuống 2,8 giây trên thiết bị tầm trung (Moto G7). Kích thước APK giảm 28% nhờ bytecode nhỏ gọn và không có thư viện JIT. Tiêu thụ RAM trung bình thấp hơn 22% ở cùng tải — điều này đặc biệt quan trọng đối với các thiết bị có 2-3 GB RAM. Trên iOS, lợi ích còn đáng kể hơn: vì JSC không thể sử dụng JIT, Hermes cải thiện TTI lên đến 45%. Các chỉ số dựa trên thử nghiệm của Meta với ứng dụng Facebook Lite. Trong các dự án thực tế, lợi ích khác nhau: đối với màn hình đơn giản (danh sách, văn bản) Hermes cải thiện nhiều hơn, đối với hoạt ảnh nặng — ít hơn. Công cụ phân tích: React Native Profiler + hermes profile --heap.

Phân tích bộ nhớ với Hermes

Hermes bao gồm một công cụ phân tích bộ nhớ tích hợp có thể truy cập qua Chrome DevTools. Kết nối với ứng dụng qua Metro, mở tab Bộ nhớ và chọn Hermes (JavaScript) trong các loại ảnh chụp nhanh. Hermes hỗ trợ ba loại ảnh chụp nhanh: Heap Snapshot (tất cả đối tượng), Allocation Timeline (vòng đời đối tượng) và Allocation Sampling (hồ sơ mẫu). Hades GC giảm thiểu các lần tạm dừng GC — trung bình một lần tạm dừng 2-5ms trong 10 giây hoạt động, so với các lần tạm dừng 10-20ms của JSC trong cùng khoảng thời gian.

Bộ thu gom rác Hades GC

Hades GC là bộ thu gom rác trong Hermes, được thiết kế cho các kịch bản di động với thời gian tạm dừng tối thiểu. Không giống như GC mark-sweep trong JSC, Hades sử dụng thu gom đồng thời (concurrent): bộ thu gom hoạt động song song với luồng thực thi chính, chỉ dừng nó trong những khoảng ngắn. Hades GC chia heap thành các thế hệ: thế hệ trẻ (nursery) được thu gom thường xuyên và nhanh chóng (Scavenge), thế hệ già được thu gom ít thường xuyên hơn với thời gian tạm dừng ngắn hơn. Kích thước heap có thể cấu hình: mặc định — 2/3 RAM khả dụng của ứng dụng, ngưỡng tối thiểu — 32 MB. Hades không sử dụng phương pháp stop-the-world: ngay cả việc thu gom hoàn toàn thế hệ già cũng không mất quá 5-8ms. Bộ thu gom được tối ưu cho các kịch bản di động điển hình: nhiều đối tượng tồn tại ngắn (chuỗi tạm thời, đối tượng React fiber), ít đối tượng tồn tại lâu. Đối với các ứng dụng có tạo đối tượng nhiều (danh sách, hoạt ảnh), Hades cung cấp FPS mượt mà hơn so với JSC.

Cách kích hoạt Hermes trong dự án React Native

Việc kích hoạt Hermes phụ thuộc vào phiên bản React Native và nền tảng. Bắt đầu từ React Native 0.70, Hermes được kích hoạt mặc định cho Android trong các dự án mới. Đối với iOS, Hermes là tùy chọn. Để kích hoạt trên Android: trong tệp android/app/build.gradle đặt enableHermes: true trong khối project.ext.react.enableHermes. Đối với iOS: đặt hermes_enabled thành true trong Podfile qua use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true). Sau khi kích hoạt, chạy pod install. Đối với các dự án hiện có, hãy kiểm tra tính tương thích của thư viện: Hermes không hỗ trợ Proxy, eval và một số tính năng ES2021. Sử dụng npx react-native info để kiểm tra cấu hình. Để chuyển đổi giữa Hermes và JSC, thay đổi cờ và thực hiện xây dựng lại sạch.

groovy
// android/app/build.gradle — kích hoạt Hermes
project.ext.react = [
    enableHermes: true,
    cliPath: "node_modules/react-native/cli.js"
]

// iOS/Podfile — kích hoạt Hermes trên iOS
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'MyApp' do
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => true
  )
end

Hạn chế của Hermes: những gì không được hỗ trợ

Các hạn chế chính của Hermes liên quan đến việc thiếu JIT. Hermes không hỗ trợ: ProxyReflect API (được sử dụng trong MobX, Vue, một số trình quản lý trạng thái), BigInt (số lớn), Symbol.toStringTag, WeakRefFinalizationRegistry. Các hàm eval và new Function tạo ra ngoại lệ trong thời gian chạy. Callback của các phương thức Array.prototype.flatflatMap với đối số this hoạt động có giới hạn. Định dạng ngày ISO 8601 với múi giờ không được xử lý hoàn toàn. Hầu hết các hạn chế này không ảnh hưởng đến các ứng dụng React Native điển hình: React và React Native sử dụng một tập hợp giới hạn các tính năng ES. Nếu một thư viện yêu cầu Proxy (ví dụ: MobX 6+ với Proxy), hãy sử dụng configure({ useProxies: false }) hoặc chọn giải pháp thay thế. Để kiểm tra tính tương thích của mã hiện có, hãy chạy npx hermesc -check trên bundle của bạn — nó sẽ hiển thị danh sách các tính năng không được hỗ trợ.

  • Proxy / Reflect — chưa được triển khai; thư viện yêu cầu Proxy cần chế độ dự phòng
  • BigInt — không khả dụng; sử dụng thư viện bignumber.js cho số lớn
  • eval / new Function — ném ngoại lệ khi gọi; tất cả mô-đun phải tĩnh
  • WeakRef / FinalizationRegistry — không được hỗ trợ; không có giải pháp thay thế
  • Symbol.toStringTag — bị bỏ qua; instanceof hoạt động chính xác

Câu hỏi thường gặp

Cách kiểm tra ứng dụng có đang chạy trên Hermes không?

Trong bảng điều khiển ứng dụng, chạy console.log(global.HermesInternal). Nếu đối tượng HermesInternal tồn tại — ứng dụng đang chạy trên Hermes. Cách khác: console.log(global.HermesInternal?.getRuntimeProperties()) — sẽ hiển thị phiên bản công cụ và tham số GC. Trong các bản dựng Release, HermesInternal có thể không khả dụng để giảm thiểu kích thước.

Tại sao ứng dụng bị crash trên iOS sau khi kích hoạt Hermes?

Kiểm tra cài đặt Podfile của bạn: Hermes trên iOS yêu cầu New Architecture (Fabric Renderer). Đặt :hermes_enabled => true, chạy pod install --repo-update. Nếu dự án đang nâng cấp từ React Native dưới 0.70, hãy kiểm tra tính tương thích của thư viện với New Architecture. Tắt Hermes nếu thư viện bên thứ ba yêu cầu JSC — thay đổi cờ thành false và cài đặt lại Pods.

Hermes có ảnh hưởng đến Hot Reload trong quá trình phát triển không?

Không, Hermes không ảnh hưởng đến Hot Reload / Fast Refresh. Trong quá trình phát triển, Metro chạy bundle JavaScript mà không cần biên dịch Hermes (JS thuần). Bytecode Hermes chỉ được biên dịch cho các bản dựng Release. Ở chế độ Gỡ lỗi, JavaScriptCore tiêu chuẩn hoặc Hermes ở chế độ thông dịch được sử dụng. Tốc độ Hot Reload không thay đổi khi Hermes được kích hoạt trong cấu hình — việc chuyển đổi chỉ xảy ra ở giai đoạn xây dựng sản xuất.

Có thể sử dụng Hermes với Expo không?

, bắt đầu từ Expo SDK 45, Hermes được hỗ trợ cho quy trình quản lý (managed workflow). Trong app.json chỉ định "jsEngine": "hermes". Đối với quy trình trần (bare workflow), Hermes hoạt động như trong dự án React Native thông thường. Expo Go không hỗ trợ Hermes — sử dụng Expo Dev Client hoặc EAS Build cho các bản dựng với Hermes. Kiểm tra tính tương thích của thư viện qua expo doctor.

Làm thế nào để so sánh hiệu suất của Hermes và JSC trong dự án của tôi?

Sử dụng React Native Performance Monitor (chỉ số FPS) và Hermes Profiling Tools. Xây dựng hai phiên bản ứng dụng — với Hermes và JSC — trên cùng một thiết bị. Đo: khởi động nguội (từ khi chạm biểu tượng đến màn hình tương tác đầu tiên), TTI (Time-To-Interactive), kích thước APK/IPA và tiêu thụ RAM tối đa. Chạy thử nghiệm ít nhất 3 lần cho mỗi cấu hình. Lợi thế điển hình của Hermes: khởi động nhanh hơn 20-40%, RAM ít hơn 15-25%.

Tổng kết

  • Hermes — công cụ JavaScript của Meta với biên dịch AOT cho React Native, tiêu chuẩn trên Android từ 0.70
  • Biên dịch AOT cung cấp hiệu suất có thể dự đoán mà không cần làm nóng JIT trên thiết bị
  • Khởi động nguội nhanh hơn 20-50%, kích thước bundle nhỏ hơn 30-40% so với JavaScriptCore
  • Hades GC — bộ thu gom rác đồng thời với thời gian tạm dừng 2-5ms thay vì 10-20ms của JSC
  • Hạn chế: Proxy, BigInt, eval, WeakRef không được hỗ trợ — kiểm tra thư viện của bạn
  • Kích hoạt: enableHermes trong build.gradle (Android) hoặc hermes_enabled trong Podfile (iOS)
  • Hermes CLI cho phép biên dịch bytecode .hbc và phân tích bộ nhớ qua DevTools
  • Hermes không ảnh hưởng đến Hot Reload trong phát triển — bytecode chỉ được biên dịch cho Release

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm