Skip to content

Commit

Permalink
feat: bff support independent project
Browse files Browse the repository at this point in the history
  • Loading branch information
keepview committed Dec 23, 2024
1 parent 0ac2af4 commit 6ea2970
Show file tree
Hide file tree
Showing 75 changed files with 2,169 additions and 134 deletions.
13 changes: 13 additions & 0 deletions .changeset/mean-bobcats-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@modern-js/create-request': patch
'@modern-js/app-tools': patch
'@modern-js/bff-runtime': patch
'@modern-js/bff-core': patch
'@modern-js/plugin-bff': patch
'@modern-js/server': patch
'@modern-js/core': patch
---

feat: bff support independent project

feat: bff 支持跨项目调用
2 changes: 2 additions & 0 deletions packages/cli/core/src/types/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export interface IAppContext {
serverRoutes: ServerRoute[];
/** Whether to use api only mode */
apiOnly: boolean;
/** prefix for independent bff projects */
indepBffPrefix?: string;
/** The Builder instance */
builder?: UniBuilderInstance | UniBuilderWebpackInstance;
/** Tools type of the current project */
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/plugin-bff/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
"types": "./dist/types/loader.d.ts",
"jsnext:source": "./src/loader.ts",
"default": "./dist/cjs/loader.js"
},
"./create-request": {
"types": "./dist/types/create-request.d.ts",
"jsnext:source": "./src/create-request.ts",
"default": "./dist/cjs/create-request.js"
}
},
"typesVersions": {
Expand Down
185 changes: 143 additions & 42 deletions packages/cli/plugin-bff/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,126 @@ import { ApiRouter } from '@modern-js/bff-core';
import { compile } from '@modern-js/server-utils';
import type { ServerRoute } from '@modern-js/types';
import { fs, API_DIR, SHARED_DIR, normalizeOutputPath } from '@modern-js/utils';
import clientGenerator from './utils/client-generator';
import pluginGenerator from './utils/plugin-generator';
import runtimeGenerator from './utils/runtime-generator';

const DEFAULT_API_PREFIX = '/api';
const TS_CONFIG_FILENAME = 'tsconfig.json';

export const bffPlugin = (): CliPlugin<AppTools> => ({
name: '@modern-js/plugin-bff',
setup: api => {
const compileApi = async () => {
const {
appDirectory,
distDirectory,
apiDirectory,
sharedDirectory,
moduleType,
} = api.useAppContext();
const modernConfig = api.useResolvedConfigContext();

const distDir = path.resolve(distDirectory);
const apiDir = apiDirectory || path.resolve(appDirectory, API_DIR);
const sharedDir =
sharedDirectory || path.resolve(appDirectory, SHARED_DIR);
const tsconfigPath = path.resolve(appDirectory, TS_CONFIG_FILENAME);

const sourceDirs = [];
if (await fs.pathExists(apiDir)) {
sourceDirs.push(apiDir);
}

if (await fs.pathExists(sharedDir)) {
sourceDirs.push(sharedDir);
}

const { server } = modernConfig;
const { alias } = modernConfig.source;
const { babel } = modernConfig.tools;

if (sourceDirs.length > 0) {
await compile(
appDirectory,
{
server,
alias,
babelConfig: babel,
},
{
sourceDirs,
distDir,
tsconfigPath,
moduleType,
},
);
}
};

const generator = async () => {
const { appDirectory, apiDirectory, lambdaDirectory, port } =
api.useAppContext();

const modernConfig = api.useResolvedConfigContext();
const { bff } = modernConfig || {};
const prefix = bff?.prefix || DEFAULT_API_PREFIX;
const httpMethodDecider = bff?.httpMethodDecider;

const apiRouter = new ApiRouter({
apiDir: apiDirectory,
appDir: appDirectory,
lambdaDir: lambdaDirectory,
prefix,
httpMethodDecider,
isBuild: true,
});

const lambdaDir = apiRouter.getLambdaDir();
const existLambda = apiRouter.isExistLambda();

const options = {
prefix,
appDir: appDirectory,
apiDir: apiDirectory,
lambdaDir,
existLambda,
port,
requestCreator: (bff as any)?.requestCreator,
httpMethodDecider,
};

const runtime =
(bff as any)?.runtime || '@modern-js/plugin-bff/create-request';
await clientGenerator(options);
await pluginGenerator(prefix);
await runtimeGenerator(runtime);
};

const handleCrossProjectInvocation = async () => {
const { bff } = api.useResolvedConfigContext();
if (bff?.enableCrossProjectInvocation) {
await compileApi();
await generator();
}
};

return {
config() {
return {
tools: {
bundlerChain: (chain, { CHAIN_ID, isServer }) => {
const { port, appDirectory, apiDirectory, lambdaDirectory } =
api.useAppContext();
const {
port,
appDirectory,
apiDirectory,
lambdaDirectory,
indepBffPrefix,
} = api.useAppContext();
const modernConfig = api.useResolvedConfigContext();
const { bff } = modernConfig || {};
const prefix = bff?.prefix || DEFAULT_API_PREFIX;
const prefix =
indepBffPrefix || bff?.prefix || DEFAULT_API_PREFIX;
const httpMethodDecider = bff?.httpMethodDecider;

const apiRouter = new ApiRouter({
Expand Down Expand Up @@ -60,6 +163,7 @@ export const bffPlugin = (): CliPlugin<AppTools> => ({
});

chain.resolve.alias.set('@api', apiDirectory);

chain.resolve.alias.set(
'@modern-js/runtime/bff',
isServer
Expand All @@ -76,8 +180,10 @@ export const bffPlugin = (): CliPlugin<AppTools> => ({
modifyServerRoutes({ routes }) {
const modernConfig = api.useResolvedConfigContext();

const { indepBffPrefix } = api.useAppContext();

const { bff } = modernConfig || {};
const prefix = bff?.prefix || '/api';
const prefix = indepBffPrefix || bff?.prefix || '/api';

const prefixList: string[] = [];

Expand Down Expand Up @@ -117,51 +223,46 @@ export const bffPlugin = (): CliPlugin<AppTools> => ({

return { plugins };
},
async beforeDev() {
await handleCrossProjectInvocation();
},

async afterBuild() {
const {
appDirectory,
distDirectory,
apiDirectory,
sharedDirectory,
moduleType,
} = api.useAppContext();
const modernConfig = api.useResolvedConfigContext();

const distDir = path.resolve(distDirectory);
const apiDir = apiDirectory || path.resolve(appDirectory, API_DIR);
const sharedDir =
sharedDirectory || path.resolve(appDirectory, SHARED_DIR);
const tsconfigPath = path.resolve(appDirectory, TS_CONFIG_FILENAME);
const { bff } = api.useResolvedConfigContext();
await compileApi();

const sourceDirs = [];
if (await fs.pathExists(apiDir)) {
sourceDirs.push(apiDir);
if (bff?.enableCrossProjectInvocation) {
await generator();
}
},
async watchFiles() {
const appContext = api.useAppContext();
const config = api.useResolvedConfigContext();
const { generateWatchFiles } = require('@modern-js/app-tools');
const files = await generateWatchFiles(
appContext,
config.source.configDir,
);

if (await fs.pathExists(sharedDir)) {
sourceDirs.push(sharedDir);
if (config?.bff?.enableCrossProjectInvocation) {
files.push(appContext.apiDirectory);
}

const { server } = modernConfig;
const { alias } = modernConfig.source;
const { babel } = modernConfig.tools;

if (sourceDirs.length > 0) {
await compile(
appDirectory,
{
server,
alias,
babelConfig: babel,
},
{
sourceDirs,
distDir,
tsconfigPath,
moduleType,
},
);
return files;
},

async fileChange(e: {
filename: string;
eventType: string;
isPrivate: boolean;
}) {
const { filename, eventType, isPrivate } = e;
if (
!isPrivate &&
(eventType === 'change' || eventType === 'unlink') &&
filename.startsWith('api/')
) {
await handleCrossProjectInvocation();
}
},
};
Expand Down
1 change: 1 addition & 0 deletions packages/cli/plugin-bff/src/create-request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '@modern-js/create-request';
19 changes: 16 additions & 3 deletions packages/cli/plugin-bff/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,20 @@ export default (): ServerPlugin => ({
return {
async prepare() {
const appContext = api.useAppContext();
const { appDirectory, distDirectory, render } = appContext;
const {
appDirectory,
distDirectory,
render,
indepBffPrefix,
apiDirectory,
} = appContext;
const root = isProd() ? distDirectory : appDirectory;
const apiPath = path.resolve(root || process.cwd(), API_DIR);

let apiPath = path.resolve(root || process.cwd(), API_DIR);

if (indepBffPrefix && apiDirectory) {
apiPath = apiDirectory;
}
apiAppPath = path.resolve(apiPath, API_APP_NAME);

const apiMod = await requireExistModule(apiAppPath);
Expand All @@ -53,7 +64,8 @@ export default (): ServerPlugin => ({

/** bind api server */
const config = api.useConfigContext();
const prefix = config?.bff?.prefix || '/api';
const prefix =
(indepBffPrefix as string) || config?.bff?.prefix || '/api';
const enableHandleWeb = config?.bff?.enableHandleWeb;
const httpMethodDecider = config?.bff?.httpMethodDecider;

Expand Down Expand Up @@ -131,6 +143,7 @@ export default (): ServerPlugin => ({
const apiDir = path.resolve(pwd, API_DIR);
const appContext = api.useAppContext();
const { apiDirectory, lambdaDirectory } = appContext;

apiRouter = new ApiRouter({
appDir: pwd,
apiDir: (apiDirectory as string) || apiDir,
Expand Down
Loading

0 comments on commit 6ea2970

Please sign in to comment.