Skip to content

Commit b00ef13

Browse files
authored
fix(dts-plugin): support compile vue@3 dts (#2723)
1 parent 52433fe commit b00ef13

33 files changed

+27764
-27173
lines changed

.changeset/pink-months-listen.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@module-federation/third-party-dts-extractor': patch
3+
'@module-federation/dts-plugin': patch
4+
'@module-federation/enhanced': patch
5+
'@module-federation/sdk': patch
6+
---
7+
8+
fix(dts-plugin): support compile vue@3 dts

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,8 @@ packages/enhanced/test/js
6060

6161
/apps/manifest-demo/**/@mf-types/
6262
/apps/manifest-demo/webpack-host/@mf-types/
63+
/apps/manifest-demo/3008-webpack-host/@mf-types/
64+
65+
# dts test cases
66+
**/dist-test
67+
**/dist-test/**

apps/runtime-demo/3005-runtime-host/webpack.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ module.exports = composePlugins(withNx(), withReact(), (config, context) => {
4545
exposes: {
4646
'./Button': './src/Button.tsx',
4747
},
48+
dts: {
49+
tsConfigPath: path.resolve(__dirname, 'tsconfig.app.json'),
50+
},
4851
shared: {
4952
lodash: {
5053
singleton: true,
Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"extends": "./tsconfig.json",
33
"compilerOptions": {
4-
"outDir": "../../../dist/out-tsc",
4+
"composite": true,
5+
"declaration": true,
56
"types": [
67
"node",
78
"@nx/react/typings/cssmodule.d.ts",
@@ -12,17 +13,5 @@
1213
"../../../node_modules/@nx/react/typings/cssmodule.d.ts",
1314
"../../../node_modules/@nx/react/typings/image.d.ts"
1415
],
15-
"exclude": [
16-
"jest.config.ts",
17-
"**/*.spec.ts",
18-
"**/*.test.ts",
19-
"**/*.spec.tsx",
20-
"**/*.test.tsx",
21-
"**/*.spec.js",
22-
"**/*.test.js",
23-
"**/*.spec.jsx",
24-
"**/*.test.jsx",
25-
"dist/**"
26-
],
27-
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
16+
"include": ["src/**/*"]
2817
}

apps/runtime-demo/3006-runtime-remote/webpack.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
} = require('@module-federation/enhanced/webpack');
1212
const packageJson = require('./package.json');
1313

14+
process.env.FEDERATION_DEBUG = true;
1415
module.exports = composePlugins(
1516
withNx(),
1617
withReact(),
@@ -60,6 +61,9 @@ module.exports = composePlugins(
6061
requiredVersion: '^18.2.0',
6162
},
6263
},
64+
dts: {
65+
tsConfigPath: path.resolve(__dirname, 'tsconfig.app.json'),
66+
},
6367
runtimePlugins: [path.join(__dirname, './runtimePlugin.ts')],
6468
}),
6569
);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@
212212
"vite-tsconfig-paths": "4.2.3",
213213
"vitest": "1.2.2",
214214
"vitest-fetch-mock": "^0.2.2",
215-
"vue-tsc": "1.8.27",
215+
"vue-tsc": "^2.0.26",
216216
"wait-on": "^7.2.0",
217217
"webpack": "^5.90.0",
218218
"webpack-virtual-modules": "0.6.2",

