-
Notifications
You must be signed in to change notification settings - Fork 13
/
esm-transformer.js
60 lines (51 loc) · 1.76 KB
/
esm-transformer.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
const crypto = require("crypto");
const fs = require("fs");
const babel = require("@babel/core");
const THIS_FILE = fs.readFileSync(__filename);
const importExportRegex = /\b(import|export)\b/;
module.exports = {
getCacheKey(fileData, filename, instance) {
return crypto
.createHash("md5")
.update(THIS_FILE)
.update("\0", "utf8")
.update(fileData)
.update("\0", "utf8")
.update(instance.configString)
.update("\0", "utf8")
.update(filename)
.digest("hex");
},
process(code, filename) {
if (babel.util && !babel.util.canCompile(filename)) {
return { code };
}
// Quick check with a regex,
// Allows to eliminate most cases right away without a more expensive parsing.
if (!importExportRegex.test(code)) {
return { code };
}
// We add Babel with a single transform
// to convert ES modules to commonjs
const options = {
babelrc: false,
compact: false,
plugins: [require.resolve("@babel/plugin-transform-modules-commonjs")]
};
const ast = babel.parseSync(code, options);
// Imports and exports have to be at the first level on a file
// This makes it easy for us to traverse the file, a simple filter does the trick
// If we had to find `import()` statements that would be more complicated, but as
// They would certainly have an import or export anyway, we're covered.
const hasImportOrExport = ast.program.body.filter(
item =>
item.type === "ImportDeclaration" ||
item.type === "ExportNamedDeclaration" ||
item.type === "ExportDefaultDeclaration"
);
if (hasImportOrExport.length === 0) {
return { code };
}
return { code: babel.transformFromAstSync(ast, code, options).code };
}
};