-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
EleventyVite.js
92 lines (79 loc) · 2.65 KB
/
EleventyVite.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { promises as fsp } from "node:fs";
import path from "node:path";
import { DeepCopy, Merge } from "@11ty/eleventy-utils";
import { build, createServer } from "vite";
/** @type {Required<import(".eleventy.js").EleventyViteOptions>} */
const DEFAULT_OPTIONS = {
tempFolderName: ".11ty-vite",
viteOptions: {
clearScreen: false,
appType: "mpa",
server: {
middlewareMode: true,
},
build: {
emptyOutDir: true,
rollupOptions: {}, // we use this to inject input for MPA build below
},
resolve: {
alias: {
// Allow references to `node_modules` directly for bundling.
"/node_modules": path.resolve(".", "node_modules"),
// Note that bare module specifiers are also supported
},
},
},
};
export default class EleventyVite {
/** @type {import("@11ty/eleventy/src/Util/ProjectDirectories.js").default} */
directories;
/** @type {Required<import(".eleventy.js").EleventyViteOptions>} */
options;
constructor(directories, pluginOptions = {}) {
this.directories = directories;
this.options = Merge({}, DEFAULT_OPTIONS, pluginOptions);
}
getServer() {
/** @type {import("vite").InlineConfig} */
const viteOptions = DeepCopy({}, this.options.viteOptions);
viteOptions.root = this.directories.output;
return createServer(viteOptions);
}
getIgnoreDirectory() {
return path.join(this.options.tempFolderName, "**");
}
async runBuild(input) {
const tempFolderPath = path.resolve(this.options.tempFolderName);
await fsp.rename(this.directories.output, tempFolderPath);
try {
/** @type {import("vite").InlineConfig} */
const viteOptions = DeepCopy({}, this.options.viteOptions);
viteOptions.root = tempFolderPath;
viteOptions.build.rollupOptions.input = input
.filter((entry) => !!entry.outputPath) // filter out `false` serverless routes
.filter((entry) => (entry.outputPath || "").endsWith(".html")) // only html output
.map((entry) => {
if (!entry.outputPath.startsWith(this.directories.output)) {
throw new Error(
`Unexpected output path (was not in output directory ${this.directories.output}): ${entry.outputPath}`,
);
}
return path.resolve(
tempFolderPath,
entry.outputPath.substring(this.directories.output.length),
);
});
viteOptions.build.outDir = path.resolve(".", this.directories.output);
await build(viteOptions);
} catch (error) {
console.warn(
`[11ty] Encountered a Vite build error, restoring original Eleventy output to ${this.directories.output}`,
error,
);
await fsp.rename(tempFolderPath, this.directories.output);
throw error;
} finally {
await fsp.rm(tempFolderPath, { force: true, recursive: true });
}
}
}