jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Vite · Part 11 — Library Mode + SSR & the Environment API

Build publishable libraries with Vite (lib mode, ESM + CJS, .d.ts types, externalized peer deps, the exports map) and understand SSR plus the Environment API — the multi-runtime build model. With a library & environments explorer.

4 MIN READ

Vite không chỉ cho app. Hai cách dùng nâng cao hoàn thiện sự thành thạo: xây thư viện publish được, và hiểu SSR cùng Environment API mới làm động lực cho meta-framework hiện đại.

Khám phá định dạng output thư viện, rồi mô hình SSR đa-môi-trường:


1. Library mode

Build app giả định entry index.html và output cho trình duyệt. Một thư viện thì khác — bạn ship module import được cho dự án khác dùng. Bật bằng build.lib:

export default defineConfig({
  build: {
    lib: {
      entry: "src/index.ts",
      name: "MyLib", // for the UMD/IIFE global
      formats: ["es", "cjs"], // which module formats to emit
    },
    rollupOptions: {
      external: ["react", "react-dom"], // don't bundle peer deps
    },
  },
});

2. Ship ESM CJS

Chọn định dạng output theo ai dùng thư viện:

FormatNgười dùng
es (.mjs)bundler hiện đại, ESM native
cjs (.cjs)tooling Node cũ, require()
umd/iifeglobal qua thẻ <script>

Ship cả escjs tối đa tương thích. Nối chúng trong package.json bằng exports map để mỗi người dùng nhận file đúng:

{
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/my-lib.mjs",
      "require": "./dist/my-lib.cjs"
    }
  }
}

3. Sinh type

Vite/Oxc bóc type — nó không tự phát file .d.ts. Cho thư viện TypeScript, thêm vite-plugin-dts:

import dts from "vite-plugin-dts";

export default defineConfig({
  plugins: [dts()], // emits dist/index.d.ts
});

Không có .d.ts, người dùng TypeScript không có autocomplete và type-check — điều cấm kỵ cho thư viện publish.


4. Externalize peer dependency

Đây là lỗi làm hỏng thư viện: bundle React (hay peer dep nào) vào thư viện. Nếu làm vậy, app dùng sẽ có hai bản React — hook hỏng, bundle phình.

rollupOptions: {
  external: ["react", "react-dom"], // leave them for the consumer
}
// package.json — declare them as peers, not deps
{ "peerDependencies": { "react": "^18 || ^19" } }

Externalize peer dep, khai báo trong peerDependencies, và React duy nhất của người dùng là cái duy nhất trong app cuối.


5. SSR tóm tắt

SSR chạy app trên server để tạo HTML, rồi client hydrate nó. Vite hỗ trợ SSR dev native — nó biến đổi server entry qua cùng pipeline:

// dev server: load the server entry through Vite's transform
const { render } = await server.ssrLoadModule("/src/entry-server.tsx");
const appHtml = await render(url);

Bạn thường build hai output: bundle client (để hydrate) và bundle server (để render). Thực tế bạn hiếm khi tự nối — meta-framework lo.


6. Environment API

Vite cũ gắn SSR như một API riêng, vụng về. Environment API (giới thiệu ở Vite 6, ổn định dần qua 7/8) biến client, SSR, và edge thành ngang hàng hạng nhất. Mỗi environment có riêng:

  • đồ thị module
  • container plugin
  • trình tối ưu dependency
  • config (externals, resolve, v.v.)
export default defineConfig({
  environments: {
    client: {
      /* browser build */
    },
    ssr: {
      resolve: { external: ["express"] },
    },
  },
});

Một vite build có thể tạo output phối hợp cho tất cả. Module Runner thực thi code SSR/edge với HMR khi dev.

Đa số dev app dùng Environment API qua một framework. Bạn chỉ chạm trực tiếp khi viết framework hoặc tích hợp runtime.


7. Bài tập

1. Bạn publish thư viện component React và người dùng báo “Invalid hook call” với hai bản React. Bạn quên gì?

Lời giải

Externalize React và khai báo trong peerDependencies để thư viện không bundle bản riêng.

2. Thư viện TS của bạn build ổn nhưng người dùng không có autocomplete. Build thiếu gì?

Lời giải

Khai báo type .d.ts — thêm vite-plugin-dts và trỏ types/exports.types tới chúng.

3. Một câu, Environment API giải quyết vấn đề gì so với thiết lập SSR cũ?

Lời giải

Nó biến client/SSR/edge thành môi trường hạng nhất, cấu hình độc lập, phối hợp bởi một build, thay vì SSR là trường hợp đặc biệt gắn thêm.

Nâng cao:trong explorer, tắt “externalize peer deps” và đọc cảnh báo — đó chính là nguyên nhân bug React đôi.


Điểm chính

  • build.lib biến Vite thành bundler thư viện — phát es + cjs và nối exports map.
  • Sinh .d.ts bằng vite-plugin-dts cho người dùng TypeScript.
  • Externalize peer dep và khai báo peerDependencies — tránh bản đôi.
  • SSR render trên server + hydrate trên client; Vite hỗ trợ native.
  • Environment API biến client/SSR/edge thành môi trường hạng nhất — thường truy cập qua framework.

Tiếp theo

Phần 12 — Hiệu năng, capstone & di trú: tăng tốc dev và build, một config capstone thực chiến, và hướng dẫn thực tế di trú từ Webpack hoặc CRA sang Vite.