@equinor/fusion-framework-vite-plugin-spa 1.0.0-next.8 → 1.0.0
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/CHANGELOG.md +34 -0
- package/README.md +442 -99
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/html/bootstrap.js +64 -41
- package/dist/html/bootstrap.js.map +1 -1
- package/dist/html/sw.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/html/index.html.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +6 -6
- package/src/version.ts +1 -1
- package/tsconfig.json +2 -1
package/README.md
CHANGED
|
@@ -1,77 +1,253 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Fusion Framework Vite SPA Plugin
|
|
3
|
+
description: >
|
|
4
|
+
A powerful Vite plugin for building Single Page Applications (SPAs) with the Fusion Framework. It automates HTML template generation, bootstraps authentication and service discovery, and streamlines portal loading and API proxying. Designed for seamless integration with the Fusion Framework CLI, this plugin provides flexible configuration for both standard and advanced SPA scenarios.
|
|
5
|
+
tags:
|
|
6
|
+
- fusion-framework
|
|
7
|
+
- cli
|
|
8
|
+
- app-development
|
|
9
|
+
- portal-development
|
|
10
|
+
- dev-server
|
|
11
|
+
- authentication
|
|
12
|
+
- configuration
|
|
13
|
+
- service-discovery
|
|
14
|
+
- equinor
|
|
15
|
+
- non-production
|
|
16
|
+
- documentation
|
|
17
|
+
keywords:
|
|
18
|
+
- fusion-framework
|
|
19
|
+
- vite
|
|
20
|
+
- spa
|
|
21
|
+
- plugin
|
|
22
|
+
- development
|
|
23
|
+
- non-production
|
|
24
|
+
---
|
|
25
|
+
|
|
1
26
|
# Fusion Framework Vite SPA Plugin
|
|
2
27
|
|
|
3
|
-
|
|
28
|
+
[](https://www.npmjs.com/package/@equinor/fusion-framework-vite-plugin-spa)
|
|
29
|
+
[](./LICENSE)
|
|
4
30
|
|
|
5
|
-
|
|
31
|
+
A powerful Vite plugin for building Single Page Applications (SPAs) with the Fusion Framework. It automates HTML template generation, bootstraps authentication and service discovery, and streamlines portal loading and API proxying. Designed for seamless integration with the Fusion Framework CLI, this plugin provides flexible configuration for both standard and advanced SPA scenarios.
|
|
6
32
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { plugin as fusionSpaPlugin } from '@equinor/fusion-framework-vite-plugin-spa';
|
|
33
|
+
> [!CAUTION]
|
|
34
|
+
> This plugin is intended for use in non-production environments only.
|
|
10
35
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
36
|
+
> [!WARNING]
|
|
37
|
+
> This plugin is developed for usage with [`@equinor/fusion-framework-cli`](https://github.com/equinor/fusion-framework/tree/main/packages/cli) and this documentation is intended for deeper understanding of the plugin's capabilities and configuration options.
|
|
38
|
+
>
|
|
39
|
+
> **NOTE:** _Just because there are buttons available doesn't mean you need to press them 🐒_
|
|
40
|
+
>
|
|
41
|
+
> The plugin is written in a modular fashion, allowing for easy customization and extension __IF__ the developer has a deep understanding of the Fusion Framework and its internals.
|
|
42
|
+
|
|
43
|
+
## Table of Contents
|
|
44
|
+
|
|
45
|
+
- [Fusion Framework Vite SPA Plugin](#fusion-framework-vite-spa-plugin)
|
|
46
|
+
- [Table of Contents](#table-of-contents)
|
|
47
|
+
- [What It Does](#what-it-does)
|
|
48
|
+
- [How the Plugin Works](#how-the-plugin-works)
|
|
49
|
+
- [Getting Started](#getting-started)
|
|
50
|
+
- [Configuration Options](#configuration-options)
|
|
51
|
+
- [Basic Configuration](#basic-configuration)
|
|
52
|
+
- [Service Discovery](#service-discovery)
|
|
53
|
+
- [MSAL](#msal)
|
|
54
|
+
- [Service Worker](#service-worker)
|
|
55
|
+
- [Configuring through `.env` File](#configuring-through-env-file)
|
|
56
|
+
- [How Environment Variables Work](#how-environment-variables-work)
|
|
57
|
+
- [Naming Convention](#naming-convention)
|
|
58
|
+
- [Example Conversion](#example-conversion)
|
|
59
|
+
- [Complete `.env` Example](#complete-env-example)
|
|
60
|
+
- [Advanced Customization](#advanced-customization)
|
|
61
|
+
- [Providing a Custom Template](#providing-a-custom-template)
|
|
62
|
+
- [Providing Custom Bootstrap](#providing-custom-bootstrap)
|
|
63
|
+
- [Examples](#examples)
|
|
64
|
+
- [Basic SPA Configuration](#basic-spa-configuration)
|
|
65
|
+
- [Using with API Service Plugin](#using-with-api-service-plugin)
|
|
66
|
+
- [Troubleshooting \& FAQ](#troubleshooting--faq)
|
|
67
|
+
- [Common Issues](#common-issues)
|
|
68
|
+
- [Known Issues](#known-issues)
|
|
69
|
+
- [Best Practices \& FAQ](#best-practices--faq)
|
|
70
|
+
- [Contributing](#contributing)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## What It Does
|
|
74
|
+
|
|
75
|
+
The plugin:
|
|
76
|
+
|
|
77
|
+
1. **Bootstraps the Fusion Framework** - Initializes core modules including MSAL authentication and service discovery
|
|
78
|
+
2. **Renders a Configured Portal** - Loads and renders any portal by ID, as long as it exports a render function
|
|
79
|
+
3. **Registers a Service Worker** - Enables authenticated API requests by automatically injecting auth tokens
|
|
80
|
+
4. **Configures Development Environment** - Works with `plugin-api-service` to intercept and proxy authenticated requests during development
|
|
81
|
+
|
|
82
|
+
> [!TIP]
|
|
83
|
+
> The plugin will render the configured portal which can be sourced from:
|
|
84
|
+
> - A local npm package (like `@equinor/fusion-framework-dev-portal`, the default used by CLI)
|
|
85
|
+
> - The Fusion Portal Service (using a portal identifier)
|
|
86
|
+
> - Any custom portal implementation configured in your environment
|
|
87
|
+
|
|
88
|
+
## How the Plugin Works
|
|
89
|
+
|
|
90
|
+
```mermaid
|
|
91
|
+
flowchart
|
|
92
|
+
A[Vite HTML request] -->|index.html| B[Plugin serve SPA]
|
|
93
|
+
B -->|bootstrap.js| C[Initialize Fusion Framework]
|
|
94
|
+
C --> D[Register Service Worker]
|
|
95
|
+
C -->|"/portals/{portalId}@${portalTag}"| E[Fetch Portal Manifest]
|
|
96
|
+
E -->|manifest.build.config| F[Fetch Portal Configuration]
|
|
97
|
+
F -->|manifest.build.entrypoint| G[Import Portal Source]
|
|
98
|
+
G -->|"Fusion Instance"| H[Render Portal]
|
|
99
|
+
|
|
100
|
+
style A fill:#F00,stroke:#333,stroke-width:1px
|
|
101
|
+
style H fill:#00F,stroke:#333,stroke-width:1px
|
|
14
102
|
```
|
|
15
103
|
|
|
16
|
-
|
|
104
|
+
**Flow Explanation:**
|
|
105
|
+
1. **Vite HTML Request**: The plugin hooks into the Vite dev-server and intercepts SPA requests.
|
|
106
|
+
2. **Serve SPA**: The plugin serves the SPA by returning the `index.html` file.
|
|
107
|
+
3. **Initialize Fusion Framework**: `bootstrap.js` is loaded
|
|
108
|
+
- configures the framework (e.g. MSAL, service discovery)
|
|
109
|
+
- initializes the framework
|
|
110
|
+
- registers service worker (connects to fusion framework)
|
|
111
|
+
4. **Fetch Portal Manifest**: The framework fetches the manifest describing the portal to load.
|
|
112
|
+
5. **Fetch Portal Configuration**: Additional configuration for the portal is retrieved.
|
|
113
|
+
6. **Load Portal Source File**: The main entry file for the portal is loaded based on the manifest.
|
|
114
|
+
7. **Render Portal**: Renders the portal with the Fusion Framework.
|
|
115
|
+
|
|
116
|
+
## Getting Started
|
|
117
|
+
|
|
118
|
+
> [!WARNING]
|
|
119
|
+
> This plugin is primarily designed to be used with the [Fusion Framework CLI](https://github.com/equinor/fusion-framework-cli). The CLI scaffolds all required configuration and wiring for you.
|
|
120
|
+
|
|
121
|
+
**Standalone usage is advanced:** If you use this plugin outside the CLI, you must provide detailed configuration for authentication, service discovery, portal loading, and more. There is no "one-line" quick start for custom setups. See the [Basic Configuration](#basic-configuration) and [Configuration Options](#configuration-options) sections below.
|
|
122
|
+
|
|
123
|
+
> [!NOTE]
|
|
124
|
+
> This plugin should cover most use cases for building SPAs with the Fusion Framework, but advanced configurations may require additional setup.
|
|
125
|
+
> If for some reason you are adventurous enough to write your custom implementation of developer utilities, this guide should help you get started.
|
|
126
|
+
|
|
127
|
+
## Configuration Options
|
|
128
|
+
|
|
129
|
+
The plugin accepts a variety of configuration options to tailor the SPA to your project's needs. These options control authentication flows, service discovery, and routing behaviors.
|
|
130
|
+
|
|
131
|
+
### Basic Configuration
|
|
132
|
+
|
|
133
|
+
Here's a comprehensive example showing all major configuration options:
|
|
17
134
|
|
|
18
135
|
```ts
|
|
19
136
|
fusionSpaPlugin({
|
|
20
|
-
generateTemplateEnv: () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
137
|
+
generateTemplateEnv: () => ({
|
|
138
|
+
// HTML page title
|
|
139
|
+
title: 'My App',
|
|
140
|
+
|
|
141
|
+
// Portal configuration: specify which portal to load
|
|
142
|
+
portal: {
|
|
143
|
+
id: 'my-portal', // Portal ID to load and render
|
|
144
|
+
// Can be:
|
|
145
|
+
// 1. A package name (e.g. '@equinor/fusion-framework-dev-portal', default for CLI)
|
|
146
|
+
// 2. An ID from the Fusion Portal Service
|
|
147
|
+
// 3. Any other configured portal ID
|
|
148
|
+
tag: 'latest', // (Optional) Version tag (defaults to 'latest')
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// Service Discovery configuration
|
|
152
|
+
serviceDiscovery: {
|
|
153
|
+
url: 'https://my-server.com/service-discovery',
|
|
154
|
+
scopes: ['api://my-app/scope'],
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
// MSAL (Microsoft Authentication Library) configuration
|
|
158
|
+
msal: {
|
|
159
|
+
tenantId: 'my-tenant-id',
|
|
160
|
+
clientId: 'my-client-id',
|
|
161
|
+
redirectUri: 'https://my-app.com/auth-callback',
|
|
162
|
+
requiresAuth: 'true',
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// Service Worker configuration for API proxying and authentication
|
|
166
|
+
serviceWorker: {
|
|
167
|
+
resources: [
|
|
168
|
+
{
|
|
169
|
+
url: '/app-proxy',
|
|
170
|
+
rewrite: '/@fusion-api/app',
|
|
171
|
+
scopes: ['xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/.default'],
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
})
|
|
46
176
|
});
|
|
47
177
|
```
|
|
178
|
+
See [@equinor/fusion-framework-vite-plugin-api-service](https://github.com/equinor/fusion-framework/tree/main/packages/vite-plugins/api-service) for advanced API proxying.
|
|
48
179
|
|
|
49
180
|
### Service Discovery
|
|
50
181
|
|
|
51
|
-
The
|
|
52
|
-
|
|
182
|
+
The Service Discovery component provides a dynamic way to discover and connect to backend services. It's a crucial part of the Fusion Framework architecture that helps applications locate and communicate with various microservices.
|
|
183
|
+
|
|
184
|
+
**Configuration Options:**
|
|
185
|
+
|
|
186
|
+
- `url`: The endpoint URL where the service discovery configuration can be fetched from
|
|
187
|
+
- `scopes`: Array of OAuth scopes required to authenticate service discovery requests
|
|
188
|
+
|
|
189
|
+
**Benefits:**
|
|
190
|
+
- Eliminates hardcoded service endpoints in your application
|
|
191
|
+
- Enables dynamic service routing based on environment
|
|
192
|
+
- Centralizes service endpoint management
|
|
53
193
|
|
|
54
194
|
### MSAL
|
|
55
195
|
|
|
56
|
-
The
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- `
|
|
196
|
+
The Microsoft Authentication Library (MSAL) configuration handles user authentication with Azure Active Directory. This enables single sign-on capabilities and secure access to protected resources.
|
|
197
|
+
|
|
198
|
+
**Configuration Options:**
|
|
199
|
+
|
|
200
|
+
- `tenantId`: The Azure AD tenant ID associated with your organization
|
|
201
|
+
- `clientId`: The client/application ID registered in Azure AD
|
|
202
|
+
- `redirectUri`: The URL where users are redirected after authentication
|
|
203
|
+
- `requiresAuth` _(optional)_: When set to "true", the application will automatically prompt for login on initial load
|
|
61
204
|
|
|
62
205
|
### Service Worker
|
|
63
206
|
|
|
64
|
-
The
|
|
207
|
+
The Service Worker component provides powerful capabilities for handling network requests, adding authentication, and enabling offline capabilities in your SPA.
|
|
208
|
+
|
|
209
|
+
#### How It Works
|
|
210
|
+
|
|
211
|
+
```mermaid
|
|
212
|
+
sequenceDiagram
|
|
213
|
+
participant App as Application
|
|
214
|
+
participant SW as Service Worker
|
|
215
|
+
participant Main as Fusion Framework
|
|
216
|
+
participant API as API Server
|
|
217
|
+
|
|
218
|
+
App->>SW: fetch('/app-proxy/assets/some-app/resource.json')
|
|
219
|
+
alt Route matches a registered resource
|
|
220
|
+
SW->>Main: Request auth tokens for scopes
|
|
221
|
+
Main-->>SW: Return tokens
|
|
222
|
+
SW->>SW: Rewrite URL to /@fusion-api/app/assets/some-app/resource.json
|
|
223
|
+
SW->>API: fetch with auth headers
|
|
224
|
+
API-->>SW: Response
|
|
225
|
+
SW-->>App: Return response
|
|
226
|
+
else Route does not match any resource
|
|
227
|
+
SW-->>App: Let request pass through (no interception)
|
|
228
|
+
end
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The Service Worker intercepts network requests made by your application and can modify them before they're sent. This is particularly useful for:
|
|
232
|
+
|
|
233
|
+
1. Adding authentication tokens automatically to API calls
|
|
234
|
+
2. Rewriting request URLs for proxying purposes
|
|
235
|
+
3. Enabling offline functionality
|
|
236
|
+
4. Improving performance through caching
|
|
237
|
+
|
|
238
|
+
#### Configuration Options
|
|
239
|
+
|
|
240
|
+
- `resources`: An array of resource configurations the service worker will manage
|
|
241
|
+
- `url`: Path pattern to match incoming requests against
|
|
242
|
+
- `rewrite` _(optional)_: Path to rewrite the matched URL to
|
|
243
|
+
- `scopes` _(optional)_: OAuth scopes to use for authenticating this resource
|
|
65
244
|
|
|
66
|
-
|
|
245
|
+
#### Complete Example
|
|
67
246
|
|
|
68
|
-
|
|
69
|
-
- `url` path to match requests to
|
|
70
|
-
- `rewrite` _(optional)_ path to replace the `url` with
|
|
71
|
-
- `scopes` _(optional)_ is an array of scopes to use for the resource.
|
|
247
|
+
Here's a detailed example of the Service Worker in action:
|
|
72
248
|
|
|
73
|
-
Example:
|
|
74
249
|
```ts
|
|
250
|
+
// Service Worker configuration example
|
|
75
251
|
const serviceWorker = {
|
|
76
252
|
resources: [
|
|
77
253
|
{
|
|
@@ -79,133 +255,300 @@ const serviceWorker = {
|
|
|
79
255
|
rewrite: '/@fusion-api/app',
|
|
80
256
|
scopes: [
|
|
81
257
|
'2bed749c-843b-413d-8b17-e7841869730f/.default',
|
|
82
|
-
'8c24cf81-de7a-435b-ab74-e90b1a7bda0a/.default'
|
|
258
|
+
'8c24cf81-de7a-435b-ab74-e90b1a7bda0a/.default',
|
|
83
259
|
],
|
|
84
260
|
},
|
|
85
261
|
],
|
|
86
262
|
};
|
|
87
263
|
|
|
264
|
+
// Example: Making a request in your application code
|
|
88
265
|
fetch('/app-proxy/assets/some-app/resource-path/resource.json');
|
|
89
266
|
```
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
267
|
+
|
|
268
|
+
#### Request Processing Flow
|
|
269
|
+
|
|
270
|
+
When the above `fetch` request is made, the following happens:
|
|
271
|
+
|
|
272
|
+
1. The Service Worker intercepts the request matching the `/app-proxy` pattern
|
|
273
|
+
2. It sends a message to the main thread requesting authentication tokens for the specified scopes
|
|
274
|
+
3. The main thread generates the necessary authentication tokens
|
|
275
|
+
4. The Service Worker rewrites the URL from `/app-proxy/assets/some-app/resource-path/resource.json` to `/@fusion-api/app/assets/some-app/resource-path/resource.json`
|
|
276
|
+
5. It adds the authentication headers to the request and executes it against the rewritten URL
|
|
277
|
+
6. The response is returned to the application as if the original URL was called
|
|
95
278
|
|
|
96
279
|
> [!TIP]
|
|
97
|
-
> The `
|
|
98
|
-
> so that url can emulate a proxy service in the production environment.
|
|
99
|
-
> The `rewrite` path is the actual endpoint to call.
|
|
280
|
+
> The `url` path doesn't need to correspond to an actual endpoint—it's simply a pattern used for matching requests. This allows you to emulate proxy services in production environments without changing your application code.
|
|
100
281
|
|
|
101
282
|
> [!TIP]
|
|
102
|
-
>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
283
|
+
> For enhanced development capabilities, consider using the `@equinor/fusion-framework-vite-plugin-api-service` plugin. This plugin creates a dynamic proxy service that can handle requests to the `/@fusion-api/app` path by intercepting them in the dev-server and routing them based on service discovery configuration.
|
|
284
|
+
|
|
285
|
+
## Configuring through `.env` File
|
|
286
|
+
|
|
287
|
+
For greater flexibility—especially in CI/CD pipelines and deployment scenarios—the plugin supports configuration through environment variables in a `.env` file.
|
|
288
|
+
|
|
289
|
+
### How Environment Variables Work
|
|
290
|
+
|
|
291
|
+
The plugin reads the `.env` file and overrides any properties defined in the `generateTemplateEnv` function with the corresponding environment variables. This approach allows you to:
|
|
107
292
|
|
|
108
|
-
|
|
293
|
+
- Maintain different configurations for development, testing, and production
|
|
294
|
+
- Keep sensitive information out of your source code
|
|
295
|
+
- Override configuration values during deployment pipelines
|
|
109
296
|
|
|
110
|
-
|
|
297
|
+
### Naming Convention
|
|
111
298
|
|
|
112
|
-
|
|
299
|
+
Environment variables follow a specific naming pattern:
|
|
300
|
+
1. All variables are prefixed with `FUSION_SPA_`
|
|
301
|
+
2. Object paths are converted to snake case with underscores
|
|
302
|
+
3. Arrays and objects are serialized as JSON strings
|
|
113
303
|
|
|
114
|
-
|
|
304
|
+
### Example Conversion
|
|
305
|
+
|
|
306
|
+
Here's how JavaScript configuration objects map to environment variables:
|
|
115
307
|
|
|
116
308
|
```ts
|
|
309
|
+
// JavaScript configuration
|
|
117
310
|
{
|
|
118
311
|
serviceWorker: {
|
|
119
312
|
resources: [...],
|
|
120
313
|
},
|
|
121
314
|
}
|
|
122
|
-
// will be converted to
|
|
123
|
-
FUSION_SPA_SERVICE_WORKER_RESOURCES: [...],
|
|
124
315
|
|
|
125
|
-
//
|
|
316
|
+
// Becomes this environment variable
|
|
317
|
+
FUSION_SPA_SERVICE_WORKER_RESOURCES=[...]
|
|
318
|
+
|
|
319
|
+
// And can be accessed in your code as
|
|
126
320
|
import.meta.env.FUSION_SPA_SERVICE_WORKER_RESOURCES
|
|
127
321
|
```
|
|
128
322
|
|
|
129
|
-
|
|
130
|
-
> Prefer to use the `generateTemplateEnv` function to provide the properties.
|
|
131
|
-
> The `.env` file is used to override configurations, example in an CI/CD pipeline.
|
|
132
|
-
|
|
133
|
-
> [!IMPORTANT]
|
|
134
|
-
> The `.env` file should be placed in the root of the project.
|
|
135
|
-
> Parameters from the `.env` file overrides the parameters from the `generateTemplateEnv` function.
|
|
323
|
+
### Complete `.env` Example
|
|
136
324
|
|
|
137
|
-
```
|
|
325
|
+
```sh
|
|
326
|
+
# Application basics
|
|
138
327
|
FUSION_SPA_TITLE=My App
|
|
139
|
-
FUSION_SPA_PORTAL_ID=my-portal
|
|
328
|
+
FUSION_SPA_PORTAL_ID=my-portal # Can be a package name, Fusion Portal Service ID, or any configured portal ID
|
|
329
|
+
|
|
330
|
+
# Service Discovery configuration
|
|
140
331
|
FUSION_SPA_SERVICE_DISCOVERY_URL=https://my-server.com/service-discovery
|
|
141
332
|
FUSION_SPA_SERVICE_DISCOVERY_SCOPES=[api://my-app/scope]
|
|
333
|
+
|
|
334
|
+
# MSAL Authentication configuration
|
|
142
335
|
FUSION_SPA_MSAL_TENANT_ID=my-tenant-id
|
|
143
336
|
FUSION_SPA_MSAL_CLIENT_ID=my-client-id
|
|
144
337
|
FUSION_SPA_MSAL_REDIRECT_URI=https://my-app.com/auth-callback
|
|
145
338
|
FUSION_SPA_MSAL_REQUIRES_AUTH=true
|
|
339
|
+
|
|
340
|
+
# Service Worker configuration (as JSON string)
|
|
146
341
|
FUSION_SPA_SERVICE_WORKER_RESOURCES=[{"url":"/app-proxy","rewrite":"/@fusion-api/app","scopes":["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/.default"]}]
|
|
147
342
|
```
|
|
148
343
|
|
|
149
|
-
|
|
344
|
+
> [!TIP]
|
|
345
|
+
> While environment variables are convenient for deployment scenarios, it's generally recommended to use the `generateTemplateEnv` function during development for better type checking and easier debugging.
|
|
346
|
+
|
|
347
|
+
> [!IMPORTANT]
|
|
348
|
+
> The `.env` file must be placed in the root of your project. Values defined in the `.env` file will override any corresponding values from the `generateTemplateEnv` function.
|
|
349
|
+
|
|
350
|
+
## Advanced Customization
|
|
351
|
+
|
|
352
|
+
For advanced scenarios, the plugin provides options to customize both the HTML template and the application bootstrapping process. These customizations should be approached carefully as they may require deeper understanding of the framework.
|
|
353
|
+
|
|
354
|
+
### Providing a Custom Template
|
|
355
|
+
|
|
356
|
+
You can provide a completely custom HTML template for your application. This gives you full control over the document structure while still leveraging the plugin's environment variable injection.
|
|
150
357
|
|
|
151
358
|
> [!WARNING]
|
|
152
|
-
>
|
|
153
|
-
|
|
359
|
+
> Custom templates move you closer to the edge of the framework's capabilities. Proceed with caution as you'll be responsible for ensuring proper structure and bootstrapping.
|
|
360
|
+
|
|
361
|
+
#### Example Custom Template
|
|
154
362
|
|
|
155
363
|
```ts
|
|
364
|
+
// Define your custom HTML template
|
|
156
365
|
const template = `
|
|
157
366
|
<!DOCTYPE html>
|
|
158
367
|
<html lang="en">
|
|
159
|
-
<head>
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
<
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
368
|
+
<head>
|
|
369
|
+
<meta charset="UTF-8">
|
|
370
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
371
|
+
<title>%MY_CUSTOM_TITLE%</title>
|
|
372
|
+
<script type="module" src="./src/my-custom-bootloader"></script>
|
|
373
|
+
</head>
|
|
374
|
+
<body>
|
|
375
|
+
<h1>%MY_CUSTOM_PROPERTY%</h1>
|
|
376
|
+
<div id="app"></div>
|
|
377
|
+
</body>
|
|
166
378
|
</html>
|
|
167
379
|
`;
|
|
168
380
|
|
|
381
|
+
// Configure Vite with your custom template
|
|
169
382
|
import { defineConfig } from 'vite';
|
|
170
383
|
import { createViteSPAPlugin } from '@equinor/fusion-framework-vite-plugin-spa';
|
|
171
384
|
|
|
385
|
+
// Custom prefix for environment variables
|
|
172
386
|
const templateEnvPrefix = 'MY_CUSTOM_';
|
|
173
387
|
|
|
174
388
|
export default defineConfig({
|
|
389
|
+
// Define environment variables to inject into the template
|
|
175
390
|
define: {
|
|
176
|
-
`import.meta.env.${templateEnvPrefix}PROPERTY
|
|
391
|
+
[`import.meta.env.${templateEnvPrefix}PROPERTY`]: '"my-custom-value"',
|
|
392
|
+
[`import.meta.env.${templateEnvPrefix}TITLE`]: '"My Application"',
|
|
177
393
|
},
|
|
178
|
-
|
|
394
|
+
// Use the custom template with the plugin
|
|
395
|
+
plugins: [createViteSPAPlugin({ template, templateEnvPrefix })],
|
|
179
396
|
});
|
|
180
397
|
```
|
|
181
398
|
|
|
182
399
|
> [!TIP]
|
|
183
|
-
> see [Vite documentation](https://vite.dev/guide/env-and-mode.html#html-constant-replacement)
|
|
400
|
+
> For more details on how HTML template variable replacement works in Vite, see the [Vite documentation](https://vite.dev/guide/env-and-mode.html#html-constant-replacement).
|
|
401
|
+
|
|
402
|
+
### Providing Custom Bootstrap
|
|
184
403
|
|
|
185
|
-
|
|
404
|
+
For even more control, you can specify a custom bootstrap file that handles the initialization of your application:
|
|
186
405
|
|
|
187
406
|
```ts
|
|
188
407
|
fusionSpaPlugin({
|
|
189
408
|
generateTemplateEnv: () => {
|
|
190
409
|
return {
|
|
410
|
+
// Points to your custom bootstrap file
|
|
191
411
|
bootstrap: 'src/my-custom-bootloader.ts',
|
|
192
412
|
}
|
|
193
413
|
}
|
|
194
414
|
});
|
|
195
415
|
```
|
|
196
416
|
|
|
197
|
-
|
|
198
|
-
> The bootstrapping of the `ServiceWorker` is done in the the bootloader,
|
|
199
|
-
> this functionality will no longer be available, but needs to be re-implemented in the custom bootloader.
|
|
417
|
+
#### Implementing Your Custom Bootloader
|
|
200
418
|
|
|
419
|
+
When implementing a custom bootloader, you'll need to handle all the initialization logic that would normally be managed by the default bootloader, including service worker registration:
|
|
201
420
|
|
|
202
421
|
```ts
|
|
203
422
|
// custom-bootloader.ts
|
|
204
|
-
import { registerServiceWorker} from '@equinor/fusion-framework-vite-plugin-spa/html';
|
|
205
|
-
|
|
423
|
+
import { registerServiceWorker } from '@equinor/fusion-framework-vite-plugin-spa/html';
|
|
206
424
|
import initializeFramework from './my-custom-framework.js';
|
|
207
425
|
|
|
208
|
-
|
|
426
|
+
// Initialize your framework and register the service worker
|
|
427
|
+
const app = await initializeFramework();
|
|
428
|
+
registerServiceWorker(app);
|
|
429
|
+
|
|
430
|
+
// Additional custom initialization code
|
|
431
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
432
|
+
console.log('Application fully loaded');
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
> [!WARNING]
|
|
437
|
+
> When using a custom bootloader, the default ServiceWorker registration is bypassed. You must explicitly call `registerServiceWorker()` in your custom bootloader to maintain this functionality, as shown in the example above.
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
## Examples
|
|
441
|
+
|
|
442
|
+
Here are some common implementation examples to help you get started quickly:
|
|
443
|
+
|
|
444
|
+
### Basic SPA Configuration
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
// vite.config.ts
|
|
448
|
+
import { defineConfig } from 'vite';
|
|
449
|
+
import { plugin as fusionSpaPlugin } from '@equinor/fusion-framework-vite-plugin-spa';
|
|
450
|
+
import react from '@vitejs/plugin-react';
|
|
451
|
+
|
|
452
|
+
export default defineConfig({
|
|
453
|
+
plugins: [
|
|
454
|
+
react(),
|
|
455
|
+
fusionSpaPlugin({
|
|
456
|
+
generateTemplateEnv: () => ({
|
|
457
|
+
title: 'My React App',
|
|
458
|
+
portal: { id: 'my-portal' },
|
|
459
|
+
serviceDiscovery: {
|
|
460
|
+
url: 'https://dev-server.com/service-discovery',
|
|
461
|
+
scopes: ['api://my-app/user.read'],
|
|
462
|
+
},
|
|
463
|
+
msal: {
|
|
464
|
+
tenantId: process.env.TENANT_ID,
|
|
465
|
+
clientId: process.env.CLIENT_ID,
|
|
466
|
+
redirectUri: 'http://localhost:3000/auth-callback',
|
|
467
|
+
requiresAuth: 'true',
|
|
468
|
+
},
|
|
469
|
+
}),
|
|
470
|
+
}),
|
|
471
|
+
],
|
|
472
|
+
});
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Using with API Service Plugin
|
|
476
|
+
|
|
477
|
+
```ts
|
|
478
|
+
// vite.config.ts
|
|
479
|
+
import { defineConfig } from 'vite';
|
|
480
|
+
import { plugin as fusionSpaPlugin } from '@equinor/fusion-framework-vite-plugin-spa';
|
|
481
|
+
import { plugin as apiServicePlugin } from '@equinor/fusion-framework-vite-plugin-api-service';
|
|
482
|
+
import react from '@vitejs/plugin-react';
|
|
483
|
+
|
|
484
|
+
export default defineConfig({
|
|
485
|
+
plugins: [
|
|
486
|
+
react(),
|
|
487
|
+
fusionSpaPlugin({
|
|
488
|
+
generateTemplateEnv: () => ({
|
|
489
|
+
title: 'API Service Example',
|
|
490
|
+
// Portal to load
|
|
491
|
+
portal: {
|
|
492
|
+
id: 'my-portal',
|
|
493
|
+
tag: 'latest',
|
|
494
|
+
},
|
|
495
|
+
serviceDiscovery: {
|
|
496
|
+
url: 'https://dev-server.com/service-discovery',
|
|
497
|
+
scopes: ['api://my-app/user.read'],
|
|
498
|
+
},
|
|
499
|
+
serviceWorker: {
|
|
500
|
+
resources: [
|
|
501
|
+
{
|
|
502
|
+
url: '/api-proxy',
|
|
503
|
+
rewrite: '/@fusion-api/service',
|
|
504
|
+
scopes: ['api://backend-service/.default'],
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
}),
|
|
509
|
+
}),
|
|
510
|
+
// API Service plugin enables portal loading from service discovery
|
|
511
|
+
apiServicePlugin(),
|
|
512
|
+
],
|
|
513
|
+
});
|
|
209
514
|
```
|
|
515
|
+
See [API Service Plugin docs](https://github.com/equinor/fusion-framework/tree/main/packages/vite-plugins/api-service) for more details.
|
|
516
|
+
|
|
517
|
+
## Troubleshooting & FAQ
|
|
518
|
+
|
|
519
|
+
### Common Issues
|
|
520
|
+
|
|
521
|
+
1. **Authentication Failures**
|
|
522
|
+
- Ensure your `tenantId` and `clientId` values are correct
|
|
523
|
+
- Check that your application is properly registered in Azure AD
|
|
524
|
+
- Verify that the required scopes are configured correctly
|
|
525
|
+
|
|
526
|
+
2. **Service Worker Not Working**
|
|
527
|
+
- Ensure the service worker is properly registered in your bootstrap process
|
|
528
|
+
- Check browser console for any registration errors
|
|
529
|
+
- Verify that the URL patterns in the resources configuration match your fetch calls
|
|
530
|
+
|
|
531
|
+
3. **Environment Variables Not Applied**
|
|
532
|
+
- Confirm your `.env` file is in the project root
|
|
533
|
+
- Verify the naming convention follows `FUSION_SPA_*` with proper snake_casing
|
|
534
|
+
- Restart your development server after changing environment variables
|
|
535
|
+
|
|
536
|
+
### Known Issues
|
|
537
|
+
|
|
538
|
+
| Issue | Impact | Description |
|
|
539
|
+
| ----- | ------ | ----------- |
|
|
540
|
+
| [#3266](https://github.com/equinor/fusion-framework/issues/3266) | **Missing bearer token on proxy assets** | When loading remote applications that use assets or code-splitting, the service worker may fail to attach the required Bearer token to requests for these resources. This occurs because the service worker rewrites `import.url`, which can interfere with proper token injection for asset requests. As a result, protected assets may not load correctly in some scenarios.|
|
|
541
|
+
|
|
542
|
+
### Best Practices & FAQ
|
|
543
|
+
|
|
544
|
+
- **Keep secrets out of source code** — use environment variables for sensitive values.
|
|
545
|
+
- **Leverage the [API Service Plugin](https://github.com/equinor/fusion-framework/tree/main/packages/vite-plugins/api-service)** for advanced API proxying and local development.
|
|
546
|
+
- **When customizing templates or bootloaders,** always test service worker registration and authentication flows.
|
|
547
|
+
- **For local development:**
|
|
548
|
+
- Use [Vite's environment variable system](https://vitejs.dev/guide/env-and-mode.html)
|
|
549
|
+
|
|
550
|
+
## Contributing
|
|
551
|
+
|
|
552
|
+
Contributions, bug reports, and feature requests are welcome! See [CONTRIBUTING.md](../../../CONTRIBUTING.md) for guidelines.
|
|
210
553
|
|
|
211
554
|
|
package/dist/esm/version.js
CHANGED
package/dist/esm/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|