mirror of
https://gitee.com/WeBank/fes.js.git
synced 2024-11-30 10:48:12 +08:00
refactor: 优化乾坤插件,增加构建配置提示
This commit is contained in:
commit
abffcdb9a1
@ -3,18 +3,13 @@ import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import SFCConfigBlockPlugin from './SFCConfigBlockPlugin';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
export default (api) => {
|
||||
const {
|
||||
env,
|
||||
paths,
|
||||
utils: { chalk },
|
||||
} = api;
|
||||
|
||||
const unwatchs = [];
|
||||
let port;
|
||||
let hostname;
|
||||
let server;
|
||||
|
||||
function destroy() {
|
||||
@ -63,30 +58,6 @@ export default (api) => {
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'getPort',
|
||||
fn() {
|
||||
assert(env === 'development', 'api.getPort() is only valid in development.');
|
||||
return port;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'getHostname',
|
||||
fn() {
|
||||
assert(env === 'development', 'api.getHostname() is only valid in development.');
|
||||
return hostname;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'getServer',
|
||||
fn() {
|
||||
assert(env === 'development', 'api.getServer() is only valid in development.');
|
||||
return server;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'restartServer',
|
||||
fn() {
|
||||
|
@ -3,11 +3,8 @@
|
||||
* https://github.com/umijs/umi/blob/master/packages/preset-built-in/src/plugins/commands/dev/dev.ts
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
export default (api) => {
|
||||
const {
|
||||
env,
|
||||
paths,
|
||||
utils: { chalk, portfinder, generateFiles },
|
||||
} = api;
|
||||
@ -165,30 +162,6 @@ export default (api) => {
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'getPort',
|
||||
fn() {
|
||||
assert(env === 'development', 'api.getPort() is only valid in development.');
|
||||
return port;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'getHostname',
|
||||
fn() {
|
||||
assert(env === 'development', 'api.getHostname() is only valid in development.');
|
||||
return hostname;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'getServer',
|
||||
fn() {
|
||||
assert(env === 'development', 'api.getServer() is only valid in development.');
|
||||
return server;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerMethod({
|
||||
name: 'restartServer',
|
||||
fn() {
|
||||
|
@ -9,18 +9,12 @@ import { AsyncSeriesWaterfallHook } from 'tapable';
|
||||
import { existsSync } from 'fs';
|
||||
import { lodash, chalk } from '@fesjs/utils';
|
||||
import { Command, Option } from 'commander';
|
||||
import { resolvePresets, pathToObj, resolvePlugins } from './utils/pluginUtils';
|
||||
import { resolvePresets, filterBuilder, pathToObj, resolvePlugins } from './utils/pluginUtils';
|
||||
import loadDotEnv from './utils/loadDotEnv';
|
||||
import isPromise from './utils/isPromise';
|
||||
import BabelRegister from './babelRegister';
|
||||
import PluginAPI from './pluginAPI';
|
||||
import {
|
||||
ApplyPluginsType,
|
||||
ConfigChangeType,
|
||||
EnableBy,
|
||||
PluginType,
|
||||
ServiceStage
|
||||
} from './enums';
|
||||
import { ApplyPluginsType, ConfigChangeType, EnableBy, PluginType, ServiceStage } from './enums';
|
||||
import Config from '../config';
|
||||
import { getUserConfigWithKey } from '../config/utils/configUtils';
|
||||
import getPaths from './getPaths';
|
||||
@ -95,6 +89,11 @@ export default class Service extends EventEmitter {
|
||||
this.env = opts.env || process.env.NODE_ENV;
|
||||
this.fesPkg = opts.fesPkg || {};
|
||||
|
||||
const builderPkgPath = filterBuilder(this.pkg);
|
||||
this.builder = {
|
||||
isVite: (builderPkgPath[0] || '').includes('build-vite'),
|
||||
innerDepPrefix: '@fesInner',
|
||||
};
|
||||
|
||||
assert(existsSync(this.cwd), `cwd ${this.cwd} does not exist.`);
|
||||
|
||||
@ -108,7 +107,7 @@ export default class Service extends EventEmitter {
|
||||
this.configInstance = new Config({
|
||||
cwd: this.cwd,
|
||||
service: this,
|
||||
localConfig: this.env === 'development'
|
||||
localConfig: this.env === 'development',
|
||||
});
|
||||
this.userConfig = this.configInstance.getUserConfig();
|
||||
|
||||
@ -116,26 +115,25 @@ export default class Service extends EventEmitter {
|
||||
this.paths = getPaths({
|
||||
cwd: this.cwd,
|
||||
config: this.userConfig,
|
||||
env: this.env
|
||||
env: this.env,
|
||||
});
|
||||
|
||||
this.program = this.initCommand();
|
||||
|
||||
|
||||
// setup initial plugins
|
||||
const baseOpts = {
|
||||
pkg: this.pkg,
|
||||
cwd: this.cwd
|
||||
cwd: this.cwd,
|
||||
};
|
||||
this.initialPresets = resolvePresets({
|
||||
...baseOpts,
|
||||
presets: opts.presets || [],
|
||||
userConfigPresets: this.userConfig.presets || []
|
||||
userConfigPresets: this.userConfig.presets || [],
|
||||
});
|
||||
this.initialPlugins = resolvePlugins({
|
||||
...baseOpts,
|
||||
plugins: opts.plugins || [],
|
||||
userConfigPlugins: this.userConfig.plugins || []
|
||||
userConfigPlugins: this.userConfig.plugins || [],
|
||||
});
|
||||
}
|
||||
|
||||
@ -182,7 +180,7 @@ export default class Service extends EventEmitter {
|
||||
this.setStage(ServiceStage.pluginReady);
|
||||
await this.applyPlugins({
|
||||
key: 'onPluginReady',
|
||||
type: ApplyPluginsType.event
|
||||
type: ApplyPluginsType.event,
|
||||
});
|
||||
|
||||
// get config, including:
|
||||
@ -200,7 +198,7 @@ export default class Service extends EventEmitter {
|
||||
const paths = await this.applyPlugins({
|
||||
key: 'modifyPaths',
|
||||
type: ApplyPluginsType.modify,
|
||||
initialValue: this.paths
|
||||
initialValue: this.paths,
|
||||
});
|
||||
Object.keys(paths).forEach((key) => {
|
||||
this.paths[key] = paths[key];
|
||||
@ -211,14 +209,14 @@ export default class Service extends EventEmitter {
|
||||
const defaultConfig = await this.applyPlugins({
|
||||
key: 'modifyDefaultConfig',
|
||||
type: this.ApplyPluginsType.modify,
|
||||
initialValue: await this.configInstance.getDefaultConfig()
|
||||
initialValue: await this.configInstance.getDefaultConfig(),
|
||||
});
|
||||
this.config = await this.applyPlugins({
|
||||
key: 'modifyConfig',
|
||||
type: this.ApplyPluginsType.modify,
|
||||
initialValue: this.configInstance.getConfig({
|
||||
defaultConfig
|
||||
})
|
||||
defaultConfig,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -242,16 +240,10 @@ export default class Service extends EventEmitter {
|
||||
const pluginAPI = new PluginAPI(opts);
|
||||
|
||||
// register built-in methods
|
||||
[
|
||||
'onPluginReady',
|
||||
'modifyPaths',
|
||||
'onStart',
|
||||
'modifyDefaultConfig',
|
||||
'modifyConfig'
|
||||
].forEach((name) => {
|
||||
['onPluginReady', 'modifyPaths', 'onStart', 'modifyDefaultConfig', 'modifyConfig'].forEach((name) => {
|
||||
pluginAPI.registerMethod({
|
||||
name,
|
||||
exitsError: false
|
||||
exitsError: false,
|
||||
});
|
||||
});
|
||||
|
||||
@ -279,15 +271,14 @@ export default class Service extends EventEmitter {
|
||||
'args',
|
||||
'hasPlugins',
|
||||
'hasPresets',
|
||||
'setConfig'
|
||||
'setConfig',
|
||||
'builder',
|
||||
].includes(prop)
|
||||
) {
|
||||
return typeof this[prop] === 'function'
|
||||
? this[prop].bind(this)
|
||||
: this[prop];
|
||||
return typeof this[prop] === 'function' ? this[prop].bind(this) : this[prop];
|
||||
}
|
||||
return target[prop];
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -309,24 +300,23 @@ export default class Service extends EventEmitter {
|
||||
this.registerPlugin(preset);
|
||||
const { presets, plugins } = await this.applyAPI({
|
||||
api,
|
||||
apply
|
||||
apply,
|
||||
});
|
||||
|
||||
// register extra presets and plugins
|
||||
if (presets) {
|
||||
assert(
|
||||
Array.isArray(presets),
|
||||
`presets returned from preset ${id} must be Array.`
|
||||
);
|
||||
assert(Array.isArray(presets), `presets returned from preset ${id} must be Array.`);
|
||||
// 插到最前面,下个 while 循环优先执行
|
||||
this._extraPresets.splice(
|
||||
0,
|
||||
0,
|
||||
...presets.map(path => pathToObj({
|
||||
type: PluginType.preset,
|
||||
path,
|
||||
cwd: this.cwd
|
||||
}))
|
||||
...presets.map((path) =>
|
||||
pathToObj({
|
||||
type: PluginType.preset,
|
||||
path,
|
||||
cwd: this.cwd,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -339,42 +329,40 @@ export default class Service extends EventEmitter {
|
||||
}
|
||||
|
||||
if (plugins) {
|
||||
assert(
|
||||
Array.isArray(plugins),
|
||||
`plugins returned from preset ${id} must be Array.`
|
||||
);
|
||||
assert(Array.isArray(plugins), `plugins returned from preset ${id} must be Array.`);
|
||||
this._extraPlugins.push(
|
||||
...plugins.map(path => pathToObj({
|
||||
type: PluginType.plugin,
|
||||
path,
|
||||
cwd: this.cwd
|
||||
}))
|
||||
...plugins.map((path) =>
|
||||
pathToObj({
|
||||
type: PluginType.plugin,
|
||||
path,
|
||||
cwd: this.cwd,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async initPlugin(plugin) {
|
||||
const { id, key, apply } = plugin;
|
||||
|
||||
const api = this.getPluginAPI({
|
||||
id,
|
||||
key,
|
||||
service: this
|
||||
service: this,
|
||||
});
|
||||
|
||||
// register before apply
|
||||
this.registerPlugin(plugin);
|
||||
await this.applyAPI({
|
||||
api,
|
||||
apply
|
||||
apply,
|
||||
});
|
||||
}
|
||||
|
||||
getPluginOptsWithKey(key) {
|
||||
return getUserConfigWithKey({
|
||||
key,
|
||||
userConfig: this.userConfig
|
||||
userConfig: this.userConfig,
|
||||
});
|
||||
}
|
||||
|
||||
@ -424,10 +412,7 @@ export default class Service extends EventEmitter {
|
||||
switch (opts.type) {
|
||||
case ApplyPluginsType.add:
|
||||
if ('initialValue' in opts) {
|
||||
assert(
|
||||
Array.isArray(opts.initialValue),
|
||||
'applyPlugins failed, opts.initialValue must be Array if opts.type is add.'
|
||||
);
|
||||
assert(Array.isArray(opts.initialValue), 'applyPlugins failed, opts.initialValue must be Array if opts.type is add.');
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
const tAdd = new AsyncSeriesWaterfallHook(["memo"]);
|
||||
@ -440,12 +425,12 @@ export default class Service extends EventEmitter {
|
||||
name: hook.pluginId,
|
||||
stage: hook.stage || 0,
|
||||
// @ts-ignore
|
||||
before: hook.before
|
||||
before: hook.before,
|
||||
},
|
||||
async (memo) => {
|
||||
const items = await hook.fn(opts.args);
|
||||
return memo.concat(items);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
return tAdd.promise(opts.initialValue || []);
|
||||
@ -461,9 +446,9 @@ export default class Service extends EventEmitter {
|
||||
name: hook.pluginId,
|
||||
stage: hook.stage || 0,
|
||||
// @ts-ignore
|
||||
before: hook.before
|
||||
before: hook.before,
|
||||
},
|
||||
async memo => hook.fn(memo, opts.args)
|
||||
async (memo) => hook.fn(memo, opts.args),
|
||||
);
|
||||
}
|
||||
return tModify.promise(opts.initialValue);
|
||||
@ -479,18 +464,16 @@ export default class Service extends EventEmitter {
|
||||
name: hook.pluginId,
|
||||
stage: hook.stage || 0,
|
||||
// @ts-ignore
|
||||
before: hook.before
|
||||
before: hook.before,
|
||||
},
|
||||
async () => {
|
||||
await hook.fn(opts.args);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
return tEvent.promise();
|
||||
default:
|
||||
throw new Error(
|
||||
`applyPlugin failed, type is not defined or is not matched, got ${opts.type}.`
|
||||
);
|
||||
throw new Error(`applyPlugin failed, type is not defined or is not matched, got ${opts.type}.`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,8 +494,8 @@ export default class Service extends EventEmitter {
|
||||
key: 'onStart',
|
||||
type: ApplyPluginsType.event,
|
||||
args: {
|
||||
args
|
||||
}
|
||||
args,
|
||||
},
|
||||
});
|
||||
|
||||
return this.runCommand({ rawArgv, args });
|
||||
@ -539,7 +522,10 @@ export default class Service extends EventEmitter {
|
||||
if (commandOptionConfig.fn) {
|
||||
c.action(async () => {
|
||||
await commandOptionConfig.fn({
|
||||
rawArgv, args, options: c.opts(), program
|
||||
rawArgv,
|
||||
args,
|
||||
options: c.opts(),
|
||||
program,
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -551,14 +537,10 @@ export default class Service extends EventEmitter {
|
||||
async parseCommand() {
|
||||
this.program.on('--help', () => {
|
||||
console.log();
|
||||
console.log(
|
||||
` Run ${chalk.cyan(
|
||||
'fes <command> --help'
|
||||
)} for detailed usage of given command.`
|
||||
);
|
||||
console.log(` Run ${chalk.cyan('fes <command> --help')} for detailed usage of given command.`);
|
||||
console.log();
|
||||
});
|
||||
this.program.commands.forEach(c => c.on('--help', () => console.log()));
|
||||
this.program.commands.forEach((c) => c.on('--help', () => console.log()));
|
||||
return this.program.parseAsync(process.argv);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ function filterPluginAndPreset(type, pkg) {
|
||||
.filter(isPluginOrPreset.bind(null, type));
|
||||
}
|
||||
|
||||
function filterBuilder(pkg) {
|
||||
export function filterBuilder(pkg) {
|
||||
const builders = Object.keys(pkg.devDependencies || {})
|
||||
.concat(Object.keys(pkg.dependencies || {}))
|
||||
.filter((name) => /^@fesjs\/build-/.test(name));
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { resolvePkg } from '@fesjs/utils';
|
||||
import { resolveInnerDep } from '@fesjs/utils';
|
||||
import { name } from '../package.json';
|
||||
|
||||
const namespace = 'plugin-access';
|
||||
|
||||
@ -32,7 +33,7 @@ export default (api) => {
|
||||
path: absoluteFilePath,
|
||||
content: Mustache.render(readFileSync(join(__dirname, 'runtime/core.tpl'), 'utf-8'), {
|
||||
REPLACE_ROLES: JSON.stringify(roles),
|
||||
lodashPath: resolvePkg('lodash-es'),
|
||||
lodashPath: resolveInnerDep('lodash-es', api.builder),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -53,4 +54,10 @@ export default (api) => {
|
||||
api.addRuntimePluginKey(() => 'access');
|
||||
|
||||
api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`);
|
||||
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
runtime: ['AccessRuntimeConfig'],
|
||||
build: ['AccessBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { winPath } from '@fesjs/utils';
|
||||
import { name } from '../package.json';
|
||||
|
||||
const namespace = 'plugin-layout';
|
||||
|
||||
@ -28,13 +29,11 @@ export default (api) => {
|
||||
const absRuntimeFilePath = join(namespace, 'runtime.js');
|
||||
|
||||
api.onGenerateFiles(async () => {
|
||||
const { name } = api.pkg;
|
||||
|
||||
const HAS_LOCALE = api.hasPlugins(['@fesjs/plugin-locale']);
|
||||
|
||||
// .fes配置
|
||||
const userConfig = {
|
||||
title: name,
|
||||
title: api.pkg.name,
|
||||
footer: 'Created by Fes.js',
|
||||
...(api.config.layout || {}),
|
||||
};
|
||||
@ -81,4 +80,10 @@ export default (api) => {
|
||||
children: routes,
|
||||
},
|
||||
]);
|
||||
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
runtime: ['LayoutRuntimeConfig'],
|
||||
build: ['LayoutBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { resolvePkg } from '@fesjs/utils';
|
||||
import { resolveInnerDep } from '@fesjs/utils';
|
||||
import { getLocalesJSON } from './utils';
|
||||
import { name } from '../package.json';
|
||||
|
||||
const namespace = 'plugin-locale';
|
||||
|
||||
@ -62,7 +63,7 @@ export default (api) => {
|
||||
2,
|
||||
),
|
||||
BASE_NAVIGATOR: userConfig.baseNavigator,
|
||||
VUE_I18N_PATH: resolvePkg('vue-i18n'),
|
||||
VUE_I18N_PATH: resolveInnerDep('vue-i18n', api.builder),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -81,4 +82,9 @@ export default (api) => {
|
||||
]);
|
||||
|
||||
api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`);
|
||||
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
build: ['LocalBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { resolvePkg } from '@fesjs/utils';
|
||||
import { resolveInnerDep } from '@fesjs/utils';
|
||||
import { name } from '../package.json';
|
||||
|
||||
const namespace = 'plugin-monaco-editor';
|
||||
|
||||
@ -47,14 +48,14 @@ export default (api) => {
|
||||
api.writeTmpFile({
|
||||
path: absLoaderFilePath,
|
||||
content: Mustache.render(readFileSync(join(__dirname, 'runtime/loader.tpl'), 'utf-8'), {
|
||||
MONACO_EDITOR: resolvePkg('monaco-editor'),
|
||||
MONACO_EDITOR: resolveInnerDep('monaco-editor', api.builder),
|
||||
}),
|
||||
});
|
||||
|
||||
api.writeTmpFile({
|
||||
path: absEditorFilePath,
|
||||
content: Mustache.render(readFileSync(join(__dirname, 'runtime/editor.tpl'), 'utf-8'), {
|
||||
LODASH_ES: resolvePkg('lodash-es'),
|
||||
LODASH_ES: resolveInnerDep('lodash-es', api.builder),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -80,4 +81,9 @@ export default (api) => {
|
||||
webpackConfig.plugin('monaco-editor').use(require('monaco-editor-webpack-plugin'), [api.config?.monacoEditor || {}]);
|
||||
return webpackConfig;
|
||||
});
|
||||
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
build: ['MonacoEditorBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -44,6 +44,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"@fesjs/build-webpack": "^1.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"@fesjs/fes-design": "^0.1.10"
|
||||
},
|
||||
|
@ -44,6 +44,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"@fesjs/build-webpack": "^1.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"@fesjs/fes-design": "^0.1.10"
|
||||
},
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { name } from '../package.json';
|
||||
|
||||
export default (api) => {
|
||||
api.describe({
|
||||
key: 'qiankun',
|
||||
@ -14,4 +16,9 @@ export default (api) => {
|
||||
api.addRuntimePluginKey(() => 'qiankun');
|
||||
|
||||
api.registerPlugins([require.resolve('./main'), require.resolve('./micro')]);
|
||||
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
build: ['QiankunBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { resolvePkg } from '@fesjs/utils';
|
||||
import { resolveInnerDep } from '@fesjs/utils';
|
||||
import { defaultMainRootId, defaultHistoryType, qiankunStateForMicroModelNamespace } from '../constants';
|
||||
import modifyRoutes from './modifyRoutes';
|
||||
|
||||
@ -39,24 +39,20 @@ export default function (api) {
|
||||
content: Mustache.render(readFileSync(join(__dirname, 'runtime/MicroApp.tpl'), 'utf-8'), {
|
||||
qiankunStateForMicroModelNamespace,
|
||||
HAS_PLUGIN_MODEL: HAS_PLUGIN_MODEL && existsSync(winPath(join(api.paths.absSrcPath, 'models/qiankunStateForMicro.js'))),
|
||||
QIANKUN: resolvePkg('qiankun'),
|
||||
LODASH_ES: resolvePkg('lodash-es'),
|
||||
QIANKUN: resolveInnerDep('qiankun', api.builder),
|
||||
LODASH_ES: resolveInnerDep('lodash-es', api.builder),
|
||||
}),
|
||||
});
|
||||
|
||||
api.writeTmpFile({
|
||||
path: absMicroAppWithMemoHistoryPath,
|
||||
content: Mustache.render(readFileSync(join(__dirname, 'runtime/MicroAppWithMemoHistory.tpl'), 'utf-8'), {}),
|
||||
});
|
||||
|
||||
api.writeTmpFile({
|
||||
path: absRuntimePath,
|
||||
content: readFileSync(join(__dirname, 'runtime/runtime.tpl'), 'utf-8'),
|
||||
});
|
||||
|
||||
api.writeTmpFile({
|
||||
path: absGetMicroAppRouteCompPath,
|
||||
content: readFileSync(join(__dirname, 'runtime/getMicroAppRouteComponent.tpl'), 'utf-8'),
|
||||
api.copyTmpFiles({
|
||||
namespace,
|
||||
path: join(__dirname, 'runtime'),
|
||||
ignore: ['.tpl'],
|
||||
});
|
||||
|
||||
const { main: options } = api.config?.qiankun || {};
|
||||
|
@ -2,12 +2,15 @@ import { defaultHistoryType } from '../constants';
|
||||
|
||||
function getMicroApp(options) {
|
||||
const { key, microAppName, masterHistoryType, base, namespace, ...normalizedRouteProps } = options;
|
||||
return `(() => {
|
||||
const { getMicroAppRouteComponent } = require('@@/${namespace}/getMicroAppRouteComponent');
|
||||
return getMicroAppRouteComponent({key: '${key}', appName: '${microAppName}', base: '${base}', masterHistoryType: '${masterHistoryType}', routeProps: ${JSON.stringify(
|
||||
return `() => {
|
||||
return new Promise((resolve)=>{
|
||||
import('@@/${namespace}/getMicroAppRouteComponent').then(({ getMicroAppRouteComponent })=>{
|
||||
resolve(getMicroAppRouteComponent({ key: '${key}', appName: '${microAppName}', base: '${base}', masterHistoryType: '${masterHistoryType}', routeProps: ${JSON.stringify(
|
||||
normalizedRouteProps,
|
||||
)} })
|
||||
})()`;
|
||||
)} }))
|
||||
})
|
||||
})
|
||||
}`;
|
||||
}
|
||||
|
||||
function modifyRoutesWithAttachMode({ routes, masterHistoryType, base, namespace }) {
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
onMounted,
|
||||
} from "vue";
|
||||
import { loadMicroApp } from "{{{QIANKUN}}}";
|
||||
import {mergeWith} from "{{{LODASH_ES}}}";
|
||||
import { mergeWith } from "{{{LODASH_ES}}}";
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { getMasterOptions } from "./masterOptions";
|
||||
import { onBeforeRouteLeave } from "@@/core/coreExports";
|
||||
|
@ -1,22 +1,19 @@
|
||||
|
||||
import {
|
||||
defineComponent, isRef, watch
|
||||
} from 'vue';
|
||||
import { defineComponent, watch } from 'vue';
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { MicroApp } from './MicroApp';
|
||||
|
||||
|
||||
export const MicroAppWithMemoHistory = defineComponent({
|
||||
components: {
|
||||
MicroApp
|
||||
MicroApp,
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
settings: Object,
|
||||
lifeCycles: Object,
|
||||
url: String
|
||||
url: String,
|
||||
},
|
||||
setup(props, { attrs }) {
|
||||
let microRouter;
|
||||
@ -24,9 +21,12 @@ export const MicroAppWithMemoHistory = defineComponent({
|
||||
microRouter = router;
|
||||
microRouter.push(props.url);
|
||||
};
|
||||
watch(()=>props.url, () => {
|
||||
microRouter.push(props.url);
|
||||
});
|
||||
watch(
|
||||
() => props.url,
|
||||
() => {
|
||||
microRouter.push(props.url);
|
||||
},
|
||||
);
|
||||
return () => <MicroApp onRouterInit={onRouterInit} {...props} {...attrs}></MicroApp>;
|
||||
}
|
||||
},
|
||||
});
|
@ -0,0 +1,6 @@
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { MicroApp } from './MicroApp';
|
||||
|
||||
export function getMicroAppRouteComponent({ key, appName, base, masterHistoryType, routeProps }) {
|
||||
return <MicroApp key={key} base={base} masterHistoryType={masterHistoryType} name={appName} {...routeProps} />;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import { MicroApp } from './MicroApp';
|
||||
|
||||
export function getMicroAppRouteComponent({
|
||||
key,
|
||||
appName,
|
||||
base,
|
||||
masterHistoryType,
|
||||
routeProps
|
||||
}) {
|
||||
|
||||
return <MicroApp key={key} base={base} masterHistoryType={masterHistoryType} name={appName} {...routeProps} />;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Logger } from '@fesjs/compiler';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { resolvePkg } from '@fesjs/utils';
|
||||
import { resolveInnerDep } from '@fesjs/utils';
|
||||
import { name } from '../package.json';
|
||||
|
||||
const logger = new Logger('fes:plugin-request');
|
||||
@ -45,7 +45,7 @@ export default (api) => {
|
||||
content: requestTemplate
|
||||
.replace('REPLACE_DATA_FIELD', JSON.stringify(dataField))
|
||||
.replace('REPLACE_BASE', base || '')
|
||||
.replace('AXIOS_PATH', resolvePkg('axios')),
|
||||
.replace('AXIOS_PATH', resolveInnerDep('axios', api.builder)),
|
||||
});
|
||||
});
|
||||
|
||||
@ -67,13 +67,9 @@ export default (api) => {
|
||||
},
|
||||
]);
|
||||
|
||||
api.addRuntimeType(() => ({
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
specifier: ['RequestRuntimeConfig'],
|
||||
}));
|
||||
|
||||
api.addBuildType(() => ({
|
||||
source: name,
|
||||
specifier: ['RequestBuildConfig'],
|
||||
runtime: ['RequestRuntimeConfig'],
|
||||
build: ['RequestBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -49,8 +49,8 @@ export default (api) => {
|
||||
return memo;
|
||||
});
|
||||
|
||||
api.addBuildType(() => ({
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
specifier: ['WindicssBuildConfig'],
|
||||
build: ['WindicssBuildConfig'],
|
||||
}));
|
||||
};
|
||||
|
@ -1,17 +1,14 @@
|
||||
function importsToStr(imports) {
|
||||
return imports.map((imp) => {
|
||||
const { source, specifier } = imp;
|
||||
if (specifier) {
|
||||
return `import {${specifier.join(', ')}} from '${source}';`;
|
||||
}
|
||||
return '';
|
||||
const { source, build = [], runtime = [] } = imp;
|
||||
return `import {${build.concat(runtime).join(', ')}} from '${source}';`;
|
||||
});
|
||||
}
|
||||
|
||||
function genTypeContent(name, imports) {
|
||||
function genTypeContent(imports) {
|
||||
return {
|
||||
TYP_NAME: name,
|
||||
TYPES: imports.reduce((previousValue, currentValue) => previousValue.concat(currentValue.specifier || []), []).join(' & '),
|
||||
RUNTIME_TYPES: imports.reduce((previousValue, currentValue) => previousValue.concat(currentValue.runtime || []), []).join(' & '),
|
||||
BUILD_TYPES: imports.reduce((previousValue, currentValue) => previousValue.concat(currentValue.build || []), []).join(' & '),
|
||||
imports: importsToStr(imports).join('\n'),
|
||||
};
|
||||
}
|
||||
@ -22,31 +19,20 @@ export default function (api) {
|
||||
} = api;
|
||||
|
||||
api.onGenerateFiles(async () => {
|
||||
const runtimeTypeName = 'PluginRuntimeConfig';
|
||||
const buildTypeName = 'PluginBuildConfig';
|
||||
const typeTpl = `
|
||||
{{{ imports }}}
|
||||
|
||||
export type {{{TYP_NAME}}} = {{{TYPES}}}
|
||||
export type PluginRuntimeConfig = {{{RUNTIME_TYPES}}};
|
||||
export type PluginBuildConfig = {{{BUILD_TYPES}}};
|
||||
`;
|
||||
const runtimeImportSources = await api.applyPlugins({
|
||||
key: 'addRuntimeType',
|
||||
const importSources = await api.applyPlugins({
|
||||
key: 'addConfigType',
|
||||
type: api.ApplyPluginsType.add,
|
||||
initialValue: [],
|
||||
});
|
||||
api.writeTmpFile({
|
||||
path: 'runtime.d.ts',
|
||||
content: Mustache.render(typeTpl, genTypeContent(runtimeTypeName, runtimeImportSources)),
|
||||
});
|
||||
|
||||
const buildImportSources = await api.applyPlugins({
|
||||
key: 'addBuildType',
|
||||
type: api.ApplyPluginsType.add,
|
||||
initialValue: [],
|
||||
});
|
||||
api.writeTmpFile({
|
||||
path: 'build.d.ts',
|
||||
content: Mustache.render(typeTpl, genTypeContent(buildTypeName, buildImportSources)),
|
||||
path: 'configType.d.ts',
|
||||
content: Mustache.render(typeTpl, genTypeContent(importSources)),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ export default function (api) {
|
||||
'addEntryCode',
|
||||
'modifyRoutes',
|
||||
|
||||
'addRuntimeType',
|
||||
'addBuildType',
|
||||
'addConfigType',
|
||||
|
||||
'addTmpGenerateWatcherPaths',
|
||||
|
||||
|
@ -86,7 +86,6 @@ function getRouteMeta(content) {
|
||||
|
||||
let cacheGenRoutes = {};
|
||||
|
||||
// TODO 约定 layout 目录作为布局文件夹,
|
||||
const genRoutes = function (parentRoutes, path, parentRoutePath, config) {
|
||||
const dirList = readdirSync(path);
|
||||
const hasLayout = checkHasLayout(path);
|
||||
@ -231,45 +230,33 @@ const getRoutesJSON = function ({ routes, config }) {
|
||||
// 因为要往 routes 里加无用的信息,所以必须 deep clone 一下,避免污染
|
||||
const clonedRoutes = lodash.cloneDeep(routes);
|
||||
|
||||
const importList = [];
|
||||
|
||||
function replacer(key, value) {
|
||||
switch (key) {
|
||||
case 'component':
|
||||
if (isFunctionComponent(value)) return value;
|
||||
if (config.dynamicImport) {
|
||||
// TODO 针对目录进行 chunk 划分,import(/* webpackChunkName: "group-user" */ './UserDetails.vue')
|
||||
return `() => import('${value}')`;
|
||||
}
|
||||
return genComponentName(value, config);
|
||||
default:
|
||||
return value;
|
||||
if (key !== 'component') {
|
||||
return value;
|
||||
}
|
||||
if (isFunctionComponent(value)) return value;
|
||||
if (config.dynamicImport) {
|
||||
// TODO 针对目录进行 chunk 划分,import(/* webpackChunkName: "group-user" */ './UserDetails.vue')
|
||||
return `() => import('${value}')`;
|
||||
}
|
||||
const componentName = genComponentName(value, config);
|
||||
importList.push(`import ${componentName} from '${value}'`);
|
||||
return componentName;
|
||||
}
|
||||
|
||||
return JSON.stringify(clonedRoutes, replacer, 2)
|
||||
const routesJSON = JSON.stringify(clonedRoutes, replacer, 2)
|
||||
.replace(/"component": ("(.+?)")/g, (global, m1, m2) => `"component": ${m2.replace(/\^/g, '"')}`)
|
||||
.replace(/\\r\\n/g, '\r\n')
|
||||
.replace(/\\n/g, '\r\n');
|
||||
|
||||
return {
|
||||
importList,
|
||||
routesJSON,
|
||||
};
|
||||
};
|
||||
|
||||
function genComponentImportExpression(routes, config) {
|
||||
if (config.dynamicImport) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result = [];
|
||||
for (const routeConfig of routes) {
|
||||
if (routeConfig.children) {
|
||||
result.push(...genComponentImportExpression(routeConfig.children, config));
|
||||
}
|
||||
|
||||
if (routeConfig.component && !isFunctionComponent(routeConfig.component)) {
|
||||
result.push(`import ${genComponentName(routeConfig.component, config)} from '${routeConfig.component}';`);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default function (api) {
|
||||
api.describe({
|
||||
key: 'router',
|
||||
@ -326,12 +313,12 @@ export default function (api) {
|
||||
|
||||
api.onGenerateFiles(async () => {
|
||||
const routesTpl = readFileSync(join(__dirname, 'template/routes.tpl'), 'utf-8');
|
||||
const routes = await api.getRoutes();
|
||||
const routes = await api.getRoutesJSON();
|
||||
api.writeTmpFile({
|
||||
path: absCoreFilePath,
|
||||
content: Mustache.render(routesTpl, {
|
||||
COMPONENTS_IMPORT: genComponentImportExpression(routes, api.config).join('\n'),
|
||||
routes: await api.getRoutesJSON(),
|
||||
COMPONENTS_IMPORT: routes.importList.join('\n'),
|
||||
routes: routes.routesJSON,
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -44,6 +44,6 @@ export default defineBuildConfig({
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -29,19 +29,19 @@
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"*.js",
|
||||
".fes.js",
|
||||
"src/**/*",
|
||||
"tests/**/*",
|
||||
"test/**/*",
|
||||
"__test__/**/*",
|
||||
"typings/**/*",
|
||||
"config/**/*",
|
||||
"src/.fes/runtime.d.ts"
|
||||
"src/.fes/configType.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"build",
|
||||
"dist",
|
||||
"scripts",
|
||||
"webpack",
|
||||
"jest"
|
||||
"jest",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"config/**/*",
|
||||
".eslintrc.js",
|
||||
".stylelintrc.js",
|
||||
".prettierrc.js"
|
||||
".prettierrc.js",
|
||||
"src/.fes/configType.d.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "build", "dist", "scripts", "src/.fes/*", "webpack", "jest"]
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import Generator from './Generator';
|
||||
import winPath from './winPath';
|
||||
import delay from './delay';
|
||||
import resolvePkg from './resolvePkg';
|
||||
import resolveInnerDep from './resolveInnerDep';
|
||||
import compatESModuleRequire from './compatESModuleRequire';
|
||||
import cleanRequireCache from './cleanRequireCache';
|
||||
import parseRequireDeps from './parseRequireDeps';
|
||||
@ -47,4 +48,16 @@ export {
|
||||
generator,
|
||||
};
|
||||
|
||||
export { Generator, winPath, delay, compatESModuleRequire, cleanRequireCache, parseRequireDeps, mergeConfig, resolvePkg, generateFiles, getAppEntryPath };
|
||||
export {
|
||||
Generator,
|
||||
winPath,
|
||||
delay,
|
||||
compatESModuleRequire,
|
||||
cleanRequireCache,
|
||||
parseRequireDeps,
|
||||
mergeConfig,
|
||||
resolvePkg,
|
||||
resolveInnerDep,
|
||||
generateFiles,
|
||||
getAppEntryPath,
|
||||
};
|
||||
|
12
packages/fes-utils/src/resolveInnerDep.js
Normal file
12
packages/fes-utils/src/resolveInnerDep.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { dirname } from 'path';
|
||||
import winPath from './winPath';
|
||||
|
||||
const resolvePkg = (pkgName, builder) => {
|
||||
const pkgPath = dirname(require.resolve(`${pkgName}/package.json`));
|
||||
if (builder.isVite) {
|
||||
return winPath(pkgPath.replace('/', `${builder.innerDepPrefix}/`));
|
||||
}
|
||||
return winPath(pkgPath);
|
||||
};
|
||||
|
||||
export default resolvePkg;
|
4
packages/fes/types.d.ts
vendored
4
packages/fes/types.d.ts
vendored
@ -1,8 +1,8 @@
|
||||
import { Component, DefineComponent, App } from 'vue';
|
||||
import { RouteRecordRaw, Router } from 'vue-router';
|
||||
import { Plugin } from '@fesjs/runtime';
|
||||
import { PluginRuntimeConfig } from '@@/runtime';
|
||||
import { PluginBuildConfig } from '@@/build';
|
||||
// @ts-ignore
|
||||
import type { PluginRuntimeConfig, PluginBuildConfig } from '@@/configType';
|
||||
|
||||
// @ts-ignore
|
||||
export * from '@@/core/coreExports';
|
||||
|
Loading…
Reference in New Issue
Block a user