-
Notifications
You must be signed in to change notification settings - Fork 417
Expand file tree
/
Copy pathlazy.ts
More file actions
132 lines (115 loc) · 4.13 KB
/
lazy.ts
File metadata and controls
132 lines (115 loc) · 4.13 KB
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
import type { PluginItem } from "@babel/core";
import babel from "@babel/core";
import * as t from "@babel/types";
import { sep as osSep } from "path";
import { basename, relative, sep } from "path/posix";
import type { PluginOption } from "vite";
import { VITE_ENVIRONMENTS } from "./constants.ts";
const idTransform = (id: string): PluginItem => {
return {
visitor: {
Program(path) {
path.node.body.unshift(
t.exportNamedDeclaration(
t.variableDeclaration("const", [
t.variableDeclarator(t.identifier("id$$"), t.stringLiteral(id)),
]),
),
);
},
},
};
};
const importTransform = (): PluginItem => {
return {
visitor: {
ImportDeclaration(path) {
if (path.node.source.value !== "solid-js") return;
path.traverse({
ImportSpecifier(subPath) {
if (subPath.node.local.name !== "lazy") return;
subPath.remove();
path.insertAfter(
t.importDeclaration(
[t.importSpecifier(t.identifier("lazy"), t.identifier("lazy"))],
t.stringLiteral("@solidjs/start/server"),
),
);
},
});
},
},
};
};
const fileEndingRegex = /(ts|js)x(\?.*)?$/;
const lazy = (): PluginOption => {
const cwd = process.cwd().replaceAll(osSep, sep);
/**
* Maps module ids to their client-specific shared chunk names.
* Modules in shared chunks need to find their assets via the chunk name, instead of their module id.
*
* Vite includes assets of such modules in the manifest via the chunk name:
* https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L179
* https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L319
*
* Rollup occassionally creates shared chunks automatically,
* but they can also be manually created by the user via:
* https://rollupjs.org/configuration-options/#output-manualchunks
*
* More infos on Rollup's logic:
* https://github.com/rollup/rollup/issues/3772#issuecomment-689955168
*/
const sharedChunkNames: Record<string, string> = {};
return {
name: "solid-lazy-css",
enforce: "pre",
generateBundle(_, bundle) {
if (this.environment.name !== VITE_ENVIRONMENTS.client) return;
for (const chunk of Object.values(bundle)) {
if (chunk.type !== "chunk" || !chunk.isDynamicEntry || chunk.facadeModuleId) continue;
// Has to follow Vites implementation:
// https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L179
const chunkName = `_${basename(chunk.fileName)}`;
for (const id of chunk.moduleIds) {
sharedChunkNames[id] = chunkName;
}
}
},
async transform(src, id) {
if (this.environment.name !== VITE_ENVIRONMENTS.server) return;
if (!id.match(fileEndingRegex)) return;
// The transformed files either import "lazy" or css files
// Therefore we skip, if the src doesn't have any import
if (src.indexOf("import") === -1) return;
if (id.includes("entry-server")) return;
const plugins: PluginItem[] = [];
const hasDefaultExport = src.indexOf("export default") !== -1;
if (hasDefaultExport) {
const localId = relative(cwd, id);
const chunkName = sharedChunkNames[id];
plugins.push(idTransform(chunkName ?? localId));
}
const hasLazy = src.indexOf("lazy(") !== -1;
if (hasLazy) plugins.push(importTransform());
if (!plugins.length) {
return;
}
const transformed = await babel.transformAsync(src, {
plugins,
parserOpts: {
plugins: ["jsx", "typescript"],
},
filename: basename(id),
ast: false,
sourceMaps: true,
configFile: false,
babelrc: false,
sourceFileName: id,
});
if (!transformed?.code) return;
const { code, map } = transformed;
return { code, map };
},
};
};
export default lazy;