@nocobase/build 0.7.0-alpha.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +0 -0
  3. package/bin/nocobase-build.js +71 -0
  4. package/lib/babel.js +252 -0
  5. package/lib/build.js +351 -0
  6. package/lib/es5ImcompatibleVersions.js +51 -0
  7. package/lib/getBabelConfig.js +75 -0
  8. package/lib/getRollupConfig.js +320 -0
  9. package/lib/getUserConfig.js +99 -0
  10. package/lib/importLibToEs.js +38 -0
  11. package/lib/index.js +13 -0
  12. package/lib/normalizeBundleOpts.js +35 -0
  13. package/lib/randomColor.js +32 -0
  14. package/lib/registerBabel.js +38 -0
  15. package/lib/rollup.js +144 -0
  16. package/lib/schema.js +213 -0
  17. package/lib/types.d.js +1 -0
  18. package/lib/utils/getLernaPackages/index.js +63 -0
  19. package/lib/utils/index.js +48 -0
  20. package/package.json +78 -0
  21. package/src/babel.ts +257 -0
  22. package/src/build.ts +260 -0
  23. package/src/es5ImcompatibleVersions.ts +33 -0
  24. package/src/getBabelConfig.ts +95 -0
  25. package/src/getRollupConfig.ts +343 -0
  26. package/src/getUserConfig.ts +87 -0
  27. package/src/importLibToEs.js +26 -0
  28. package/src/index.ts +3 -0
  29. package/src/normalizeBundleOpts.ts +24 -0
  30. package/src/randomColor.ts +34 -0
  31. package/src/registerBabel.ts +23 -0
  32. package/src/rollup.ts +77 -0
  33. package/src/schema.ts +175 -0
  34. package/src/types.d.ts +118 -0
  35. package/src/utils/getLernaPackages/fixtures/customize/core/core1/package.json +7 -0
  36. package/src/utils/getLernaPackages/fixtures/customize/core/core1/src/index.js +2 -0
  37. package/src/utils/getLernaPackages/fixtures/customize/core/core2/package.json +5 -0
  38. package/src/utils/getLernaPackages/fixtures/customize/core/core2/src/index.js +2 -0
  39. package/src/utils/getLernaPackages/fixtures/customize/lerna.json +6 -0
  40. package/src/utils/getLernaPackages/fixtures/customize/package.json +4 -0
  41. package/src/utils/getLernaPackages/fixtures/customize/packages/bar/package.json +4 -0
  42. package/src/utils/getLernaPackages/fixtures/customize/packages/bar/src/index.js +2 -0
  43. package/src/utils/getLernaPackages/fixtures/customize/packages/foo/package.json +7 -0
  44. package/src/utils/getLernaPackages/fixtures/customize/packages/foo/src/index.js +2 -0
  45. package/src/utils/getLernaPackages/fixtures/default/lerna.json +1 -0
  46. package/src/utils/getLernaPackages/fixtures/default/package.json +4 -0
  47. package/src/utils/getLernaPackages/fixtures/default/packages/bar/package.json +4 -0
  48. package/src/utils/getLernaPackages/fixtures/default/packages/bar/src/index.js +2 -0
  49. package/src/utils/getLernaPackages/fixtures/default/packages/foo/package.json +7 -0
  50. package/src/utils/getLernaPackages/fixtures/default/packages/foo/src/index.js +2 -0
  51. package/src/utils/getLernaPackages/index.ts +57 -0
  52. package/src/utils/index.ts +13 -0
  53. package/template/tsconfig.json +23 -0
