@cloudflare/vite-plugin 0.0.0-39933740e → 0.0.0-3af2e30f8
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 +15 -540
- package/dist/index.js +76 -23
- package/dist/runner-worker/index.js +0 -14
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,340 +1,8 @@
|
|
|
1
1
|
# `@cloudflare/vite-plugin`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Intro
|
|
6
|
-
|
|
7
|
-
The Cloudflare Vite plugin enables a full-featured integration between Vite and the Workers runtime.
|
|
3
|
+
The Cloudflare Vite plugin enables a full-featured integration between [Vite](https://vite.dev/) and the [Workers runtime](https://developers.cloudflare.com/workers/runtime-apis/).
|
|
8
4
|
Your Worker code runs inside [workerd](https://github.com/cloudflare/workerd), matching the production behavior as closely as possible and providing confidence as you develop and deploy your applications.
|
|
9
5
|
|
|
10
|
-
### Features
|
|
11
|
-
|
|
12
|
-
- Provides direct access to Workers runtime APIs and bindings
|
|
13
|
-
- Supports Workers Assets, enabling you to build static sites, SPAs, and full-stack applications
|
|
14
|
-
- Leverages Vite's hot module replacement for consistently fast updates
|
|
15
|
-
- Supports `vite preview` for previewing your build output in the Workers runtime prior to deployment
|
|
16
|
-
|
|
17
|
-
## Quick start
|
|
18
|
-
|
|
19
|
-
### Start with a basic `package.json`
|
|
20
|
-
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"name": "cloudflare-vite-quick-start",
|
|
24
|
-
"private": true,
|
|
25
|
-
"version": "0.0.0",
|
|
26
|
-
"type": "module",
|
|
27
|
-
"scripts": {
|
|
28
|
-
"dev": "vite",
|
|
29
|
-
"build": "vite build",
|
|
30
|
-
"preview": "vite preview"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
> [!NOTE]
|
|
36
|
-
> Ensure that you include `"type": "module"` in order to use ES modules by default.
|
|
37
|
-
|
|
38
|
-
### Install the dependencies
|
|
39
|
-
|
|
40
|
-
```sh
|
|
41
|
-
npm install vite @cloudflare/vite-plugin wrangler --save-dev
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Create your Vite config file and include the Cloudflare plugin
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
// vite.config.ts
|
|
48
|
-
|
|
49
|
-
import { defineConfig } from "vite";
|
|
50
|
-
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
51
|
-
|
|
52
|
-
export default defineConfig({
|
|
53
|
-
plugins: [cloudflare()],
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Create your Worker config file
|
|
58
|
-
|
|
59
|
-
```toml
|
|
60
|
-
# wrangler.toml
|
|
61
|
-
|
|
62
|
-
name = "cloudflare-vite-quick-start"
|
|
63
|
-
compatibility_date = "2024-12-30"
|
|
64
|
-
main = "./src/index.ts"
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Create your Worker entry file
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
// src/index.ts
|
|
71
|
-
|
|
72
|
-
export default {
|
|
73
|
-
fetch() {
|
|
74
|
-
return new Response(`Running in ${navigator.userAgent}!`);
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
You can now develop (`npm run dev`), build (`npm run build`), preview (`npm run preview`), and deploy (`npm exec wrangler deploy`) your application.
|
|
80
|
-
|
|
81
|
-
## Tutorial
|
|
82
|
-
|
|
83
|
-
In this tutorial, you will create a React SPA that can be deployed as a Worker with Workers Assets.
|
|
84
|
-
Then, you will add an API Worker that can be accessed from the front-end code.
|
|
85
|
-
You will develop, build, and preview the application using Vite before finally deploying to Cloudflare.
|
|
86
|
-
|
|
87
|
-
### Set up and configure the React SPA
|
|
88
|
-
|
|
89
|
-
#### Scaffold a Vite project
|
|
90
|
-
|
|
91
|
-
Start by creating a React TypeScript project with Vite.
|
|
92
|
-
|
|
93
|
-
```sh
|
|
94
|
-
npm create vite@latest cloudflare-vite-tutorial -- --template react-ts
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Open the `cloudflare-vite-tutorial` directory in your editor of choice.
|
|
98
|
-
|
|
99
|
-
#### Add the Cloudflare dependencies
|
|
100
|
-
|
|
101
|
-
```sh
|
|
102
|
-
npm install @cloudflare/vite-plugin wrangler --save-dev
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
#### Add the plugin to your Vite config
|
|
106
|
-
|
|
107
|
-
```ts
|
|
108
|
-
// vite.config.ts
|
|
109
|
-
|
|
110
|
-
import { defineConfig } from "vite";
|
|
111
|
-
import react from "@vitejs/plugin-react";
|
|
112
|
-
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
113
|
-
|
|
114
|
-
export default defineConfig({
|
|
115
|
-
plugins: [react(), cloudflare()],
|
|
116
|
-
});
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
#### Create your Worker config file
|
|
120
|
-
|
|
121
|
-
```toml
|
|
122
|
-
# wrangler.toml
|
|
123
|
-
|
|
124
|
-
name = "cloudflare-vite-tutorial"
|
|
125
|
-
compatibility_date = "2024-12-30"
|
|
126
|
-
assets = { not_found_handling = "single-page-application" }
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
The [`not_found_handling`](https://developers.cloudflare.com/workers/static-assets/routing/#not_found_handling--404-page--single-page-application--none) value has been set to `single-page-application`.
|
|
130
|
-
This means that all not found requests will serve the `index.html` file.
|
|
131
|
-
With the Cloudflare plugin, the `assets` routing configuration is used in place of Vite's default behavior.
|
|
132
|
-
This ensures that your application's routing works the same way while developing as it does when deployed to production.
|
|
133
|
-
|
|
134
|
-
Note that the [`directory`](https://developers.cloudflare.com/workers/static-assets/binding/#directory) field is not used when configuring assets with Vite.
|
|
135
|
-
The `directory` in the output configuration will automatically point to the client build output.
|
|
136
|
-
|
|
137
|
-
> [!NOTE]
|
|
138
|
-
> When using the Cloudflare Vite plugin, the Worker config (for example, `wrangler.toml`) that you provide is the input configuration file.
|
|
139
|
-
> A separate output `wrangler.json` file is created when you run `vite build`.
|
|
140
|
-
> This output file is a snapshot of your configuration at the time of the build and is modified to reference your build artifacts.
|
|
141
|
-
> It is the configuration that is used for preview and deployment.
|
|
142
|
-
|
|
143
|
-
#### Update the .gitignore file
|
|
144
|
-
|
|
145
|
-
Wrangler will use and/or generate temporary files that should not be stored in git. Add the following lines to the `.gitignore` file:
|
|
146
|
-
|
|
147
|
-
```gitignore
|
|
148
|
-
.wrangler
|
|
149
|
-
.dev.vars
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
#### Run the development server
|
|
153
|
-
|
|
154
|
-
Run `npm run dev` to verify that your application is working as expected.
|
|
155
|
-
|
|
156
|
-
For a purely front-end application, you could now build (`npm run build`), preview (`npm run preview`), and deploy (`npm exec wrangler deploy`) your application.
|
|
157
|
-
However, this tutorial will show you how to go a step further and add an API Worker.
|
|
158
|
-
|
|
159
|
-
### Add an API Worker
|
|
160
|
-
|
|
161
|
-
#### Configure TypeScript for your Worker code
|
|
162
|
-
|
|
163
|
-
```sh
|
|
164
|
-
npm install @cloudflare/workers-types --save-dev
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
```jsonc
|
|
168
|
-
// tsconfig.worker.json
|
|
169
|
-
|
|
170
|
-
{
|
|
171
|
-
"extends": "./tsconfig.node.json",
|
|
172
|
-
"compilerOptions": {
|
|
173
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo",
|
|
174
|
-
"types": ["@cloudflare/workers-types/2023-07-01", "vite/client"],
|
|
175
|
-
},
|
|
176
|
-
"include": ["api"],
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
```jsonc
|
|
181
|
-
// tsconfig.json
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
"files": [],
|
|
185
|
-
"references": [
|
|
186
|
-
{ "path": "./tsconfig.app.json" },
|
|
187
|
-
{ "path": "./tsconfig.node.json" },
|
|
188
|
-
{ "path": "./tsconfig.worker.json" },
|
|
189
|
-
],
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
#### Add to your Worker configuration
|
|
194
|
-
|
|
195
|
-
```toml
|
|
196
|
-
# wrangler.toml
|
|
197
|
-
|
|
198
|
-
name = "cloudflare-vite-tutorial"
|
|
199
|
-
compatibility_date = "2024-12-30"
|
|
200
|
-
assets = { not_found_handling = "single-page-application", binding = "ASSETS" }
|
|
201
|
-
main = "./api/index.ts"
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
The assets `binding` defined here will allow you to access the assets functionality from your Worker.
|
|
205
|
-
|
|
206
|
-
#### Add your API Worker
|
|
207
|
-
|
|
208
|
-
```ts
|
|
209
|
-
// api/index.ts
|
|
210
|
-
|
|
211
|
-
interface Env {
|
|
212
|
-
ASSETS: Fetcher;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export default {
|
|
216
|
-
fetch(request, env) {
|
|
217
|
-
const url = new URL(request.url);
|
|
218
|
-
|
|
219
|
-
if (url.pathname.startsWith("/api/")) {
|
|
220
|
-
return Response.json({
|
|
221
|
-
name: "Cloudflare",
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return env.ASSETS.fetch(request);
|
|
226
|
-
},
|
|
227
|
-
} satisfies ExportedHandler<Env>;
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
The Worker above will be invoked for any request not matching a static asset.
|
|
231
|
-
It returns a JSON response if the `pathname` starts with `/api/` and otherwise passes the incoming request through to the assets binding.
|
|
232
|
-
This means that for paths that do not start with `/api/`, the `not_found_handling` behavior defined in the Worker config will be evaluated and the `index.html` file will be returned, enabling SPA navigations.
|
|
233
|
-
|
|
234
|
-
#### Call the API from the client
|
|
235
|
-
|
|
236
|
-
Edit `src/App.tsx` so that it includes an additional button that calls the API and sets some state.
|
|
237
|
-
Replace the file contents with the following code:
|
|
238
|
-
|
|
239
|
-
```tsx
|
|
240
|
-
// src/App.tsx
|
|
241
|
-
|
|
242
|
-
import { useState } from "react";
|
|
243
|
-
import reactLogo from "./assets/react.svg";
|
|
244
|
-
import viteLogo from "/vite.svg";
|
|
245
|
-
import "./App.css";
|
|
246
|
-
|
|
247
|
-
function App() {
|
|
248
|
-
const [count, setCount] = useState(0);
|
|
249
|
-
const [name, setName] = useState("unknown");
|
|
250
|
-
|
|
251
|
-
return (
|
|
252
|
-
<>
|
|
253
|
-
<div>
|
|
254
|
-
<a href="https://vite.dev" target="_blank">
|
|
255
|
-
<img src={viteLogo} className="logo" alt="Vite logo" />
|
|
256
|
-
</a>
|
|
257
|
-
<a href="https://react.dev" target="_blank">
|
|
258
|
-
<img src={reactLogo} className="logo react" alt="React logo" />
|
|
259
|
-
</a>
|
|
260
|
-
</div>
|
|
261
|
-
<h1>Vite + React</h1>
|
|
262
|
-
<div className="card">
|
|
263
|
-
<button
|
|
264
|
-
onClick={() => setCount((count) => count + 1)}
|
|
265
|
-
aria-label="increment"
|
|
266
|
-
>
|
|
267
|
-
count is {count}
|
|
268
|
-
</button>
|
|
269
|
-
<p>
|
|
270
|
-
Edit <code>src/App.tsx</code> and save to test HMR
|
|
271
|
-
</p>
|
|
272
|
-
</div>
|
|
273
|
-
<div className="card">
|
|
274
|
-
<button
|
|
275
|
-
onClick={() => {
|
|
276
|
-
fetch("/api/")
|
|
277
|
-
.then((res) => res.json() as Promise<{ name: string }>)
|
|
278
|
-
.then((data) => setName(data.name));
|
|
279
|
-
}}
|
|
280
|
-
aria-label="get name"
|
|
281
|
-
>
|
|
282
|
-
Name from API is: {name}
|
|
283
|
-
</button>
|
|
284
|
-
<p>
|
|
285
|
-
Edit <code>api/index.ts</code> to change the name
|
|
286
|
-
</p>
|
|
287
|
-
</div>
|
|
288
|
-
<p className="read-the-docs">
|
|
289
|
-
Click on the Vite and React logos to learn more
|
|
290
|
-
</p>
|
|
291
|
-
</>
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export default App;
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
Now, if you click the button, it will display 'Name from API is: Cloudflare'.
|
|
299
|
-
|
|
300
|
-
Increment the counter to update the application state in the browser.
|
|
301
|
-
Next, edit `api/index.ts` by changing the `name` it returns to `'Cloudflare Workers'`.
|
|
302
|
-
If you click the button again, it will display the new `name` while preserving the previously set counter value.
|
|
303
|
-
With Vite and the Cloudflare plugin, you can iterate on the client and server parts of your app quickly without losing UI state between edits.
|
|
304
|
-
|
|
305
|
-
#### Build your application
|
|
306
|
-
|
|
307
|
-
Run `npm run build` to build your application.
|
|
308
|
-
|
|
309
|
-
If you inspect the `dist` directory, you will see that it contains two subdirectories: `client` and `cloudflare-vite-tutorial`.
|
|
310
|
-
The `cloudflare-vite-tutorial` directory contains your Worker code and the output `wrangler.json` configuration.
|
|
311
|
-
|
|
312
|
-
#### Preview your application
|
|
313
|
-
|
|
314
|
-
Run `npm run preview` to validate that your application runs as expected.
|
|
315
|
-
This command will run your build output locally in the Workers runtime, closely matching its behaviour in production.
|
|
316
|
-
|
|
317
|
-
#### Deploy to Cloudflare
|
|
318
|
-
|
|
319
|
-
Run `npm exec wrangler deploy` to deploy your application to Cloudflare.
|
|
320
|
-
This command will automatically use the output `wrangler.json` that was included in the build output.
|
|
321
|
-
|
|
322
|
-
### Next steps
|
|
323
|
-
|
|
324
|
-
In this tutorial, we created an SPA that could be deployed as a Worker with Workers Assets.
|
|
325
|
-
We then added an API Worker that could be accessed from the front-end code and deployed to Cloudflare.
|
|
326
|
-
Possible next steps include:
|
|
327
|
-
|
|
328
|
-
- Adding a binding to another Cloudflare service such as a [KV namespace](https://developers.cloudflare.com/kv/) or [D1 database](https://developers.cloudflare.com/d1/)
|
|
329
|
-
- Expanding the API to include additional routes
|
|
330
|
-
- Using a library, such as [tRPC](https://trpc.io/) or [Hono](https://hono.dev/), in your API Worker
|
|
331
|
-
|
|
332
|
-
## API
|
|
333
|
-
|
|
334
|
-
### `cloudflare`
|
|
335
|
-
|
|
336
|
-
The `cloudflare` plugin should be included in the Vite `plugins` array:
|
|
337
|
-
|
|
338
6
|
```ts
|
|
339
7
|
// vite.config.ts
|
|
340
8
|
|
|
@@ -346,215 +14,22 @@ export default defineConfig({
|
|
|
346
14
|
});
|
|
347
15
|
```
|
|
348
16
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
### `interface PluginConfig`
|
|
352
|
-
|
|
353
|
-
- `configPath?: string`
|
|
354
|
-
|
|
355
|
-
An optional path to your Worker config file.
|
|
356
|
-
By default, a `wrangler.toml`, `wrangler.json`, or `wrangler.jsonc` file in the root of your application will be used as the Worker config.
|
|
357
|
-
|
|
358
|
-
- `viteEnvironment?: { name?: string }`
|
|
359
|
-
|
|
360
|
-
Optional Vite environment options.
|
|
361
|
-
By default, the environment name is the Worker name with `-` characters replaced with `_`.
|
|
362
|
-
Setting the name here will override this.
|
|
363
|
-
|
|
364
|
-
- `persistState?: boolean | { path: string }`
|
|
365
|
-
|
|
366
|
-
An optional override for state persistence.
|
|
367
|
-
By default, state is persisted to `.wrangler/state` in a `v3` subdirectory.
|
|
368
|
-
A custom `path` can be provided or, alternatively, persistence can be disabled by setting the value to `false`.
|
|
369
|
-
|
|
370
|
-
- `auxiliaryWorkers?: Array<AuxiliaryWorkerConfig>`
|
|
371
|
-
|
|
372
|
-
An optional array of auxiliary workers.
|
|
373
|
-
You can use [service bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) to call auxiliary workers from your main (entry) Worker.
|
|
374
|
-
All requests are routed through your entry Worker.
|
|
375
|
-
During the build, each Worker is output to a separate subdirectory of `dist`.
|
|
376
|
-
|
|
377
|
-
- `inspectorPort?: number | false`
|
|
378
|
-
|
|
379
|
-
Optional inspector port to use for debugging your workers, for more details on debugging see the [devtools section](#devtools). By default the vite plugin will attempt to use the first available port it can find starting at `9229`.
|
|
380
|
-
|
|
381
|
-
> [!NOTE]
|
|
382
|
-
> When running `wrangler deploy`, only your main (entry) Worker will be deployed.
|
|
383
|
-
> If using multiple Workers, each must be deployed individually.
|
|
384
|
-
> You can inspect the `dist` directory and then run `wrangler deploy -c path-to-worker-output-config` for each.
|
|
385
|
-
|
|
386
|
-
### `interface AuxiliaryWorkerConfig`
|
|
387
|
-
|
|
388
|
-
- `configPath: string`
|
|
389
|
-
|
|
390
|
-
A required path to your Worker config file.
|
|
391
|
-
|
|
392
|
-
- `viteEnvironment?: { name?: string }`
|
|
393
|
-
|
|
394
|
-
Optional Vite environment options.
|
|
395
|
-
By default, the environment name is the Worker name with `-` characters replaced with `_`.
|
|
396
|
-
Setting the name here will override this.
|
|
397
|
-
|
|
398
|
-
## Cloudflare environments
|
|
399
|
-
|
|
400
|
-
A Worker config file may contain configuration for multiple [Cloudflare environments](https://developers.cloudflare.com/workers/wrangler/environments/).
|
|
401
|
-
With the Cloudflare Vite plugin, you select a Cloudflare environment at dev or build time by providing the `CLOUDFLARE_ENV` environment variable.
|
|
402
|
-
Consider the following example `wrangler.toml` file:
|
|
403
|
-
|
|
404
|
-
```toml
|
|
405
|
-
# wrangler.toml
|
|
406
|
-
|
|
407
|
-
name = "my-worker"
|
|
408
|
-
compatibility_date = "2024-12-30"
|
|
409
|
-
main = "./src/index.ts"
|
|
410
|
-
|
|
411
|
-
vars = { MY_VAR = "Top-level var" }
|
|
412
|
-
|
|
413
|
-
[env.staging]
|
|
414
|
-
vars = { MY_VAR = "Staging var" }
|
|
415
|
-
|
|
416
|
-
[env.production]
|
|
417
|
-
vars = { MY_VAR = "Production var" }
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
If you run `CLOUDFLARE_ENV=production vite build` then the output `wrangler.json` file generated by the build will be a flattened configuration for the 'production' Cloudflare environment.
|
|
421
|
-
This combines [top-level only](https://developers.cloudflare.com/workers/wrangler/configuration/#top-level-only-keys), [inheritable](https://developers.cloudflare.com/workers/wrangler/configuration/#inheritable-keys), and [non-inheritable](https://developers.cloudflare.com/workers/wrangler/configuration/#non-inheritable-keys) keys.
|
|
422
|
-
The value of `MY_VAR` will therefore be `'Production var'`.
|
|
423
|
-
The name of the Worker will be `'my-worker-production'`.
|
|
424
|
-
This is because the environment name is automatically appended to the top-level Worker name.
|
|
425
|
-
|
|
426
|
-
> [!NOTE]
|
|
427
|
-
> The default Vite environment name for a Worker is always the top-level Worker name.
|
|
428
|
-
> This enables you to reference the Worker consistently in your Vite config when using multiple Cloudflare environments.
|
|
429
|
-
|
|
430
|
-
Cloudflare environments can also be used in development.
|
|
431
|
-
For example, you could run `CLOUDFLARE_ENV=development vite dev`.
|
|
432
|
-
It is common to use the default top-level environment as the development environment and then add additional environments as necessary.
|
|
433
|
-
|
|
434
|
-
> [!NOTE]
|
|
435
|
-
> Running `vite dev` or `vite build` without providing `CLOUDFLARE_ENV` will use the default top-level Cloudflare environment.
|
|
436
|
-
> The value of `MY_VAR` will therefore be `'Top-level var'`.
|
|
437
|
-
> As Cloudflare environments are applied at dev and build time, specifying `CLOUDFLARE_ENV` when running `vite preview` or `wrangler deploy` will have no effect.
|
|
438
|
-
|
|
439
|
-
### Combining Cloudflare environments and Vite modes
|
|
440
|
-
|
|
441
|
-
You may wish to combine the concepts of [Cloudflare environments](https://developers.cloudflare.com/workers/wrangler/environments/) and [Vite modes](https://vite.dev/guide/env-and-mode.html#modes).
|
|
442
|
-
With this approach, the Vite mode can be used to select the Cloudflare environment and a single method can be used to determine environment specific configuration and code.
|
|
443
|
-
Consider again the previous example:
|
|
444
|
-
|
|
445
|
-
```toml
|
|
446
|
-
# wrangler.toml
|
|
447
|
-
|
|
448
|
-
name = "my-worker"
|
|
449
|
-
compatibility_date = "2024-12-30"
|
|
450
|
-
main = "./src/index.ts"
|
|
451
|
-
|
|
452
|
-
vars = { MY_VAR = "Top-level var" }
|
|
453
|
-
|
|
454
|
-
[env.staging]
|
|
455
|
-
vars = { MY_VAR = "Staging var" }
|
|
456
|
-
|
|
457
|
-
[env.production]
|
|
458
|
-
vars = { MY_VAR = "Production var" }
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
Next, provide `.env.staging` and `.env.production` files:
|
|
462
|
-
|
|
463
|
-
```sh
|
|
464
|
-
# .env.staging
|
|
465
|
-
|
|
466
|
-
CLOUDFLARE_ENV=staging
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
```sh
|
|
470
|
-
# .env.production
|
|
471
|
-
|
|
472
|
-
CLOUDFLARE_ENV=production
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
By default, `vite build` uses the 'production' Vite mode.
|
|
476
|
-
Vite will therefore load the `.env.production` file to get the environment variables that are used in the build.
|
|
477
|
-
Since the `.env.production` file contains `CLOUDFLARE_ENV=production`, the Cloudflare Vite plugin will select the 'production' Cloudflare environment.
|
|
478
|
-
The value of `MY_VAR` will therefore be `'Production var'`.
|
|
479
|
-
If you run `vite build --mode staging` then the 'staging' Vite mode will be used and the 'staging' Cloudflare environment will be selected.
|
|
480
|
-
The value of `MY_VAR` will therefore be `'Staging var'`.
|
|
481
|
-
|
|
482
|
-
## Secrets
|
|
17
|
+
## Documentation
|
|
483
18
|
|
|
484
|
-
|
|
19
|
+
Full documentation can be found [here](https://developers.cloudflare.com/workers/vite-plugin/).
|
|
485
20
|
|
|
486
|
-
|
|
487
|
-
> The `vite build` command copies the relevant `.dev.vars[.env-name]` file to the output directory. This is only used when running `vite preview` and is not deployed with your Worker.
|
|
21
|
+
## Features
|
|
488
22
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
There are two recommended ways of doing so, which we'll explore in this section.
|
|
496
|
-
|
|
497
|
-
### Devtools
|
|
498
|
-
|
|
499
|
-
When running `vite dev` or `vite preview` a `/__debug` route in your local server will be made available which gives you access to [Cloudflare's implementation](/packages/chrome-devtools-patches) of [Chrome's DevTools](https://developer.chrome.com/docs/devtools/overview).
|
|
500
|
-
|
|
501
|
-
Navigating to this route will open a devtools tab for each of the workers in your application (Note: in case of multiple workers you might need to allow your browser to open pop-ups).
|
|
502
|
-
|
|
503
|
-
Once the tab or tabs are open, you can make a request to your application and start debugging your workers' code.
|
|
504
|
-
|
|
505
|
-
Note: If you're not interested in debugging all your workers you can close the tabs of the workers you don't want to debug.
|
|
506
|
-
|
|
507
|
-
### VS Code
|
|
508
|
-
|
|
509
|
-
To setup VS Code for breakpoint debugging for your application, you will need to create a `.vscode/launch.json` file that contains a configuration following this structure:
|
|
510
|
-
|
|
511
|
-
```json
|
|
512
|
-
{
|
|
513
|
-
"configurations": [
|
|
514
|
-
{
|
|
515
|
-
"name": "<NAME_OF_WORKER>",
|
|
516
|
-
"type": "node",
|
|
517
|
-
"request": "attach",
|
|
518
|
-
"websocketAddress": "ws://localhost:9229/<NAME_OF_WORKER>",
|
|
519
|
-
"resolveSourceMapLocations": null,
|
|
520
|
-
"attachExistingChildren": false,
|
|
521
|
-
"autoAttachChildProcesses": false,
|
|
522
|
-
"sourceMaps": true
|
|
523
|
-
}
|
|
524
|
-
],
|
|
525
|
-
"compounds": [
|
|
526
|
-
{
|
|
527
|
-
"name": "Debug All Workers",
|
|
528
|
-
"configurations": ["<NAME_OF_WORKER>"],
|
|
529
|
-
"stopAll": true
|
|
530
|
-
}
|
|
531
|
-
]
|
|
532
|
-
}
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
Where, `<NAME_OF_WORKER>` indicates the name of your worker as specified in your Wrangler configuration.
|
|
536
|
-
|
|
537
|
-
Note: if you customized your `inspectorPort` you need to use that port in the `websocketAddress` field.
|
|
538
|
-
|
|
539
|
-
If you have more than one worker you need add a configuration in the `configurations` field for each one and then include the configuration name in the `configurations` array in the compound configuration.
|
|
540
|
-
|
|
541
|
-
Once your `launch.json` file is ready, after running `vite dev` or `vite preview` you can select **Debug All Workers** at the top of the **Run & Debug** panel to attach debuggers to all the various Workers. Then you can add breakpoints to your code and start debugging.
|
|
542
|
-
|
|
543
|
-
Note: You can also manually select the configurations to run (e.g. **Debug Worker1**) to filter which workers you want to debug.
|
|
544
|
-
|
|
545
|
-
## Migrating from `wrangler dev`
|
|
546
|
-
|
|
547
|
-
Migrating from `wrangler dev` is a simple process and you can follow the instructions in the [Quick start](#quick-start) to get started.
|
|
548
|
-
There are a few key differences to highlight:
|
|
549
|
-
|
|
550
|
-
### Input and output Worker config files
|
|
551
|
-
|
|
552
|
-
In the Vite integration, your Worker config file (for example, `wrangler.toml`) is the input configuration and a separate output configuration is created as part of the build.
|
|
553
|
-
This output file is a snapshot of your configuration at the time of the build and is modified to reference your build artifacts.
|
|
554
|
-
It is the configuration that is used for preview and deployment.
|
|
23
|
+
- Uses the Vite [Environment API](https://vite.dev/guide/api-environment) to integrate Vite with the Workers runtime
|
|
24
|
+
- Provides direct access to [Workers runtime APIs](https://developers.cloudflare.com/workers/runtime-apis/) and [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/)
|
|
25
|
+
- Builds your front-end assets for deployment to Cloudflare, enabling you to build static sites, SPAs, and full-stack applications
|
|
26
|
+
- Official support for [React Router v7](https://reactrouter.com/) with server-side rendering
|
|
27
|
+
- Leverages Vite's hot module replacement for consistently fast updates
|
|
28
|
+
- Supports `vite preview` for previewing your build output in the Workers runtime prior to deployment
|
|
555
29
|
|
|
556
|
-
|
|
30
|
+
## Use cases
|
|
557
31
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
32
|
+
- React Router v7 (support for more full-stack frameworks is coming soon)
|
|
33
|
+
- Static sites, such as single-page applications, with or without an integrated backend API
|
|
34
|
+
- Standalone Workers
|
|
35
|
+
- Multi-Worker applications
|
package/dist/index.js
CHANGED
|
@@ -485,7 +485,7 @@ var require_mime = __commonJS({
|
|
|
485
485
|
});
|
|
486
486
|
|
|
487
487
|
// src/index.ts
|
|
488
|
-
import
|
|
488
|
+
import assert10 from "node:assert";
|
|
489
489
|
import * as fs5 from "node:fs";
|
|
490
490
|
import * as fsp2 from "node:fs/promises";
|
|
491
491
|
import * as path9 from "node:path";
|
|
@@ -13828,8 +13828,7 @@ var nonApplicableWorkerConfigs = {
|
|
|
13828
13828
|
"preserve_file_names",
|
|
13829
13829
|
"rules",
|
|
13830
13830
|
"site",
|
|
13831
|
-
"tsconfig"
|
|
13832
|
-
"upload_source_maps"
|
|
13831
|
+
"tsconfig"
|
|
13833
13832
|
]
|
|
13834
13833
|
};
|
|
13835
13834
|
var nullableNonApplicable = [
|
|
@@ -13840,8 +13839,7 @@ var nullableNonApplicable = [
|
|
|
13840
13839
|
"no_bundle",
|
|
13841
13840
|
"preserve_file_names",
|
|
13842
13841
|
"site",
|
|
13843
|
-
"tsconfig"
|
|
13844
|
-
"upload_source_maps"
|
|
13842
|
+
"tsconfig"
|
|
13845
13843
|
];
|
|
13846
13844
|
function readWorkerConfig(configPath, env2) {
|
|
13847
13845
|
const nonApplicable = {
|
|
@@ -14174,6 +14172,54 @@ function handleWebSocket(httpServer, getFetcher) {
|
|
|
14174
14172
|
);
|
|
14175
14173
|
}
|
|
14176
14174
|
|
|
14175
|
+
// src/worker-environments-validation.ts
|
|
14176
|
+
import assert9 from "node:assert";
|
|
14177
|
+
function validateWorkerEnvironmentsResolvedConfigs(resolvedPluginConfig, resolvedViteConfig) {
|
|
14178
|
+
const workersEnvironmentNames = Object.keys(resolvedPluginConfig.workers);
|
|
14179
|
+
const disallowedEnvsConfigs = /* @__PURE__ */ new Map();
|
|
14180
|
+
for (const envName of workersEnvironmentNames) {
|
|
14181
|
+
const workerEnvConfig = resolvedViteConfig.environments[envName];
|
|
14182
|
+
assert9(workerEnvConfig, `Missing environment config for "${envName}"`);
|
|
14183
|
+
const { optimizeDeps, resolve: resolve8 } = workerEnvConfig;
|
|
14184
|
+
const disallowedConfig = {};
|
|
14185
|
+
const disallowedOptimizeDepsExcludeEntries = (optimizeDeps.exclude ?? []).filter((entry) => {
|
|
14186
|
+
if (cloudflareBuiltInModules.includes(entry)) {
|
|
14187
|
+
return false;
|
|
14188
|
+
}
|
|
14189
|
+
if (NODEJS_MODULES_RE.test(entry) && isNodeCompat(resolvedPluginConfig.workers[envName])) {
|
|
14190
|
+
return false;
|
|
14191
|
+
}
|
|
14192
|
+
return true;
|
|
14193
|
+
});
|
|
14194
|
+
if (disallowedOptimizeDepsExcludeEntries.length > 0) {
|
|
14195
|
+
disallowedConfig.optimizeDepsExclude = disallowedOptimizeDepsExcludeEntries;
|
|
14196
|
+
}
|
|
14197
|
+
if (resolve8.external === true || resolve8.external.length > 0) {
|
|
14198
|
+
disallowedConfig.resolveExternal = resolve8.external;
|
|
14199
|
+
}
|
|
14200
|
+
if (Object.keys(disallowedConfig).length > 0) {
|
|
14201
|
+
disallowedEnvsConfigs.set(envName, disallowedConfig);
|
|
14202
|
+
}
|
|
14203
|
+
}
|
|
14204
|
+
if (disallowedEnvsConfigs.size > 0) {
|
|
14205
|
+
const errorMessage = `The following environment configurations are incompatible with the Cloudflare Vite plugin:
|
|
14206
|
+
${[
|
|
14207
|
+
...disallowedEnvsConfigs
|
|
14208
|
+
].map(
|
|
14209
|
+
([envName, disallowedConfig]) => [
|
|
14210
|
+
disallowedConfig.optimizeDepsExclude ? ` - "${envName}" environment: \`optimizeDeps.exclude\`: ${JSON.stringify(disallowedConfig.optimizeDepsExclude)}
|
|
14211
|
+
` : null,
|
|
14212
|
+
disallowedConfig.resolveExternal ? ` - "${envName}" environment: \`resolve.external\`: ${JSON.stringify(disallowedConfig.resolveExternal)}
|
|
14213
|
+
` : null
|
|
14214
|
+
].join("")
|
|
14215
|
+
).join(
|
|
14216
|
+
""
|
|
14217
|
+
)}To resolve this issue, avoid setting \`optimizeDeps.exclude\` and \`resolve.external\` in your Cloudflare Worker environments.
|
|
14218
|
+
`;
|
|
14219
|
+
throw new Error(errorMessage);
|
|
14220
|
+
}
|
|
14221
|
+
}
|
|
14222
|
+
|
|
14177
14223
|
// src/index.ts
|
|
14178
14224
|
var workersConfigsWarningShown = false;
|
|
14179
14225
|
var miniflare;
|
|
@@ -14244,7 +14290,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14244
14290
|
resolvedPluginConfig.workers
|
|
14245
14291
|
).map((environmentName) => {
|
|
14246
14292
|
const environment = builder.environments[environmentName];
|
|
14247
|
-
|
|
14293
|
+
assert10(
|
|
14248
14294
|
environment,
|
|
14249
14295
|
`${environmentName} environment not found`
|
|
14250
14296
|
);
|
|
@@ -14265,6 +14311,12 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14265
14311
|
},
|
|
14266
14312
|
configResolved(config) {
|
|
14267
14313
|
resolvedViteConfig = config;
|
|
14314
|
+
if (resolvedPluginConfig?.type === "workers") {
|
|
14315
|
+
validateWorkerEnvironmentsResolvedConfigs(
|
|
14316
|
+
resolvedPluginConfig,
|
|
14317
|
+
resolvedViteConfig
|
|
14318
|
+
);
|
|
14319
|
+
}
|
|
14268
14320
|
},
|
|
14269
14321
|
generateBundle(_, bundle) {
|
|
14270
14322
|
let config;
|
|
@@ -14285,7 +14337,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14285
14337
|
if (isEntryWorker && hasClientBuild) {
|
|
14286
14338
|
const workerOutputDirectory = this.environment.config.build.outDir;
|
|
14287
14339
|
const clientOutputDirectory = resolvedViteConfig.environments.client?.build.outDir;
|
|
14288
|
-
|
|
14340
|
+
assert10(
|
|
14289
14341
|
clientOutputDirectory,
|
|
14290
14342
|
"Unexpected error: client output directory is undefined"
|
|
14291
14343
|
);
|
|
@@ -14362,16 +14414,16 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14362
14414
|
}
|
|
14363
14415
|
},
|
|
14364
14416
|
async configureServer(viteDevServer) {
|
|
14365
|
-
|
|
14417
|
+
assert10(
|
|
14366
14418
|
viteDevServer.httpServer,
|
|
14367
14419
|
"Unexpected error: No Vite HTTP server"
|
|
14368
14420
|
);
|
|
14369
|
-
|
|
14370
|
-
|
|
14371
|
-
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14421
|
+
if (!miniflare) {
|
|
14422
|
+
const inputInspectorPort = await getInputInspectorPortOption(
|
|
14423
|
+
pluginConfig,
|
|
14424
|
+
viteDevServer
|
|
14425
|
+
);
|
|
14426
|
+
miniflare = new Miniflare(
|
|
14375
14427
|
getDevMiniflareOptions(
|
|
14376
14428
|
resolvedPluginConfig,
|
|
14377
14429
|
viteDevServer,
|
|
@@ -14379,18 +14431,19 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14379
14431
|
)
|
|
14380
14432
|
);
|
|
14381
14433
|
} else {
|
|
14382
|
-
|
|
14434
|
+
const resolvedInspectorPort = await getResolvedInspectorPort(pluginConfig);
|
|
14435
|
+
await miniflare.setOptions(
|
|
14383
14436
|
getDevMiniflareOptions(
|
|
14384
14437
|
resolvedPluginConfig,
|
|
14385
14438
|
viteDevServer,
|
|
14386
|
-
|
|
14439
|
+
resolvedInspectorPort ?? false
|
|
14387
14440
|
)
|
|
14388
14441
|
);
|
|
14389
14442
|
}
|
|
14390
14443
|
await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
|
|
14391
14444
|
const middleware = createMiddleware(
|
|
14392
14445
|
async ({ request }) => {
|
|
14393
|
-
|
|
14446
|
+
assert10(miniflare, `Miniflare not defined`);
|
|
14394
14447
|
const routerWorker = await getRouterWorker(miniflare);
|
|
14395
14448
|
return routerWorker.fetch(toMiniflareRequest(request), {
|
|
14396
14449
|
redirect: "manual"
|
|
@@ -14399,7 +14452,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14399
14452
|
{ alwaysCallNext: false }
|
|
14400
14453
|
);
|
|
14401
14454
|
handleWebSocket(viteDevServer.httpServer, async () => {
|
|
14402
|
-
|
|
14455
|
+
assert10(miniflare, `Miniflare not defined`);
|
|
14403
14456
|
const routerWorker = await getRouterWorker(miniflare);
|
|
14404
14457
|
return routerWorker.fetch;
|
|
14405
14458
|
});
|
|
@@ -14499,7 +14552,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14499
14552
|
for (const match of matches) {
|
|
14500
14553
|
magicString ??= new MagicString(code);
|
|
14501
14554
|
const [full, _, modulePath] = match;
|
|
14502
|
-
|
|
14555
|
+
assert10(
|
|
14503
14556
|
modulePath,
|
|
14504
14557
|
`Unexpected error: module path not found in reference ${full}.`
|
|
14505
14558
|
);
|
|
@@ -14572,7 +14625,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14572
14625
|
return this.resolve(source, importer, options);
|
|
14573
14626
|
}
|
|
14574
14627
|
if (this.environment.mode === "dev") {
|
|
14575
|
-
|
|
14628
|
+
assert10(
|
|
14576
14629
|
this.environment.depsOptimizer,
|
|
14577
14630
|
"depsOptimizer is required in dev mode"
|
|
14578
14631
|
);
|
|
@@ -14586,7 +14639,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14586
14639
|
},
|
|
14587
14640
|
async transform(code, id) {
|
|
14588
14641
|
const workerConfig = getWorkerConfig2(this.environment.name);
|
|
14589
|
-
|
|
14642
|
+
assert10(workerConfig, "Expected a worker config");
|
|
14590
14643
|
const resolvedId = await this.resolve(workerConfig.main);
|
|
14591
14644
|
if (id === resolvedId?.id) {
|
|
14592
14645
|
return injectGlobalCode(id, code);
|
|
@@ -14644,7 +14697,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14644
14697
|
addDebugToVitePrintUrls(vitePreviewServer);
|
|
14645
14698
|
}
|
|
14646
14699
|
const workerNames = workerConfigs.map((worker) => {
|
|
14647
|
-
|
|
14700
|
+
assert10(worker.name, "Expected the Worker to have a name");
|
|
14648
14701
|
return worker.name;
|
|
14649
14702
|
});
|
|
14650
14703
|
vitePreviewServer.middlewares.use(async (req, res, next) => {
|
|
@@ -14722,7 +14775,7 @@ function cloudflare2(pluginConfig = {}) {
|
|
|
14722
14775
|
}
|
|
14723
14776
|
];
|
|
14724
14777
|
function getWorkerConfig2(environmentName) {
|
|
14725
|
-
|
|
14778
|
+
assert10(resolvedPluginConfig, "Expected resolvedPluginConfig to be defined");
|
|
14726
14779
|
return resolvedPluginConfig.type !== "assets-only" ? resolvedPluginConfig.workers[environmentName] : void 0;
|
|
14727
14780
|
}
|
|
14728
14781
|
}
|
|
@@ -1394,13 +1394,6 @@ async function createModuleRunner(env, webSocket, viteRoot) {
|
|
|
1394
1394
|
},
|
|
1395
1395
|
{
|
|
1396
1396
|
async runInlinedModule(context, transformed, module) {
|
|
1397
|
-
if (module.file.includes("/node_modules") && !module.file.includes("/node_modules/.vite")) {
|
|
1398
|
-
throw new Error(
|
|
1399
|
-
`[Error] Trying to import non-prebundled module (only prebundled modules are allowed): ${module.id}
|
|
1400
|
-
|
|
1401
|
-
(have you excluded the module via \`optimizeDeps.exclude\`?)`
|
|
1402
|
-
);
|
|
1403
|
-
}
|
|
1404
1397
|
const codeDefinition = `'use strict';async (${Object.keys(context).join(
|
|
1405
1398
|
","
|
|
1406
1399
|
)})=>{{`;
|
|
@@ -1426,13 +1419,6 @@ async function createModuleRunner(env, webSocket, viteRoot) {
|
|
|
1426
1419
|
)
|
|
1427
1420
|
});
|
|
1428
1421
|
}
|
|
1429
|
-
if (!additionalModuleRE.test(filepath) && filepath.includes("/node_modules") && !filepath.includes("/node_modules/.vite")) {
|
|
1430
|
-
throw new Error(
|
|
1431
|
-
`[Error] Trying to import non-prebundled module (only prebundled modules are allowed): ${filepath}
|
|
1432
|
-
|
|
1433
|
-
(have you externalized the module via \`resolve.external\`?)`
|
|
1434
|
-
);
|
|
1435
|
-
}
|
|
1436
1422
|
filepath = filepath.replace(/^file:\/\//, "");
|
|
1437
1423
|
return import(filepath);
|
|
1438
1424
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/vite-plugin",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-3af2e30f8",
|
|
4
4
|
"description": "Cloudflare plugin for Vite",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"tinyglobby": "^0.2.12",
|
|
40
40
|
"unenv": "2.0.0-rc.15",
|
|
41
41
|
"ws": "8.18.0",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
42
|
+
"miniflare": "0.0.0-3af2e30f8",
|
|
43
|
+
"wrangler": "0.0.0-3af2e30f8",
|
|
44
|
+
"@cloudflare/unenv-preset": "0.0.0-3af2e30f8"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@cloudflare/workers-types": "^4.
|
|
47
|
+
"@cloudflare/workers-types": "^4.20250404.0",
|
|
48
48
|
"@types/node": "^22.10.1",
|
|
49
49
|
"@types/ws": "^8.5.13",
|
|
50
50
|
"magic-string": "^0.30.12",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"undici": "^5.28.5",
|
|
55
55
|
"vite": "^6.1.0",
|
|
56
56
|
"vitest": "~3.0.8",
|
|
57
|
-
"@cloudflare/workers-shared": "0.0.0-39933740e",
|
|
58
57
|
"@cloudflare/mock-npm-registry": "0.0.0",
|
|
58
|
+
"@cloudflare/workers-shared": "0.0.0-3af2e30f8",
|
|
59
59
|
"@cloudflare/workers-tsconfig": "0.0.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|