-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathEleventyVite.js
123 lines (106 loc) · 3.47 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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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 {
static LOGGER_PREFIX = "[11ty/eleventy-plugin-vite]";
/** @type {import("@11ty/eleventy/src/Util/ProjectDirectories.js").default} */
directories;
/** @type {import("@11ty/eleventy/src/Util/ConsoleLogger.js").default} */
logger;
/** @type {Required<import(".eleventy.js").EleventyViteOptions>} */
options;
constructor(eleventyConfig, pluginOptions = {}) {
this.directories = eleventyConfig.directories;
this.logger = eleventyConfig.logger;
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);
this.logger.logWithOptions({
prefix: EleventyVite.LOGGER_PREFIX,
message: "Starting Vite build",
type: "info",
});
await build(viteOptions);
this.logger.logWithOptions({
prefix: EleventyVite.LOGGER_PREFIX,
message: "Finished Vite build",
type: "info",
});
} catch (error) {
this.logger.logWithOptions({
prefix: EleventyVite.LOGGER_PREFIX,
message: `Encountered a Vite build error, restoring original Eleventy output to ${this.directories.output}`,
type: "error",
color: "red",
});
this.logger.logWithOptions({
prefix: EleventyVite.LOGGER_PREFIX,
message: "Vite error:",
type: "error",
});
this.logger.logWithOptions({
prefix: EleventyVite.LOGGER_PREFIX,
message: JSON.stringify(error, null, 2),
type: "error",
color: "cyan",
});
await fsp.rename(tempFolderPath, this.directories.output);
throw error;
} finally {
await fsp.rm(tempFolderPath, { force: true, recursive: true });
}
}
}