package/src/babel.ts ADDED
@@ -0,0 +1,257 @@
1
+ import { join, extname, relative } from "path";
2
+ import { existsSync, readFileSync, statSync } from "fs";
3
+ import vfs from "vinyl-fs";
4
+ import signale from "signale";
5
+ import lodash from "lodash";
6
+ import rimraf from "rimraf";
7
+ import through from "through2";
8
+ import slash from "slash2";
9
+ import * as chokidar from "chokidar";
10
+ import * as babel from "@babel/core";
11
+ import gulpTs from "gulp-typescript";
12
+ import gulpLess from "gulp-less";
13
+ import gulpPlumber from "gulp-plumber";
14
+ import gulpIf from "gulp-if";
15
+ import chalk from "chalk";
16
+ import getBabelConfig from "./getBabelConfig";
17
+ import { Dispose, IBundleOptions } from "./types";
18
+ import * as ts from "typescript";
19
+
20
+ interface IBabelOpts {
21
+ cwd: string;
22
+ rootPath?: string;
23
+ type: "esm" | "cjs";
24
+ target?: "browser" | "node";
25
+ log?: (string) => void;
26
+ watch?: boolean;
27
+ dispose?: Dispose[];
28
+ importLibToEs?: boolean;
29
+ bundleOpts: IBundleOptions;
30
+ }
31
+
32
+ interface ITransformOpts {
33
+ file: {
34
+ contents: string;
35
+ path: string;
36
+ };
37
+ type: "esm" | "cjs";
38
+ }
39
+
40
+ export default async function (opts: IBabelOpts) {
41
+ const {
42
+ cwd,
43
+ rootPath,
44
+ type,
45
+ watch,
46
+ dispose,
47
+ importLibToEs,
48
+ log,
49
+ bundleOpts: {
50
+ target = "browser",
51
+ runtimeHelpers,
52
+ extraBabelPresets = [],
53
+ extraBabelPlugins = [],
54
+ browserFiles = [],
55
+ nodeFiles = [],
56
+ nodeVersion,
57
+ disableTypeCheck,
58
+ cjs,
59
+ lessInBabelMode,
60
+ },
61
+ } = opts;
62
+ const srcPath = join(cwd, "src");
63
+ const targetDir = type === "esm" ? "es" : "lib";
64
+ const targetPath = join(cwd, targetDir);
65
+
66
+ log(chalk.gray(`Clean ${targetDir} directory`));
67
+ rimraf.sync(targetPath);
68
+
69
+ function transform(opts: ITransformOpts) {
70
+ const { file, type } = opts;
71
+ const { opts: babelOpts, isBrowser } = getBabelConfig({
72
+ target,
73
+ type,
74
+ typescript: true,
75
+ runtimeHelpers,
76
+ filePath: slash(relative(cwd, file.path)),
77
+ browserFiles,
78
+ nodeFiles,
79
+ nodeVersion,
80
+ lazy: cjs && cjs.lazy,
81
+ lessInBabelMode,
82
+ });
83
+ if (importLibToEs && type === "esm") {
84
+ babelOpts.plugins.push(require.resolve("../lib/importLibToEs"));
85
+ }
86
+ babelOpts.presets.push(...extraBabelPresets);
87
+ babelOpts.plugins.push(...extraBabelPlugins);
88
+
89
+ const relFile = slash(file.path).replace(`${cwd}/`, "");
90
+ log(
91
+ `Transform to ${type} for ${chalk[isBrowser ? "yellow" : "blue"](
92
+ relFile
93
+ )}`
94
+ );
95
+
96
+ return babel.transform(file.contents, {
97
+ ...babelOpts,
98
+ filename: file.path,
99
+ // 不读取外部的babel.config.js配置文件,全采用babelOpts中的babel配置来构建
100
+ configFile: false,
101
+ }).code;
102
+ }
103
+
104
+ /**
105
+ * tsconfig.json is not valid json file
106
+ * https://github.com/Microsoft/TypeScript/issues/20384
107
+ */
108
+ function parseTsconfig(path: string) {
109
+ const readFile = (path: string) => readFileSync(path, "utf-8");
110
+ const result = ts.readConfigFile(path, readFile);
111
+ if (result.error) {
112
+ return;
113
+ }
114
+ const pkgTsConfig = result.config;
115
+ if (pkgTsConfig.extends) {
116
+ const rootTsConfigPath = slash(relative(cwd, pkgTsConfig.extends));
117
+ const rootTsConfig = parseTsconfig(rootTsConfigPath);
118
+ if (rootTsConfig) {
119
+ const mergedConfig = {
120
+ ...rootTsConfig,
121
+ ...pkgTsConfig,
122
+ compilerOptions: {
123
+ ...rootTsConfig.compilerOptions,
124
+ ...pkgTsConfig.compilerOptions,
125
+ },
126
+ };
127
+ return mergedConfig;
128
+ }
129
+ }
130
+ return pkgTsConfig;
131
+ }
132
+
133
+ function getTsconfigCompilerOptions(path: string) {
134
+ const config = parseTsconfig(path);
135
+ return config ? config.compilerOptions : undefined;
136
+ }
137
+
138
+ function getTSConfig() {
139
+ const tsconfigPath = join(cwd, "tsconfig.json");
140
+ const templateTsconfigPath = join(__dirname, "../template/tsconfig.json");
141
+
142
+ if (existsSync(tsconfigPath)) {
143
+ return getTsconfigCompilerOptions(tsconfigPath) || {};
144
+ }
145
+ if (rootPath && existsSync(join(rootPath, "tsconfig.json"))) {
146
+ return getTsconfigCompilerOptions(join(rootPath, "tsconfig.json")) || {};
147
+ }
148
+ return getTsconfigCompilerOptions(templateTsconfigPath) || {};
149
+ }
150
+
151
+ function createStream(src) {
152
+ const tsConfig = getTSConfig();
153
+ const babelTransformRegexp = disableTypeCheck ? /\.(t|j)sx?$/ : /\.jsx?$/;
154
+
155
+ function isTsFile(path) {
156
+ return /\.tsx?$/.test(path) && !path.endsWith(".d.ts");
157
+ }
158
+
159
+ function isTransform(path) {
160
+ return babelTransformRegexp.test(path) && !path.endsWith(".d.ts");
161
+ }
162
+
163
+ return vfs
164
+ .src(src, {
165
+ allowEmpty: true,
166
+ base: srcPath,
167
+ })
168
+ .pipe(watch ? gulpPlumber() : through.obj())
169
+ .pipe(
170
+ gulpIf((f) => !disableTypeCheck && isTsFile(f.path), gulpTs(tsConfig))
171
+ )
172
+ .pipe(
173
+ gulpIf(
174
+ (f) => lessInBabelMode && /\.less$/.test(f.path),
175
+ gulpLess(lessInBabelMode || {})
176
+ )
177
+ )
178
+ .pipe(
179
+ gulpIf(
180
+ (f) => isTransform(f.path),
181
+ through.obj((file, env, cb) => {
182
+ try {
183
+ file.contents = Buffer.from(
184
+ transform({
185
+ file,
186
+ type,
187
+ })
188
+ );
189
+ // .jsx -> .js
190
+ file.path = file.path.replace(extname(file.path), ".js");
191
+ cb(null, file);
192
+ } catch (e) {
193
+ signale.error(`Compiled faild: ${file.path}`);
194
+ console.log(e);
195
+ cb(null);
196
+ }
197
+ })
198
+ )
199
+ )
200
+ .pipe(vfs.dest(targetPath));
201
+ }
202
+
203
+ return new Promise((resolve) => {
204
+ const patterns = [
205
+ join(srcPath, "**/*"),
206
+ `!${join(srcPath, "**/fixtures{,/**}")}`,
207
+ `!${join(srcPath, "**/demos{,/**}")}`,
208
+ `!${join(srcPath, "**/__test__{,/**}")}`,
209
+ `!${join(srcPath, "**/__tests__{,/**}")}`,
210
+ `!${join(srcPath, "**/*.mdx")}`,
211
+ `!${join(srcPath, "**/*.md")}`,
212
+ `!${join(srcPath, "**/*.+(test|e2e|spec).+(js|jsx|ts|tsx)")}`,
213
+ `!${join(srcPath, "**/tsconfig{,.*}.json")}`,
214
+ `!${join(srcPath, ".umi{,-production,-test}{,/**}")}`,
215
+ ];
216
+ createStream(patterns).on("end", () => {
217
+ if (watch) {
218
+ log(
219
+ chalk.magenta(
220
+ `Start watching ${slash(srcPath).replace(
221
+ `${cwd}/`,
222
+ ""
223
+ )} directory...`
224
+ )
225
+ );
226
+ const watcher = chokidar.watch(patterns, {
227
+ ignoreInitial: true,
228
+ });
229
+
230
+ const files = [];
231
+ function compileFiles() {
232
+ while (files.length) {
233
+ createStream(files.pop());
234
+ }
235
+ }
236
+
237
+ const debouncedCompileFiles = lodash.debounce(compileFiles, 1000);
238
+ watcher.on("all", (event, fullPath) => {
239
+ const relPath = fullPath.replace(srcPath, "");
240
+ log(
241
+ `[${event}] ${slash(join(srcPath, relPath)).replace(`${cwd}/`, "")}`
242
+ );
243
+ if (!existsSync(fullPath)) return;
244
+ if (statSync(fullPath).isFile()) {
245
+ if (!files.includes(fullPath)) files.push(fullPath);
246
+ debouncedCompileFiles();
247
+ }
248
+ });
249
+ process.once("SIGINT", () => {
250
+ watcher.close();
251
+ });
252
+ dispose?.push(() => watcher.close());
253
+ }
254
+ resolve();
255
+ });
256
+ });
257
+ }
package/src/build.ts ADDED
@@ -0,0 +1,260 @@
1
+ import * as assert from 'assert';
2
+ import chalk from 'chalk';
3
+ import { existsSync, readFileSync } from 'fs';
4
+ import { merge } from 'lodash';
5
+ import { isAbsolute, join, sep } from 'path';
6
+ import rimraf from 'rimraf';
7
+ import signale from 'signale';
8
+ import babel from './babel';
9
+ import getUserConfig, { CONFIG_FILES } from './getUserConfig';
10
+ import randomColor from './randomColor';
11
+ import registerBabel from './registerBabel';
12
+ import rollup from './rollup';
13
+ import { Dispose, IBundleOptions, IBundleTypeOutput, ICjs, IEsm, IOpts } from './types';
14
+ import { getExistFile, getLernaPackages } from './utils';
15
+
16
+ export function getBundleOpts(opts: IOpts): IBundleOptions[] {
17
+ const { cwd, buildArgs = {}, rootConfig = {} } = opts;
18
+ const entry = getExistFile({
19
+ cwd,
20
+ files: ['src/index.tsx', 'src/index.ts', 'src/index.jsx', 'src/index.js'],
21
+ returnRelative: true,
22
+ });
23
+ const userConfig = getUserConfig({ cwd, customPath: buildArgs.config });
24
+ const userConfigs = Array.isArray(userConfig) ? userConfig : [userConfig];
25
+ return (userConfigs as any).map((userConfig) => {
26
+ const bundleOpts = merge(
27
+ {
28
+ entry,
29
+ },
30
+ rootConfig,
31
+ userConfig,
32
+ buildArgs
33
+ );
34
+
35
+ // Support config esm: 'rollup' and cjs: 'rollup'
36
+ if (typeof bundleOpts.esm === 'string') {
37
+ bundleOpts.esm = { type: bundleOpts.esm };
38
+ }
39
+ if (typeof bundleOpts.cjs === 'string') {
40
+ bundleOpts.cjs = { type: bundleOpts.cjs };
41
+ }
42
+
43
+ return bundleOpts;
44
+ });
45
+ }
46
+
47
+ function validateBundleOpts(bundleOpts: IBundleOptions, { cwd, rootPath }) {
48
+ if (bundleOpts.runtimeHelpers) {
49
+ const pkgPath = join(cwd, 'package.json');
50
+ assert.ok(existsSync(pkgPath), `@babel/runtime dependency is required to use runtimeHelpers`);
51
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
52
+ assert.ok(
53
+ (pkg.dependencies || {})['@babel/runtime'],
54
+ `@babel/runtime dependency is required to use runtimeHelpers`
55
+ );
56
+ }
57
+ if (
58
+ bundleOpts.cjs &&
59
+ (bundleOpts.cjs as ICjs).lazy &&
60
+ (bundleOpts.cjs as ICjs).type === 'rollup'
61
+ ) {
62
+ throw new Error(
63
+ `
64
+ cjs.lazy don't support rollup.
65
+ `.trim()
66
+ );
67
+ }
68
+ if (!bundleOpts.esm && !bundleOpts.cjs && !bundleOpts.umd) {
69
+ throw new Error(
70
+ `
71
+ None format of ${chalk.cyan(
72
+ 'cjs | esm | umd'
73
+ )} is configured, checkout https://github.com/umijs/father for usage details.
74
+ `.trim()
75
+ );
76
+ }
77
+ if (bundleOpts.entry) {
78
+ const tsConfigPath = join(cwd, 'tsconfig.json');
79
+ const tsConfig =
80
+ existsSync(tsConfigPath) || (rootPath && existsSync(join(rootPath, 'tsconfig.json')));
81
+ if (
82
+ !tsConfig &&
83
+ ((Array.isArray(bundleOpts.entry) && bundleOpts.entry.some(isTypescriptFile)) ||
84
+ (!Array.isArray(bundleOpts.entry) && isTypescriptFile(bundleOpts.entry)))
85
+ ) {
86
+ signale.info(
87
+ `Project using ${chalk.cyan(
88
+ 'typescript'
89
+ )} but tsconfig.json not exists. Use default config.`
90
+ );
91
+ }
92
+ }
93
+ }
94
+
95
+ function isTypescriptFile(filePath) {
96
+ return filePath.endsWith('.ts') || filePath.endsWith('.tsx');
97
+ }
98
+
99
+ interface IExtraBuildOpts {
100
+ pkg?: string | { name?: string };
101
+ }
102
+
103
+ export async function build(opts: IOpts, extraOpts: IExtraBuildOpts = {}) {
104
+ const { cwd, rootPath, watch, buildArgs = {}, clean = true } = opts;
105
+ const { pkg } = extraOpts;
106
+
107
+ const dispose: Dispose[] = [];
108
+
109
+ const customConfigPath =
110
+ buildArgs.config &&
111
+ (isAbsolute(buildArgs.config) ? buildArgs.config : join(process.cwd(), buildArgs.config));
112
+
113
+ // register babel for config files
114
+ registerBabel({
115
+ cwd,
116
+ only: customConfigPath ? CONFIG_FILES.concat(customConfigPath) : CONFIG_FILES,
117
+ });
118
+
119
+ const pkgName = (typeof pkg === 'string' ? pkg : pkg?.name) || 'unknown';
120
+
121
+ function log(msg) {
122
+ console.log(`${pkg ? `${randomColor(`${pkgName}`)}: ` : ''}${msg}`);
123
+ }
124
+
125
+ // Get user config
126
+ const bundleOptsArray = getBundleOpts(opts);
127
+
128
+ for (const bundleOpts of bundleOptsArray) {
129
+ validateBundleOpts(bundleOpts, { cwd, rootPath });
130
+
131
+ // Clean dist
132
+ if (clean) {
133
+ log(chalk.gray(`Clean dist directory`));
134
+ rimraf.sync(join(cwd, 'dist'));
135
+ }
136
+
137
+
138
+ // Build umd
139
+ if (bundleOpts.umd) {
140
+ log(`Build umd`);
141
+ await rollup({
142
+ cwd,
143
+ rootPath,
144
+ log,
145
+ type: 'umd',
146
+ entry: bundleOpts.entry,
147
+ watch,
148
+ dispose,
149
+ bundleOpts,
150
+ });
151
+ }
152
+
153
+ // Build cjs
154
+ if (bundleOpts.cjs) {
155
+ const cjs = bundleOpts.cjs as IBundleTypeOutput;
156
+ log(`Build cjs with ${cjs.type}`);
157
+ if (cjs.type === 'babel') {
158
+ await babel({ cwd, rootPath, watch, dispose, type: 'cjs', log, bundleOpts });
159
+ } else {
160
+ await rollup({
161
+ cwd,
162
+ rootPath,
163
+ log,
164
+ type: 'cjs',
165
+ entry: bundleOpts.entry,
166
+ watch,
167
+ dispose,
168
+ bundleOpts,
169
+ });
170
+ }
171
+ }
172
+
173
+ // Build esm
174
+ if (bundleOpts.esm) {
175
+ const esm = bundleOpts.esm as IEsm;
176
+ log(`Build esm with ${esm.type}`);
177
+ const importLibToEs = esm && esm.importLibToEs;
178
+ if (esm && esm.type === 'babel') {
179
+ await babel({ cwd, rootPath, watch, dispose, type: 'esm', importLibToEs, log, bundleOpts });
180
+ } else {
181
+ await rollup({
182
+ cwd,
183
+ rootPath,
184
+ log,
185
+ type: 'esm',
186
+ entry: bundleOpts.entry,
187
+ importLibToEs,
188
+ watch,
189
+ dispose,
190
+ bundleOpts,
191
+ });
192
+ }
193
+ }
194
+ }
195
+
196
+ return dispose;
197
+ }
198
+
199
+ function getPkgRelativePath(cwd, pkg) {
200
+ const basePath = cwd.split(sep).join('/') + '/packages/';
201
+ const dir = pkg.contents.split(sep).join('/');
202
+ return dir.substring(basePath.length);
203
+ }
204
+
205
+ export async function buildForLerna(opts: IOpts) {
206
+ const { cwd, rootConfig = {}, buildArgs = {}, packages = [] } = opts;
207
+
208
+ // register babel for config files
209
+ registerBabel({
210
+ cwd,
211
+ only: CONFIG_FILES,
212
+ });
213
+
214
+ const userConfig = merge(getUserConfig({ cwd }), rootConfig, buildArgs);
215
+
216
+ let pkgs = await getLernaPackages(cwd, userConfig.pkgFilter);
217
+ // support define pkgs in lerna
218
+ if (userConfig.pkgs) {
219
+ pkgs = pkgs.filter(pkg => userConfig.pkgs.includes(getPkgRelativePath(cwd, pkg)));
220
+ }
221
+ const dispose: Dispose[] = [];
222
+ for (const pkg of pkgs) {
223
+ const pkgName = getPkgRelativePath(cwd, pkg);
224
+ if (userConfig.excludePkgs && userConfig.excludePkgs.includes(pkgName)) {
225
+ continue;
226
+ }
227
+ if (packages.length && !packages.includes(pkgName)) continue;
228
+ // build error when .DS_Store includes in packages root
229
+ const pkgPath = pkg.contents;
230
+ assert.ok(
231
+ existsSync(join(pkgPath, 'package.json')),
232
+ `package.json not found in packages/${pkg}`
233
+ );
234
+ process.chdir(pkgPath);
235
+ dispose.push(
236
+ ...(await build(
237
+ {
238
+ // eslint-disable-line
239
+ ...opts,
240
+ buildArgs: opts.buildArgs,
241
+ rootConfig: userConfig,
242
+ cwd: pkgPath,
243
+ rootPath: cwd,
244
+ },
245
+ {
246
+ pkg,
247
+ }
248
+ ))
249
+ );
250
+ }
251
+ return dispose;
252
+ }
253
+
254
+ export default async function (opts: IOpts) {
255
+ const useLerna = existsSync(join(opts.cwd, 'lerna.json'));
256
+ const isLerna = useLerna && process.env.LERNA !== 'none';
257
+
258
+ const dispose = isLerna ? await buildForLerna(opts) : await build(opts);
259
+ return () => dispose.forEach((e) => e());
260
+ }
@@ -0,0 +1,33 @@
1
+ // 参考:
2
+ // https://github.com/umijs/umi/blob/2.x/packages/af-webpack/src/getWebpackConfig/es5ImcompatibleVersions.js
3
+ import { dirname } from 'path';
4
+ import pkgUp from 'pkg-up';
5
+ import { satisfies } from 'semver';
6
+
7
+ const pkgPathCache = {};
8
+ const pkgCache = {};
9
+ const {
10
+ config: { 'es5-imcompatible-versions': config },
11
+ } = require('es5-imcompatible-versions/package.json');
12
+
13
+ export function getPkgPath(filePath: string) {
14
+ const dir = dirname(filePath);
15
+ if (dir in pkgPathCache) return pkgPathCache[dir];
16
+ pkgPathCache[dir] = pkgUp.sync({ cwd: filePath });
17
+ return pkgPathCache[dir];
18
+ }
19
+
20
+ export function shouldTransform(pkgPath: string) {
21
+ if (pkgPath in pkgCache) return pkgCache[pkgPath];
22
+ const { name, version } = require(pkgPath);
23
+ pkgCache[pkgPath] = isMatch(name, version);
24
+ return pkgCache[pkgPath];
25
+ }
26
+
27
+ function isMatch(name, version) {
28
+ if (config[name]) {
29
+ return Object.keys(config[name]).some((sv) => satisfies(version, sv));
30
+ } else {
31
+ return false;
32
+ }
33
+ }
@@ -0,0 +1,95 @@
1
+ import { extname } from 'path';
2
+ import { ModuleFormat } from 'rollup';
3
+
4
+ interface IGetBabelConfigOpts {
5
+ target: 'browser' | 'node';
6
+ type?: ModuleFormat;
7
+ typescript?: boolean;
8
+ runtimeHelpers?: boolean;
9
+ filePath?: string;
10
+ browserFiles?: {
11
+ [value: string]: any;
12
+ };
13
+ nodeVersion?: number;
14
+ nodeFiles?: {
15
+ [value: string]: any;
16
+ };
17
+ lazy?: boolean;
18
+ lessInBabelMode?: boolean|{
19
+ paths?: any[];
20
+ plugins?: any[];
21
+ };
22
+ }
23
+
24
+ function transformImportLess2Css() {
25
+ return {
26
+ name: 'transform-import-less-to-css',
27
+ visitor: {
28
+ ImportDeclaration(path, source) {
29
+ const re = /\.less$/;
30
+ if(re.test(path.node.source.value)){
31
+ path.node.source.value = path.node.source.value.replace(re, '.css');
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ export default function(opts: IGetBabelConfigOpts) {
39
+ const { target, typescript, type, runtimeHelpers, filePath, browserFiles, nodeFiles, nodeVersion, lazy, lessInBabelMode } = opts;
40
+ let isBrowser = target === 'browser';
41
+ // rollup 场景下不会传入 filePath
42
+ if (filePath) {
43
+ if (extname(filePath) === '.tsx' || extname(filePath) === '.jsx') {
44
+ isBrowser = true;
45
+ } else {
46
+ if (isBrowser) {
47
+ if (nodeFiles.includes(filePath)) isBrowser = false;
48
+ } else {
49
+ if (browserFiles.includes(filePath)) isBrowser = true;
50
+ }
51
+ }
52
+ }
53
+ const targets = isBrowser ? { browsers: ['last 2 versions', 'IE 10'] } : { node: nodeVersion || 6 };
54
+
55
+ return {
56
+ opts: {
57
+ presets: [
58
+ ...(typescript ? [require.resolve('@babel/preset-typescript')] : []),
59
+ [require.resolve('@babel/preset-env'), {
60
+ targets,
61
+ modules: type === 'esm' ? false : 'auto'
62
+ }],
63
+ ...(isBrowser ? [require.resolve('@babel/preset-react')] : []),
64
+ ],
65
+ plugins: [
66
+ ...((type === 'cjs' && lazy && !isBrowser)
67
+ ? [[require.resolve('@babel/plugin-transform-modules-commonjs'), {
68
+ lazy: true,
69
+ }]]
70
+ : []),
71
+ ...(lessInBabelMode ? [transformImportLess2Css] : []),
72
+ ...(isBrowser ? [require.resolve('babel-plugin-react-require')] : []),
73
+ require.resolve('@babel/plugin-syntax-dynamic-import'),
74
+ require.resolve('@babel/plugin-proposal-export-default-from'),
75
+ require.resolve('@babel/plugin-proposal-export-namespace-from'),
76
+ require.resolve('@babel/plugin-proposal-do-expressions'),
77
+ require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
78
+ require.resolve('@babel/plugin-proposal-optional-chaining'),
79
+ [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
80
+ [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }],
81
+ ...(runtimeHelpers
82
+ ? [[require.resolve('@babel/plugin-transform-runtime'), {
83
+ useESModules: isBrowser && (type === 'esm'),
84
+ version: require('@babel/runtime/package.json').version,
85
+ }]]
86
+ : []),
87
+ ...(process.env.COVERAGE
88
+ ? [require.resolve('babel-plugin-istanbul')]
89
+ : []
90
+ )
91
+ ],
92
+ },
93
+ isBrowser,
94
+ };
95
+ }