forked from mui/mui-x
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.mjs
132 lines (119 loc) · 4.01 KB
/
build.mjs
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
// TODO: Use the core file (need to change the way the babel config is loaded to load the X one instead of the core one)
import childProcess from 'child_process';
import glob from 'fast-glob';
import path from 'path';
import { promisify } from 'util';
import yargs from 'yargs';
import { getWorkspaceRoot } from './utils.mjs';
const exec = promisify(childProcess.exec);
const validBundles = [
// legacy build using ES6 modules
'legacy',
// modern build with a rolling target using ES6 modules
'modern',
// build for node using commonJS modules
'node',
// build with a hardcoded target using ES6 modules
'stable',
];
async function run(argv) {
const { bundle, largeFiles, outDir: relativeOutDir, verbose, ignore: providedIgnore } = argv;
if (validBundles.indexOf(bundle) === -1) {
throw new TypeError(
`Unrecognized bundle '${bundle}'. Did you mean one of "${validBundles.join('", "')}"?`,
);
}
const env = {
NODE_ENV: 'production',
BABEL_ENV: bundle,
MUI_BUILD_VERBOSE: verbose,
};
const babelConfigPath = path.resolve(getWorkspaceRoot(), 'babel.config.js');
const srcDir = path.resolve('./src');
const extensions = ['.js', '.ts', '.tsx'];
const ignore = [
'**/*.test.js',
'**/*.test.ts',
'**/*.test.tsx',
'**/*.spec.js',
'**/*.spec.ts',
'**/*.spec.tsx',
'**/*.d.ts',
...(providedIgnore || []),
];
const topLevelNonIndexFiles = glob
.sync(`*{${extensions.join(',')}}`, { cwd: srcDir, ignore })
.filter((file) => {
return path.basename(file, path.extname(file)) !== 'index';
});
const topLevelPathImportsCanBePackages = topLevelNonIndexFiles.length === 0;
const outDir = path.resolve(
relativeOutDir,
// We generally support top level path imports e.g.
// 1. `import ArrowDownIcon from '@mui/icons-material/ArrowDown'`.
// 2. `import Typography from '@mui/material/Typography'`.
// The first case resolves to a file while the second case resolves to a package first i.e. a package.json
// This means that only in the second case the bundler can decide whether it uses ES modules or CommonJS modules.
// Different extensions are not viable yet since they require additional bundler config for users and additional transpilation steps in our repo.
// Switch to `exports` field in v6.
{
node: topLevelPathImportsCanBePackages ? './node' : './',
modern: './modern',
stable: topLevelPathImportsCanBePackages ? './' : './esm',
legacy: './legacy',
}[bundle],
);
const babelArgs = [
'--config-file',
babelConfigPath,
'--extensions',
`"${extensions.join(',')}"`,
srcDir,
'--out-dir',
outDir,
'--ignore',
// Need to put these patterns in quotes otherwise they might be evaluated by the used terminal.
`"${ignore.join('","')}"`,
];
if (largeFiles) {
babelArgs.push('--compact false');
}
const command = ['yarn babel', ...babelArgs].join(' ');
if (verbose) {
// eslint-disable-next-line no-console
console.log(`running '${command}' with ${JSON.stringify(env)}`);
}
const { stderr, stdout } = await exec(command, { env: { ...process.env, ...env } });
if (stderr) {
throw new Error(`'${command}' failed with \n${stderr}`);
}
if (verbose) {
// eslint-disable-next-line no-console
console.log(stdout);
}
}
yargs(process.argv.slice(2))
.command({
command: '$0 <bundle>',
description: 'build package',
builder: (command) => {
return command
.positional('bundle', {
description: `Valid bundles: "${validBundles.join('" | "')}"`,
type: 'string',
})
.option('largeFiles', {
type: 'boolean',
default: false,
describe: 'Set to `true` if you know you are transpiling large files.',
})
.option('out-dir', { default: './build', type: 'string' })
.option('verbose', { type: 'boolean' })
.option('ignore', { type: 'string', array: true });
},
handler: run,
})
.help()
.strict(true)
.version(false)
.parse();