-
-
Notifications
You must be signed in to change notification settings - Fork 590
/
index.js
125 lines (107 loc) · 3.95 KB
/
index.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
import path from 'path';
import { walk } from 'estree-walker';
import MagicString from 'magic-string';
import fastGlob from 'fast-glob';
import { generate } from 'astring';
import { createFilter } from '@rollup/pluginutils';
import { dynamicImportToGlob, VariableDynamicImportError } from './dynamic-import-to-glob';
function dynamicImportVariables({ include, exclude, warnOnError, errorWhenNoFilesFound } = {}) {
const filter = createFilter(include, exclude);
return {
name: 'rollup-plugin-dynamic-import-variables',
transform(code, id) {
if (!filter(id)) {
return null;
}
const parsed = this.parse(code);
let dynamicImportIndex = -1;
let ms;
walk(parsed, {
enter: (node) => {
if (node.type !== 'ImportExpression') {
return;
}
dynamicImportIndex += 1;
let importArg;
if (node.arguments && node.arguments.length > 0) {
// stringify the argument node, without indents, removing newlines and using single quote strings
importArg = generate(node.arguments[0], { indent: '' })
.replace(/\n/g, '')
.replace(/"/g, "'");
}
try {
// see if this is a variable dynamic import, and generate a glob expression
const glob = dynamicImportToGlob(node.source, code.substring(node.start, node.end));
if (!glob) {
// this was not a variable dynamic import
return;
}
// execute the glob
const result = fastGlob.sync(glob, { cwd: path.dirname(id) });
const paths = result.map((r) =>
r.startsWith('./') || r.startsWith('../') ? r : `./${r}`
);
if (errorWhenNoFilesFound && paths.length === 0) {
const error = new Error(
`No files found in ${glob} when trying to dynamically load concatted string from ${id}`
);
if (warnOnError) {
this.warn(error);
} else {
this.error(error);
}
}
// create magic string if it wasn't created already
ms = ms || new MagicString(code);
// unpack variable dynamic import into a function with import statements per file, rollup
// will turn these into chunks automatically
ms.prepend(
`function __variableDynamicImportRuntime${dynamicImportIndex}__(path) {
switch (path) {
${paths
.map((p) => ` case '${p}': return import('${p}'${importArg ? `, ${importArg}` : ''});`)
.join('\n')}
${` default: return new Promise(function(resolve, reject) {
(typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)(
reject.bind(null, new Error("Unknown variable dynamic import: " + path))
);
})\n`} }
}\n\n`
);
// call the runtime function instead of doing a dynamic import, the import specifier will
// be evaluated at runtime and the correct import will be returned by the injected function
ms.overwrite(
node.start,
node.start + 6,
`__variableDynamicImportRuntime${dynamicImportIndex}__`
);
} catch (error) {
if (error instanceof VariableDynamicImportError) {
// TODO: line number
if (warnOnError) {
this.warn(error);
} else {
this.error(error);
}
} else {
this.error(error);
}
}
}
});
if (ms && dynamicImportIndex !== -1) {
return {
code: ms.toString(),
map: ms.generateMap({
file: id,
includeContent: true,
hires: true
})
};
}
return null;
}
};
}
export default dynamicImportVariables;
export { dynamicImportToGlob, VariableDynamicImportError };