@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.
- package/LICENSE +201 -0
- package/README.md +0 -0
- package/bin/nocobase-build.js +71 -0
- package/lib/babel.js +252 -0
- package/lib/build.js +351 -0
- package/lib/es5ImcompatibleVersions.js +51 -0
- package/lib/getBabelConfig.js +75 -0
- package/lib/getRollupConfig.js +320 -0
- package/lib/getUserConfig.js +99 -0
- package/lib/importLibToEs.js +38 -0
- package/lib/index.js +13 -0
- package/lib/normalizeBundleOpts.js +35 -0
- package/lib/randomColor.js +32 -0
- package/lib/registerBabel.js +38 -0
- package/lib/rollup.js +144 -0
- package/lib/schema.js +213 -0
- package/lib/types.d.js +1 -0
- package/lib/utils/getLernaPackages/index.js +63 -0
- package/lib/utils/index.js +48 -0
- package/package.json +78 -0
- package/src/babel.ts +257 -0
- package/src/build.ts +260 -0
- package/src/es5ImcompatibleVersions.ts +33 -0
- package/src/getBabelConfig.ts +95 -0
- package/src/getRollupConfig.ts +343 -0
- package/src/getUserConfig.ts +87 -0
- package/src/importLibToEs.js +26 -0
- package/src/index.ts +3 -0
- package/src/normalizeBundleOpts.ts +24 -0
- package/src/randomColor.ts +34 -0
- package/src/registerBabel.ts +23 -0
- package/src/rollup.ts +77 -0
- package/src/schema.ts +175 -0
- package/src/types.d.ts +118 -0
- package/src/utils/getLernaPackages/fixtures/customize/core/core1/package.json +7 -0
- package/src/utils/getLernaPackages/fixtures/customize/core/core1/src/index.js +2 -0
- package/src/utils/getLernaPackages/fixtures/customize/core/core2/package.json +5 -0
- package/src/utils/getLernaPackages/fixtures/customize/core/core2/src/index.js +2 -0
- package/src/utils/getLernaPackages/fixtures/customize/lerna.json +6 -0
- package/src/utils/getLernaPackages/fixtures/customize/package.json +4 -0
- package/src/utils/getLernaPackages/fixtures/customize/packages/bar/package.json +4 -0
- package/src/utils/getLernaPackages/fixtures/customize/packages/bar/src/index.js +2 -0
- package/src/utils/getLernaPackages/fixtures/customize/packages/foo/package.json +7 -0
- package/src/utils/getLernaPackages/fixtures/customize/packages/foo/src/index.js +2 -0
- package/src/utils/getLernaPackages/fixtures/default/lerna.json +1 -0
- package/src/utils/getLernaPackages/fixtures/default/package.json +4 -0
- package/src/utils/getLernaPackages/fixtures/default/packages/bar/package.json +4 -0
- package/src/utils/getLernaPackages/fixtures/default/packages/bar/src/index.js +2 -0
- package/src/utils/getLernaPackages/fixtures/default/packages/foo/package.json +7 -0
- package/src/utils/getLernaPackages/fixtures/default/packages/foo/src/index.js +2 -0
- package/src/utils/getLernaPackages/index.ts +57 -0
- package/src/utils/index.ts +13 -0
- 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
|
+
}
|