0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

Tự động nạp lại WASM với Zig và Lume

Đăng vào 1 tháng trước

• 4 phút đọc

Giới thiệu

Gần đây, tôi đã dành thời gian nghỉ ngơi để phục hồi sức khỏe, và để trở lại với công việc, tôi đã khởi động một dự án nhỏ mang tên shine. Mục tiêu của dự án là phát triển một ứng dụng đa nền tảng, bao gồm cả di động và web. Mặc dù tôi đã từng làm việc với Flutter và rất thích nó, nhưng hiện tại tôi đang rất hứng thú với Zig, vì vậy tôi muốn thử sức với nó.

Thư viện

Đồ họa

Ban đầu, tôi đã thử nghiệm với Raylib, nhưng nhận thấy rằng nó không hỗ trợ iOS và gặp một số vấn đề với WASM. Sau khi xem xét một số tùy chọn khác, tôi đã quyết định sử dụng Sokolsokol-zig. Mặc dù Sokol có mức độ thấp hơn so với Raylib, nhưng nó có:

  • API hiện đại và sạch sẽ
  • Hỗ trợ di động tốt
  • Hỗ trợ WASM tốt

Giao diện người dùng (UI)

Gần đây, tôi đã làm việc nhiều với dvui, nhưng tiếc rằng nó không hỗ trợ Sokol. Do đó, tôi đã chọn imgui là một lựa chọn tốt hơn, và còn có một dự án mẫu mà tôi có thể bắt đầu.

Ưu tiên WASM

Để giữ mọi thứ đơn giản, tôi quyết định bắt đầu với WASM. Nếu tôi làm cho trang web thân thiện với di động, tôi sẽ xem xét xem nó có cần phiên bản di động hay không. Tôi cũng cần một kho lưu trữ dữ liệu chung và đã cân nhắc đến Supabase, vốn có thư viện JavaScript. Bằng cách sử dụng WASM, tôi có thể dễ dàng gọi các hàm JavaScript để xử lý mà không cần phải viết các cuộc gọi REST từ Zig.

Cấu trúc dự án

Dự án này có phải là một dự án Zig với một thành phần web, hay ngược lại, hoặc thực sự là hai phần độc lập hoạt động cùng nhau. Tôi đã tìm kiếm trên internet để tìm hướng dẫn về cách cấu trúc một dự án Zig+JS đơn giản, nhưng không tìm thấy. Cuối cùng, tôi quyết định giữ cho nó đơn giản:

Copy
- shine/
  - src/ # mã Zig
  - web/ # tất cả các thứ liên quan đến web

Frontend

Sau một chút nghiên cứu, tôi nhận ra rằng tôi sẽ cần một số nội dung hỗ trợ xung quanh shine, vì vậy tôi đã chọn sử dụng Lume. Tôi đã sử dụng chủ đề simple-blog như một mẫu để bắt đầu. Tôi có thể chỉ cần kéo mẫu nhưng tôi muốn có một trang chính tùy chỉnh.

Khi tôi cố gắng thêm một index.md, nó thông báo rằng có hai tệp muốn ghi index.html. Từ những gì tôi tìm thấy, cách dễ nhất để ghi đè trang chính là chỉ cần lấy chủ đề và chỉnh sửa nó - điều này khá đơn giản.

WASM => frontend

Tôi không muốn sao chép file WASM và file JS mỗi khi thực hiện thay đổi, vì vậy tôi đã thêm một số bước vào build.zig ngay sau bước link_step.

zig Copy
// build.zig
// tạo một bước xây dựng gọi linker Emscripten
const link_step = try sokol.emLinkStep(b, .{
    .lib_main = shine,
    .target = opts.mod_main.resolved_target.?,
    .optimize = opts.mod_main.optimize.?,
    .emsdk = dep_emsdk,
    .use_webgl2 = true,
    .use_emmalloc = true,
    .use_filesystem = false,
    .shell_file_path = opts.dep_sokol.path("src/sokol/web/shell.html"),
});
// đính kèm vào mục tiêu mặc định
b.getInstallStep().dependOn(&link_step.step);

// Sao chép shine.js từ đầu ra emscripten mặc định
const js_install = b.addInstallFileWithDir(
    b.path("zig-out/web/shine.js"),
    .{ .custom = "../web/src/static/shine" },
    "shine.js",
);
js_install.step.dependOn(&link_step.step);
b.getInstallStep().dependOn(&js_install.step);

// Sao chép shine.wasm từ đầu ra emscripten mặc định
const wasm_install = b.addInstallFileWithDir(
    b.path("zig-out/web/shine.wasm"),
    .{ .custom = "../web/src/static/shine" },
    "shine.wasm",
);
wasm_install.step.dependOn(&link_step.step);

Những bước này sẽ sao chép WASM và tệp JS sang thư mục static/shine. Tôi muốn đặt tệp JS trong src/js và WASM trong thư mục tĩnh, nhưng tệp JS yêu cầu WASM ở cùng thư mục. Tôi đã thử ghi đè locateFile nhưng không thành công.

html Copy
<!-- index.vto -->
<script>
  window.Module = {
    locateFile: (path, prefix) => {
      if (path.endsWith(".wasm")) {
        return "/static/shine/shine.wasm";
      }
      return prefix + path;
    },
  };
</script>
<script src="/js/shine.js"></script>

Tôi đã có thể để Lume xử lý tệp JavaScript bằng cách thêm nó:

typescript Copy
// _config.ts
site.add("static/shine/shine.js");

Kết luận

Với tất cả những thiết lập này, tôi có thể chạy:

Copy
zig build -Dtarget=wasm32-emscripten --watch

trong một cửa sổ. Lệnh này sẽ xây dựng lại WASM và cung cấp cho Lume bất cứ khi nào mã Zig thay đổi.

Copy
deno task serve

Chạy lệnh này trong một cửa sổ khác sẽ khiến Lume xây dựng lại mọi thay đổi, bao gồm cả tệp WASM mới và triển khai lại. Việc triển khai lại sẽ kích hoạt tự động làm mới trang nếu tôi mở nó trong trình duyệt.

Giờ đây, tôi đã có khả năng tự động nạp lại với những thay đổi nếu tôi thay đổi trong cả Zig hoặc frontend. Tôi chưa có hot reload - nhưng điều này khá tốt cho hiện tại.

Mẹo và thủ thuật

  • Luôn kiểm tra khả năng tương thích của các thư viện bạn sử dụng với cả nền tảng di động và web.
  • Sử dụng các công cụ xây dựng tự động để tiết kiệm thời gian trong quá trình phát triển.

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

Zig có thể được sử dụng trong dự án web không?

Có, Zig có thể được sử dụng để phát triển ứng dụng web thông qua WASM.

Có nên dùng Sokol cho dự án đồ họa không?

Có, Sokol là một lựa chọn tốt cho việc phát triển đồ họa với hỗ trợ tốt cho WASM và di động.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào