@sbee/vite-federation 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # @sbee/vite-federation
2
+
3
+ Plugin Module Federation cho **Vite 8** (rolldown), tương thích với [Webpack Module Federation](https://webpack.js.org/concepts/module-federation/).
4
+
5
+ - **Zero runtime dependencies** — dùng `RolldownMagicString` và AST walker built-in của Vite/rolldown, không kéo theo `magic-string`, `oxc-parser`, hay `estree-walker`.
6
+ - **Runtime API** — host có thể tải remote động khi chạy mà **không cần** khai báo trước trong `vite.config.ts`.
7
+ - Hỗ trợ định dạng `esm`, `systemjs`, `var`; tương thích remote build bằng cả Vite lẫn Webpack.
8
+
9
+ ## Cài đặt
10
+
11
+ ```bash
12
+ npm install @sbee/vite-federation --save-dev
13
+ ```
14
+
15
+ `vite >= 7` là peer dependency (khuyến nghị Vite 8).
16
+
17
+ ## Sử dụng qua config
18
+
19
+ Module Federation thường cần ít nhất 2 project: một `remote` (bên expose module) và một `host` (bên tiêu thụ module).
20
+
21
+ ### Bước 1: Cấu hình remote
22
+
23
+ ```js
24
+ // vite.config.js — remote
25
+ import federation from '@sbee/vite-federation'
26
+
27
+ export default {
28
+ plugins: [
29
+ federation({
30
+ name: 'remote-app',
31
+ filename: 'remoteEntry.js',
32
+ // Các module được expose
33
+ exposes: {
34
+ './Button': './src/Button.vue'
35
+ },
36
+ shared: ['vue']
37
+ })
38
+ ],
39
+ build: {
40
+ // Module Federation yêu cầu target >= es2020
41
+ target: 'esnext'
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### Bước 2: Cấu hình host
47
+
48
+ ```js
49
+ // vite.config.js — host
50
+ import federation from '@sbee/vite-federation'
51
+
52
+ export default {
53
+ plugins: [
54
+ federation({
55
+ name: 'host-app',
56
+ remotes: {
57
+ remote_app: 'http://localhost:5001/assets/remoteEntry.js'
58
+ },
59
+ shared: ['vue']
60
+ })
61
+ ],
62
+ build: {
63
+ target: 'esnext'
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### Bước 3: Dùng remote module trên host
69
+
70
+ ```js
71
+ import { defineAsyncComponent } from 'vue'
72
+
73
+ const RemoteButton = defineAsyncComponent(() => import('remote_app/Button'))
74
+ ```
75
+
76
+ ```vue
77
+ <template>
78
+ <RemoteButton />
79
+ </template>
80
+ ```
81
+
82
+ ## Runtime API — tải remote động không cần config
83
+
84
+ Khi host **không biết trước** danh sách remote (ví dụ URL đến từ backend, plugin marketplace, cấu hình động), dùng entry `@sbee/vite-federation/runtime`. Không cần khai báo `remotes` trong `vite.config.ts`.
85
+
86
+ ```ts
87
+ import { loadRemote } from '@sbee/vite-federation/runtime'
88
+
89
+ // Tải thẳng từ URL, không cần đăng ký trước
90
+ const Button = await loadRemote('https://remote.example.com/remoteEntry.js', './Button')
91
+ ```
92
+
93
+ ### Đăng ký trước rồi dùng theo tên
94
+
95
+ ```ts
96
+ import { registerRemote, loadRemote } from '@sbee/vite-federation/runtime'
97
+
98
+ registerRemote('design-system', {
99
+ url: 'https://cdn.example.com/remoteEntry.js',
100
+ format: 'esm',
101
+ from: 'vite'
102
+ })
103
+
104
+ const Modal = await loadRemote('design-system', './Modal')
105
+ ```
106
+
107
+ ### Preload & tải nhiều module cùng lúc
108
+
109
+ ```ts
110
+ import { preloadRemote, loadRemoteModules } from '@sbee/vite-federation/runtime'
111
+
112
+ // Init sẵn remote, trả về handle để gọi .get() nhiều lần
113
+ const remote = await preloadRemote('design-system')
114
+ const Button = await remote.get('./Button')
115
+
116
+ // Tải nhiều module một lần
117
+ const { Header, Footer } = await loadRemoteModules(
118
+ 'https://remote.example.com/remoteEntry.js',
119
+ { Header: './Header', Footer: './Footer' }
120
+ )
121
+ ```
122
+
123
+ Gọi `loadRemote` / `preloadRemote` đồng thời với cùng một remote chỉ tải và init **đúng một lần** (promise được dedup), tránh trùng `<script>` hoặc double init.
124
+
125
+ ### API reference
126
+
127
+ | Hàm | Mô tả |
128
+ | --- | --- |
129
+ | `loadRemote<T>(urlOrName, moduleName, config?)` | Tải một module từ remote. `urlOrName` là URL trực tiếp hoặc tên đã đăng ký. |
130
+ | `loadRemoteModules(urlOrName, { key: moduleName }, config?)` | Tải nhiều module cùng lúc, trả về object theo key. |
131
+ | `registerRemote(name, config)` | Đăng ký remote để dùng lại theo tên. Đồng bộ, chỉ lưu config. |
132
+ | `preloadRemote(name, config?)` | Tải & init remote, trả về `RemoteHandle` có `.get()`, `.init()`, `.inited`. |
133
+ | `provideShared(scope, packages)` | Đăng ký shared packages vào global share scope (dùng bởi host). |
134
+ | `getShareScope(scope?)` | Lấy global share scope hiện tại. |
135
+
136
+ `RemoteConfig`:
137
+
138
+ ```ts
139
+ interface RemoteConfig {
140
+ url: string | (() => Promise<string>)
141
+ format?: 'esm' | 'var' // mặc định 'esm'
142
+ from?: 'vite' | 'webpack' // mặc định 'vite'
143
+ shareScope?: string // mặc định 'default'
144
+ }
145
+ ```
146
+
147
+ ## Tùy chọn plugin
148
+
149
+ | Option | Kiểu | Mô tả |
150
+ | --- | --- | --- |
151
+ | `name` | `string` | Tên container. |
152
+ | `filename` | `string` | Tên file remote entry, mặc định `remoteEntry.js`. |
153
+ | `exposes` | `object` | Các module remote expose ra ngoài. |
154
+ | `remotes` | `object` | Các remote mà host tiêu thụ. |
155
+ | `shared` | `string[] \| object` | Các dependency dùng chung giữa host và remote. |
156
+ | `shareScope` | `string` | Tên share scope, mặc định `default`. |
157
+
158
+ ## Build
159
+
160
+ ```bash
161
+ npm run build
162
+ ```
163
+
164
+ Sinh ra bundle `esm` + `cjs` trong `dist/` kèm khai báo type cho entry `runtime`. Chạy test:
165
+
166
+ ```bash
167
+ npx vitest run
168
+ ```