Skip to content

Commit 45ab62f

Browse files
authored
feat: plugin antd (umijs#155)
* feat: plugin antd * fix: addExtraBabelPlugins babel-plugin-import error * feat: add config * chore: remove runtime * feat: dayjs
1 parent 559f459 commit 45ab62f

File tree

5 files changed

+268
-63
lines changed

5 files changed

+268
-63
lines changed

packages/plugins/package.json

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
"publishConfig": {
2626
"access": "public"
2727
},
28+
"dependencies": {
29+
"antd": "^4.16.13",
30+
"antd-dayjs-webpack-plugin": "^1.0.6",
31+
"babel-plugin-import": "^1.13.3",
32+
"dayjs": "^1.10.7"
33+
},
2834
"devDependencies": {
2935
"umi": "4.0.0-beta.5"
3036
}

packages/plugins/src/antd.ts

+205-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,213 @@
1+
import { Mustache, resolve, winPath } from '@umijs/utils';
2+
import { ConfigProviderProps } from 'antd/es/config-provider';
3+
import { readFileSync } from 'fs';
4+
import { dirname, join } from 'path';
15
import { IApi } from 'umi';
26

3-
export default (api: IApi) => {
4-
api;
7+
interface IDayJsOpts {
8+
preset?: string; // 'antd' | 'antdv3'
9+
plugins?: string[];
10+
replaceMoment?: boolean;
11+
}
12+
13+
interface IAntdOpts {
14+
dark?: boolean;
15+
compact?: boolean;
16+
dayjs?: boolean | IDayJsOpts;
17+
config?: ConfigProviderProps;
18+
}
19+
20+
const presets = {
21+
antd: {
22+
plugins: [
23+
'isSameOrBefore',
24+
'isSameOrAfter',
25+
'advancedFormat',
26+
'customParseFormat',
27+
'weekday',
28+
'weekYear',
29+
'weekOfYear',
30+
'isMoment',
31+
'localeData',
32+
'localizedFormat',
33+
],
34+
replaceMoment: true,
35+
},
36+
antdv3: {
37+
plugins: [
38+
'isSameOrBefore',
39+
'isSameOrAfter',
40+
'advancedFormat',
41+
'customParseFormat',
42+
'weekday',
43+
'weekYear',
44+
'weekOfYear',
45+
'isMoment',
46+
'localeData',
47+
'localizedFormat',
48+
'badMutable',
49+
],
50+
replaceMoment: true,
51+
},
52+
} as any;
553

54+
const getConfig = (api: IApi) => {
55+
let {
56+
preset = 'antd',
57+
plugins,
58+
replaceMoment,
59+
} = api.userConfig.antdDayjs || {};
60+
61+
if (preset && presets[preset]) {
62+
plugins = presets[preset].plugins;
63+
replaceMoment = presets[preset].replaceMoment;
64+
}
65+
if (plugins) plugins = plugins;
66+
if (replaceMoment !== undefined) replaceMoment = replaceMoment;
67+
return {
68+
plugins,
69+
replaceMoment,
70+
};
71+
};
72+
73+
const DIR_NAME = 'plugin-antd';
74+
75+
export default (api: IApi) => {
76+
const opts: IAntdOpts = api.userConfig.antd;
77+
// dayjs (by default)
78+
const { dayjs = true } = opts;
79+
api.describe({
80+
config: {
81+
schema(Joi) {
82+
return Joi.object({
83+
dark: Joi.boolean(),
84+
compact: Joi.boolean(),
85+
config: Joi.object(),
86+
dayjs: Joi.alternatives(
87+
Joi.boolean(),
88+
Joi.object({
89+
preset: Joi.string(), // 'antd' | 'antdv3'
90+
plugins: Joi.array(),
91+
replaceMoment: Joi.boolean(),
92+
}),
93+
),
94+
});
95+
},
96+
},
97+
});
698
// antd import
99+
api.chainWebpack((memo) => {
100+
function getUserLibDir({ library }: { library: string }) {
101+
if (
102+
// @ts-ignore
103+
(api.pkg.dependencies && api.pkg.dependencies[library]) ||
104+
// @ts-ignore
105+
(api.pkg.devDependencies && api.pkg.devDependencies[library]) ||
106+
// egg project using `clientDependencies` in ali tnpm
107+
// @ts-ignore
108+
(api.pkg.clientDependencies && api.pkg.clientDependencies[library])
109+
) {
110+
return winPath(
111+
dirname(
112+
// 通过 resolve 往上找,可支持 lerna 仓库
113+
// lerna 仓库如果用 yarn workspace 的依赖不一定在 node_modules,可能被提到根目录,并且没有 link
114+
resolve.sync(`${library}/package.json`, {
115+
basedir: api.paths.cwd,
116+
}),
117+
),
118+
);
119+
}
120+
return null;
121+
}
122+
memo.resolve.alias.set(
123+
'antd',
124+
getUserLibDir({ library: 'antd' }) ||
125+
dirname(require.resolve('antd/package.json')),
126+
);
127+
if (dayjs !== false) {
128+
const { replaceMoment } = getConfig(api);
129+
if (replaceMoment) {
130+
memo.resolve.alias.set(
131+
'moment',
132+
getUserLibDir({ library: 'dayjs' }) ||
133+
dirname(require.resolve('dayjs/package.json')),
134+
);
135+
}
136+
}
137+
return memo;
138+
});
7139
// dark mode
8140
// compat mode
9-
// dayjs (by default?)
141+
if (opts?.dark || opts?.compact) {
142+
// support dark mode, user use antd 4 by default
143+
const { getThemeVariables } = require('antd/dist/theme');
144+
api.modifyDefaultConfig((config) => {
145+
config.theme = {
146+
...getThemeVariables(opts),
147+
...config.theme,
148+
};
149+
return config;
150+
});
151+
}
152+
if (dayjs !== false) {
153+
api.onGenerateFiles({
154+
fn: () => {
155+
const { plugins } = getConfig(api);
156+
157+
const runtimeTpl = readFileSync(
158+
join(__dirname, '../templates/antd/dayjs.tpl'),
159+
'utf-8',
160+
);
161+
api.writeTmpFile({
162+
path: 'plugin-antd/dayjs.tsx',
163+
content: Mustache.render(runtimeTpl, {
164+
plugins,
165+
dayjsPath: dirname(require.resolve('dayjs/package.json')),
166+
dayjsPluginPath: dirname(
167+
require.resolve('antd-dayjs-webpack-plugin/package.json'),
168+
),
169+
}),
170+
});
171+
},
172+
});
173+
api.addEntryCodeAhead(() => {
174+
return [`import './${DIR_NAME}/dayjs.tsx'`];
175+
});
176+
}
10177
// babel-plugin-import
11-
// antd config provider (HOLD, depends on umi)
178+
api.addExtraBabelPlugins(() => {
179+
return [
180+
[
181+
require.resolve('babel-plugin-import'),
182+
{
183+
libraryName: 'antd',
184+
libraryDirectory: 'es',
185+
style: true,
186+
},
187+
],
188+
];
189+
});
190+
// antd config provider
191+
// TODO: use umi provider
192+
if (opts?.config) {
193+
api.onGenerateFiles({
194+
fn() {
195+
// runtime.tsx
196+
const runtimeTpl = readFileSync(
197+
join(__dirname, '../templates/antd/runtime.tpl'),
198+
'utf-8',
199+
);
200+
api.writeTmpFile({
201+
path: `${DIR_NAME}/runtime.tsx`,
202+
content: Mustache.render(runtimeTpl, {
203+
config: JSON.stringify(opts?.config),
204+
}),
205+
});
206+
},
207+
});
208+
//TODO:Runtime Plugin
209+
api.addRuntimePlugin(() => [
210+
join(api.paths.absTmpPath!, DIR_NAME, 'runtime.tsx'),
211+
]);
212+
}
12213
};
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import dayjs from '{{{dayjsPath}}}';
2+
import antdPlugin from '{{{dayjsPluginPath}}}/src/antd-plugin';
3+
4+
{{#plugins}}
5+
import {{.}} from '{{{dayjsPath}}}/plugin/{{.}}';
6+
{{/plugins}}
7+
8+
{{#plugins}}
9+
dayjs.extend({{.}});
10+
{{/plugins}}
11+
12+
dayjs.extend(antdPlugin);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react';
2+
import { ConfigProvider, Modal, message, notification } from 'antd';
3+
import { ApplyPluginsType } from 'umi';
4+
5+
export function rootContainer(container) {
6+
const finalConfig = {...{{{ config }}}}
7+
8+
if (finalConfig.prefixCls) {
9+
Modal.config({
10+
rootPrefixCls: finalConfig.prefixCls,
11+
});
12+
message.config({
13+
prefixCls: `${finalConfig.prefixCls}-message`,
14+
});
15+
notification.config({
16+
prefixCls: `${finalConfig.prefixCls}-notification`,
17+
});
18+
}
19+
return React.createElement(ConfigProvider, finalConfig, container);
20+
}

0 commit comments

Comments
 (0)