-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathbabel.js
96 lines (85 loc) · 2.79 KB
/
babel.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
const path = require('path');
const crypto = require('crypto');
const { outputFile } = require('fs-extra');
const fs = require('fs');
const babel = require('@babel/core');
const { getDefaultCacheDir } = require('../cache');
const md5 = (string) => crypto.createHash('md5').update(string).digest('hex');
const babelPlugin = (options = {}) => ({
name: 'babel',
setup(build, { transform } = {}) {
const {
filter = /.*/,
namespace = '',
cache = true,
loader = 'js',
config = {},
} = options;
const transformCache = new Map();
const transformContents = async ({ args, contents }) => {
const babelOptions = babel.loadOptions({
minified: false,
compact: false,
...config,
sourceMaps: 'inline',
filename: args.path,
caller: {
name: 'esbuild-plugin-babel',
supportsStaticESM: true,
},
});
if (!babelOptions) {
return { contents };
}
if (babelOptions.sourceMaps) {
const filename = path.relative(process.cwd(), args.path);
babelOptions.sourceFileName = filename;
}
const transformWithBabel = () =>
new Promise((resolve, reject) => {
babel.transform(contents, babelOptions, (error, result) => {
error ? reject(error) : resolve(result.code);
});
});
if (cache) {
const cachePath = path.join(
typeof cache === 'string' ? cache : getDefaultCacheDir(),
md5(JSON.stringify(babelOptions) + contents)
);
try {
return await fs.promises.readFile(cachePath, { encoding: 'utf8' });
} catch (err) {
const transformed = await transformWithBabel();
await outputFile(cachePath, transformed);
return transformed;
}
}
return transformWithBabel();
};
build.onLoad({ filter, namespace }, async (args) => {
let handle;
try {
handle = await fs.promises.open(args.path, 'r');
let entry = transformCache.get(args.path);
const stats = await handle.stat();
// Use in-memory cache unless file was modified.
// Ideally we'd compare file contents, but it would be
// slower and is already done by the file system cache
if (!entry || entry.mtimeMs !== stats.mtimeMs) {
const contents = await handle.readFile('utf8');
const transformed = await transformContents({ args, contents });
entry = { transformed, mtimeMs: stats.mtimeMs };
if (cache) {
transformCache.set(args.path, entry);
}
}
return { contents: entry.transformed, loader };
} finally {
if (handle) {
handle.close();
}
}
});
},
});
module.exports = { babelPlugin };