-
Notifications
You must be signed in to change notification settings - Fork 16
/
.eleventy.js
132 lines (117 loc) · 4.78 KB
/
.eleventy.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
124
125
126
127
128
129
130
131
132
const fs = require("fs/promises");
const path = require("path");
const markdownIt = require("markdown-it");
const INPUT_DIR = "src";
const OUTPUT_DIR = "_site";
// This will change both Eleventy's pathPrefix, and the one output by the
// vite-related shortcodes below. Double-check if you change this, as this is only a demo :)
const PATH_PREFIX = "/";
module.exports = function (eleventyConfig) {
// Disable whitespace-as-code-indicator, which breaks a lot of markup
const configuredMdLibrary = markdownIt({ html: true }).disable("code");
eleventyConfig.setLibrary("md", configuredMdLibrary);
// Read Vite's manifest.json, and add script tags for the entry files
// You could decide to do more things here, such as adding preload/prefetch tags
// for dynamic segments
// NOTE: There is some hard-coding going on here, with regard to the assetDir
// and location of manifest.json
// you could probably read vite.config.js and get that information directly
// @see https://vitejs.dev/guide/backend-integration.html
eleventyConfig.addNunjucksAsyncShortcode("viteScriptTag", viteScriptTag);
eleventyConfig.addNunjucksAsyncShortcode(
"viteLegacyScriptTag",
viteLegacyScriptTag
);
eleventyConfig.addNunjucksAsyncShortcode(
"viteLinkStylesheetTags",
viteLinkStylesheetTags
);
eleventyConfig.addNunjucksAsyncShortcode(
"viteLinkModulePreloadTags",
viteLinkModulePreloadTags
);
async function viteScriptTag(entryFilename) {
const entryChunk = await getChunkInformationFor(entryFilename);
return `<script type="module" src="${PATH_PREFIX}${entryChunk.file}"></script>`;
}
/* Generate link[rel=modulepreload] tags for a script's imports */
/* TODO(fpapado): Consider link[rel=prefetch] for dynamic imports, or some other signifier */
async function viteLinkModulePreloadTags(entryFilename) {
const entryChunk = await getChunkInformationFor(entryFilename);
if (!entryChunk.imports || entryChunk.imports.length === 0) {
console.log(
`The script for ${entryFilename} has no imports. Nothing to preload.`
);
return "";
}
/* There can be multiple import files per entry, so assume many by default */
/* Each entry in .imports is a filename referring to a chunk in the manifest; we must resolve it to get the output path on disk.
*/
const allPreloadTags = await Promise.all(
entryChunk.imports.map(async (importEntryFilename) => {
const chunk = await getChunkInformationFor(importEntryFilename);
return `<link rel="modulepreload" href="${PATH_PREFIX}${chunk.file}"></link>`;
})
);
return allPreloadTags.join("\n");
}
async function viteLinkStylesheetTags(entryFilename) {
const entryChunk = await getChunkInformationFor(entryFilename);
if (!entryChunk.css || entryChunk.css.length === 0) {
console.warn(`No css found for ${entryFilename} entry. Is that correct?`);
return "";
}
/* There can be multiple CSS files per entry, so assume many by default */
return entryChunk.css
.map(
(cssFile) =>
`<link rel="stylesheet" href="${PATH_PREFIX}${cssFile}"></link>`
)
.join("\n");
}
async function viteLegacyScriptTag(entryFilename) {
const entryChunk = await getChunkInformationFor(entryFilename);
return `<script nomodule src="${PATH_PREFIX}${entryChunk.file}"></script>`;
}
async function getChunkInformationFor(entryFilename) {
// We want an entryFilename, because in practice you might have multiple entrypoints
// This is similar to how you specify an entry in development more
if (!entryFilename) {
throw new Error(
"You must specify an entryFilename, so that vite-script can find the correct file."
);
}
// TODO: Consider caching this call, to avoid going to the filesystem every time
const manifest = await fs.readFile(
path.resolve(process.cwd(), "_site", "manifest.json")
);
const parsed = JSON.parse(manifest);
let entryChunk = parsed[entryFilename];
if (!entryChunk) {
const possibleEntries = Object.values(parsed)
.filter((chunk) => chunk.isEntry === true)
.map((chunk) => `"${chunk.src}"`)
.join(`, `);
throw new Error(
`No entry for ${entryFilename} found in _site/manifest.json. Valid entries in manifest: ${possibleEntries}`
);
}
return entryChunk;
}
return {
templateFormats: ["md", "njk", "html"],
pathPrefix: PATH_PREFIX,
markdownTemplateEngine: "njk",
htmlTemplateEngine: "njk",
dataTemplateEngine: "njk",
passthroughFileCopy: true,
dir: {
input: INPUT_DIR,
output: OUTPUT_DIR,
// NOTE: These two paths are relative to dir.input
// @see https://github.com/11ty/eleventy/issues/232
includes: "_includes",
data: "_data",
},
};
};