packages/dts-plugin/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,14 @@
6363
"@types/ws": "8.5.10",
6464
"@types/koa": "2.11.2",
6565
"@types/node-schedule": "2.1.7",
66-
"@module-federation/runtime": "workspace:*"
66+
"@module-federation/runtime": "workspace:*",
67+
"vue": "^3.4.29",
68+
"@vue/tsconfig": "^0.5.1",
69+
"vue-tsc": "^2.0.26"
6770
},
6871
"peerDependencies": {
6972
"typescript": "^4.9.0 || ^5.0.0",
70-
"vue-tsc": "^1.0.24"
73+
"vue-tsc": ">=1.0.24"
7174
},
7275
"peerDependenciesMeta": {
7376
"vue-tsc": {

packages/dts-plugin/src/core/configurations/remotePlugin.test.ts

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,28 @@ describe('hostPlugin', () => {
3535
});
3636

3737
expect(tsConfig).toStrictEqual({
38-
target: 4,
39-
module: 99,
40-
lib: ['lib.esnext.d.ts'],
41-
moduleResolution: 2,
42-
esModuleInterop: true,
43-
strict: true,
44-
strictNullChecks: true,
45-
resolveJsonModule: true,
46-
configFilePath: undefined,
47-
emitDeclarationOnly: true,
48-
noEmit: false,
49-
declaration: true,
50-
outDir: resolve(
51-
remoteOptions.context,
52-
'dist/@mf-types/compiled-types',
53-
),
38+
compileOnSave: false,
39+
compilerOptions: {
40+
target: 'es2017',
41+
module: 'esnext',
42+
lib: ['esnext'],
43+
moduleResolution: 'node',
44+
esModuleInterop: true,
45+
strict: true,
46+
strictNullChecks: true,
47+
resolveJsonModule: true,
48+
emitDeclarationOnly: true,
49+
noEmit: false,
50+
declaration: true,
51+
outDir: resolve(
52+
remoteOptions.context,
53+
'dist/@mf-types/compiled-types',
54+
),
55+
rootDir: resolve(__dirname),
56+
},
57+
files: ['./src/components/button', './src/components/anotherButton'],
58+
include: [],
59+
exclude: [],
5460
});
5561

5662
expect(mapComponentsToExpose).toStrictEqual({
@@ -91,22 +97,28 @@ describe('hostPlugin', () => {
9197
});
9298

9399
expect(tsConfig).toStrictEqual({
94-
module: 99,
95-
resolveJsonModule: true,
96-
strict: true,
97-
strictNullChecks: true,
98-
target: 4,
99-
lib: ['lib.esnext.d.ts'],
100-
moduleResolution: 2,
101-
esModuleInterop: true,
102-
configFilePath: undefined,
103-
emitDeclarationOnly: true,
104-
noEmit: false,
105-
declaration: true,
106-
outDir: resolve(
107-
remoteOptions.context,
108-
'dist/typesFolder/compiledTypesFolder',
109-
),
100+
compileOnSave: false,
101+
compilerOptions: {
102+
module: 'esnext',
103+
resolveJsonModule: true,
104+
strict: true,
105+
strictNullChecks: true,
106+
target: 'es2017',
107+
lib: ['esnext'],
108+
moduleResolution: 'node',
109+
esModuleInterop: true,
110+
emitDeclarationOnly: true,
111+
noEmit: false,
112+
declaration: true,
113+
outDir: resolve(
114+
remoteOptions.context,
115+
'dist/typesFolder/compiledTypesFolder',
116+
),
117+
rootDir: resolve(__dirname),
118+
},
119+
exclude: [],
120+
include: [],
121+
files: ['./src/components/button', './src/components/anotherButton'],
110122
});
111123

112124
expect(mapComponentsToExpose).toStrictEqual({

packages/dts-plugin/src/core/configurations/remotePlugin.ts

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import typescript from 'typescript';
55

66
import { RemoteOptions } from '../interfaces/RemoteOptions';
77
import { validateOptions } from '../lib/utils';
8+
import { TsConfigJson } from '../interfaces/TsConfigJson';
89

910
const defaultOptions = {
1011
tsConfigPath: './tsconfig.json',
@@ -23,12 +24,44 @@ const defaultOptions = {
2324
extractThirdParty: false,
2425
} satisfies Partial<RemoteOptions>;
2526

26-
const readTsConfig = ({
27-
tsConfigPath,
28-
typesFolder,
29-
compiledTypesFolder,
30-
context,
31-
}: Required<RemoteOptions>): typescript.CompilerOptions => {
27+
function getEffectiveRootDir(
28+
parsedCommandLine: typescript.ParsedCommandLine,
29+
): string {
30+
const compilerOptions = parsedCommandLine.options;
31+
32+
if (compilerOptions.rootDir) {
33+
return compilerOptions.rootDir;
34+
}
35+
36+
// if no set rootDir , infer the commonRoot
37+
const files = parsedCommandLine.fileNames;
38+
if (files.length > 0) {
39+
const commonRoot = files
40+
.map((file) => dirname(file))
41+
.reduce((commonPath, fileDir) => {
42+
while (!fileDir.startsWith(commonPath)) {
43+
commonPath = dirname(commonPath);
44+
}
45+
return commonPath;
46+
}, files[0]);
47+
return commonRoot;
48+
}
49+
50+
throw new Error(
51+
'Can not get effective rootDir, please set compilerOptions.rootDir !',
52+
);
53+
}
54+
55+
const readTsConfig = (
56+
{
57+
tsConfigPath,
58+
typesFolder,
59+
compiledTypesFolder,
60+
context,
61+
additionalFilesToCompile,
62+
}: Required<RemoteOptions>,
63+
mapComponentsToExpose: Record<string, string>,
64+
): TsConfigJson => {
3265
const resolvedTsConfigPath = resolve(context, tsConfigPath);
3366

3467
const readResult = typescript.readConfigFile(
@@ -40,25 +73,53 @@ const readTsConfig = ({
4073
throw new Error(readResult.error.messageText.toString());
4174
}
4275

76+
const rawTsConfigJson: TsConfigJson = readResult.config;
77+
4378
const configContent = typescript.parseJsonConfigFileContent(
44-
readResult.config,
79+
rawTsConfigJson,
4580
typescript.sys,
4681
dirname(resolvedTsConfigPath),
4782
);
83+
84+
const rootDir = getEffectiveRootDir(configContent);
85+
4886
const outDir = resolve(
4987
context,
5088
configContent.options.outDir || 'dist',
5189
typesFolder,
5290
compiledTypesFolder,
5391
);
5492

55-
return {
56-
...configContent.options,
93+
const defaultCompilerOptions: typescript.CompilerOptions = {
94+
rootDir,
5795
emitDeclarationOnly: true,
5896
noEmit: false,
5997
declaration: true,
6098
outDir,
6199
};
100+
101+
rawTsConfigJson.compilerOptions = rawTsConfigJson.compilerOptions || {};
102+
103+
rawTsConfigJson.compilerOptions = {
104+
...rawTsConfigJson.compilerOptions,
105+
...defaultCompilerOptions,
106+
};
107+
108+
const filesToCompile = [
109+
...Object.values(mapComponentsToExpose),
110+
...additionalFilesToCompile,
111+
];
112+
113+
rawTsConfigJson.include = [];
114+
rawTsConfigJson.files = filesToCompile;
115+
rawTsConfigJson.exclude = [];
116+
'references' in rawTsConfigJson && delete rawTsConfigJson.references;
117+
118+
const extendsPath = rawTsConfigJson.extends;
119+
if (extendsPath && extendsPath.startsWith('.')) {
120+
rawTsConfigJson.extends = resolve(context, extendsPath);
121+
}
122+
return rawTsConfigJson;
62123
};
63124

64125
const TS_EXTENSIONS = ['ts', 'tsx', 'vue', 'svelte'];
@@ -115,7 +176,7 @@ export const retrieveRemoteConfig = (options: RemoteOptions) => {
115176
...options,
116177
};
117178
const mapComponentsToExpose = resolveExposes(remoteOptions);
118-
const tsConfig = readTsConfig(remoteOptions);
179+
const tsConfig = readTsConfig(remoteOptions, mapComponentsToExpose);
119180

120181
return {
121182
tsConfig,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import ts from 'typescript';
2+
3+
export interface TsConfigJson {
4+
extends?: string;
5+
compilerOptions?: ts.CompilerOptions;
6+
exclude?: string[];
7+
include?: string[];
8+
files?: string[];
9+
}

0 commit comments

Comments
 (0)