# JavaScript trên trình duyệt

> Cài @belvador/browser cho website hoặc ứng dụng chạy trên trình duyệt không dùng React.

Dùng `@belvador/browser` cho JavaScript chạy trên trình duyệt mà không dùng React — TypeScript thuần, website build bằng Vite, một widget. Với React dùng [React](https://belvador.dev/vi/docs/sdk/react); với Lovable hoặc TanStack Start dùng [TanStack Start](https://belvador.dev/vi/docs/sdk/tanstack-start).

## Trước khi bắt đầu

- Một project có nền tảng **JavaScript (trình duyệt)** và DSN của nó — xem [Project và DSN](https://belvador.dev/vi/docs/projects-and-dsn).
- Một công cụ build xử lý được ES module (Vite, esbuild, Rollup, webpack 5).

## 1. Cài đặt

```bash
npm install @belvador/browser@0.6.1
```

## 2. Khởi tạo

Đặt `init` trong file riêng, `src/instrument.ts`:

```ts title="src/instrument.ts"
import { init } from "@belvador/browser";

init({
  dsn: "https://<public-key>@ingest.belvador.dev/<project-id>",
  release: import.meta.env.VITE_APP_VERSION, // your build or commit id
  environment: import.meta.env.MODE,
});
```

Sau đó đặt nó là dòng import **đầu tiên** của file entry. Các import chạy trước phần còn lại của file, nên một lệnh `init` viết bên dưới các import khác sẽ không bao giờ chạy nếu một module trong đó lỗi lúc đang nạp — ví dụ thiếu biến môi trường — và lỗi đó không bao giờ được báo.

```ts title="src/main.ts"
import "./instrument"; // first line: starts Belvador before your app's modules load

// …the rest of your imports and start-up code
```

- `release` là phiên bản **ứng dụng của bạn**, ví dụ số build hoặc mã commit; nhờ đó Belvador biết lỗi đến từ lần triển khai nào và khớp được [source map](https://belvador.dev/vi/docs/source-maps). Đặt `VITE_APP_VERSION` trong bước build, hoặc truyền một chuỗi bất kỳ.
- `environment` tách production khỏi staging. Bỏ trống thì mặc định là `production`.

`init` trả về `true` khi theo dõi lỗi đang chạy. Hàm không bao giờ ném lỗi: DSN sai chỉ ghi một cảnh báo trong console và để SDK ở trạng thái tắt. Gọi `init` lần nữa với cùng DSN thì không có tác dụng gì.

## 3. Cho phép địa chỉ nhận lỗi trong CSP

Nếu website gửi header `Content-Security-Policy`, thêm origin nhận lỗi vào `connect-src`. Gộp vào chính sách hiện có — đừng thay cả chính sách:

```text
connect-src 'self' https://ingest.belvador.dev;
```

Thiếu dòng này, trình duyệt chặn request và lỗi không bao giờ tới.

## Những gì được bắt

Ngay sau khi `init` chạy:

- **lỗi chưa bắt** (`window.onerror`) và
- **promise bị từ chối mà không ai xử lý**.

Lỗi từ tiện ích trình duyệt (extension) bị bỏ qua. Breadcrumb từ console, click, `fetch`, XHR và điều hướng mặc định **tắt**; bật bằng tuỳ chọn `instrument` ([Tuỳ chọn SDK](https://belvador.dev/vi/docs/sdk/configuration#breadcrumb)).

Các framework tự bắt lỗi (ví dụ `app.config.errorHandler` của Vue hay `ErrorHandler` của Angular) giữ các lỗi đó lại, không tới `window.onerror`. Gọi `captureException` từ hook đó để báo.

## Báo những lỗi bạn đã xử lý

Khi code của bạn bắt lỗi và tự phục hồi, SDK không thấy lỗi đó. Hãy tự báo nếu vẫn muốn biết:

```ts
import { captureException } from "@belvador/browser";

async function saveOrder(order: Order) {
  try {
    await api.post("/orders", order);
  } catch (error) {
    captureException(error, { tags: { feature: "checkout" } });
    showToast("Chưa lưu được đơn hàng. Vui lòng thử lại.");
  }
}
```

`captureException` trả về một event ID. ID này được tạo trong ứng dụng; nó không chứng minh event đã tới node.

## Thêm ngữ cảnh

```ts
import { setContext, setTag, setUser } from "@belvador/browser";

setUser({ id: account.id }); // chỉ giữ id
setTag("plan", account.plan);
setContext("cart", { items: cart.length });
```

Đừng đặt email, tên hay token vào tag hoặc ngữ cảnh: mọi người trong workspace đều thấy. SDK che các mẫu bí mật thường gặp, nhưng đó là lưới an toàn, không phải bộ lọc để dựa vào — xem [Bảo vệ dữ liệu](https://belvador.dev/vi/docs/privacy).

## Kiểm tra

1. Triển khai hoặc chạy ứng dụng với phần cài đặt ở trên.
2. Tạo một lỗi thử, ví dụ từ một nút bấm:

```ts
setTimeout(() => {
  throw new Error("Belvador browser test");
}, 0);
```

3. Mở project trong Belvador: issue hiện sau vài giây. Nếu không, mở tab Network của trình duyệt và tìm request `POST` tới `https://ingest.belvador.dev/api/…/envelope/` — [Khắc phục sự cố](https://belvador.dev/vi/docs/troubleshooting) giải thích từng mã trạng thái.

## Giới hạn cần biết

- Lỗi từ script ở tên miền khác hiện là `Script error.` không có chi tiết, trừ khi script đó được phục vụ kèm header CORS và tải với `crossorigin="anonymous"` — đây là quy tắc của trình duyệt, không phải của Belvador.
- Event chỉ chờ trong bộ nhớ. Nếu trang bị đóng trước khi gửi xong, event bị mất.
- Stack trace của code đã thu nhỏ cần [source map](https://belvador.dev/vi/docs/source-maps) để hiện đúng file và dòng gốc.
