Skip to content

Commit 33a032b

Browse files
authored
feat(scripts-babel): implement v9 babel preset to properly resolve griffel module mappings (#27313)
1 parent 34438ce commit 33a032b

File tree

6 files changed

+128
-15
lines changed

6 files changed

+128
-15
lines changed

.babelrc-v9.json

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,9 @@
11
{
22
"presets": [
33
[
4-
"@griffel",
4+
"@fluentui/scripts-babel/preset-v9",
55
{
6-
"babelOptions": {
7-
"plugins": [
8-
[
9-
"babel-plugin-module-resolver",
10-
{
11-
"root": ["../../../"],
12-
"alias": {
13-
"@fluentui/tokens": "packages/tokens/lib/index.js",
14-
"^@fluentui/(?!react-icons)(.+)": "packages/react-components/\\1/lib/index.js"
15-
}
16-
}
17-
]
18-
]
19-
}
6+
"tsBaseConfigPath": "./tsconfig.base.json"
207
}
218
]
229
]

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
/yarn.lock @microsoft/fluentui-react-build
5353
/*.config.js @microsoft/fluentui-react-build
5454
/typings @microsoft/fluentui-react-build
55+
/.babelrc-v9.json @microsoft/fluentui-react-build
5556

5657
#### NX related files
5758
/nx.json @microsoft/fluentui-react-build

scripts/babel/jest.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ module.exports = {
99
transform: {
1010
'^.+\\.tsx?$': 'ts-jest',
1111
},
12+
globals: {
13+
'ts-jest': {
14+
tsconfig: '<rootDir>/tsconfig.spec.json',
15+
isolatedModules: true,
16+
},
17+
},
1218
coverageDirectory: './coverage',
1319
testEnvironment: 'node',
1420
};

scripts/babel/preset-v9.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
const { workspaceRoot } = require('@nrwl/devkit');
5+
6+
const cwd = process.cwd();
7+
const rootOffset = path.relative(cwd, workspaceRoot);
8+
9+
/**
10+
*
11+
* @param {{tsBaseConfigPath:string}} options
12+
* @returns
13+
*/
14+
function createModuleResolverAliases(options) {
15+
const { tsBaseConfigPath } = options;
16+
const tsBaseConfigPathAbsolute = path.join(workspaceRoot, tsBaseConfigPath);
17+
const tsConfigBase = JSON.parse(fs.readFileSync(tsBaseConfigPathAbsolute, 'utf-8'));
18+
19+
/**
20+
* @type {Record<string,[string]>}
21+
*/
22+
const allPathAliases = tsConfigBase.compilerOptions.paths;
23+
return Object.entries(allPathAliases).reduce((acc, [packageName, aliasTuple]) => {
24+
const tsSourceRoot = aliasTuple[0];
25+
const jsSourceRoot = tsSourceRoot.replace('src', 'lib').replace('.ts', '.js');
26+
const aliasRegex = `^${packageName}$`;
27+
acc[aliasRegex] = `${rootOffset}/${jsSourceRoot}`;
28+
return acc;
29+
}, /** @type {Record<string,string>} */ ({}));
30+
}
31+
32+
/** @type {Array<import('./types').BabelPluginItem>} */
33+
const presets = [];
34+
35+
/** @type {Array<import('./types').BabelPluginItem>} */
36+
const plugins = [];
37+
38+
/**
39+
* @param {import('@babel/core').ConfigAPI} api
40+
* @param {import('./types').BabelPresetOptions} options
41+
*/
42+
const preset = (api, options) => {
43+
const moduleResolverAliasMappings = createModuleResolverAliases(options);
44+
/** @type {Array<import('./types').BabelPluginItem>} */
45+
const dynamicPresets = [
46+
[
47+
'@griffel',
48+
{
49+
babelOptions: {
50+
plugins: [
51+
[
52+
'babel-plugin-module-resolver',
53+
{
54+
alias: moduleResolverAliasMappings,
55+
},
56+
],
57+
],
58+
},
59+
},
60+
],
61+
];
62+
63+
presets.push(...dynamicPresets);
64+
65+
return { presets, plugins };
66+
};
67+
68+
module.exports = preset;

scripts/babel/preset-v9.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import preset from './preset-v9';
2+
3+
describe(`babel preset v9`, () => {
4+
const babelMockedApi = {
5+
assertVersion: jest.fn(),
6+
caller: jest.fn(),
7+
env: jest.fn(),
8+
cache: {},
9+
version: '0',
10+
} as unknown as import('@babel/core').ConfigAPI;
11+
it(`should generate module-resolve alias mappings for @griffel preset`, () => {
12+
const presetConfig = preset(babelMockedApi, { tsBaseConfigPath: './tsconfig.base.json' });
13+
14+
const griffelPreset = presetConfig.presets.find(presetItem => presetItem[0] === '@griffel')!;
15+
const griffelPresetConfig = griffelPreset[1];
16+
17+
expect(griffelPresetConfig).toEqual({
18+
babelOptions: {
19+
plugins: [
20+
[
21+
'babel-plugin-module-resolver',
22+
{
23+
alias: expect.any(Object),
24+
},
25+
],
26+
],
27+
},
28+
});
29+
30+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
31+
const alias = (griffelPresetConfig as any).babelOptions.plugins[0][1].alias;
32+
const aliasesEntries = Object.entries(alias);
33+
34+
/**
35+
* we pick 5th entry from the big list of path aliases entries. there is nothing special about it and we can pick any existing entry index.
36+
* I chose to not pick first nor last. In general this is an integration test that checks if we would introduce some violation within tsconfig.base.json path aliases config
37+
*/
38+
const aliasDeclaration = aliasesEntries[5];
39+
const [aliasKey, aliasPath] = aliasDeclaration;
40+
41+
expect(aliasKey).toEqual(expect.stringContaining('^@fluentui/'));
42+
expect(aliasPath).toEqual(expect.stringMatching(/[../]+[a-z-/]+\/lib\/index\.js/));
43+
});
44+
});

scripts/babel/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { PluginTarget } from '@babel/core';
2+
3+
export interface BabelPresetOptions {
4+
tsBaseConfigPath: string;
5+
}
6+
7+
export type BabelPluginItem = [PluginTarget, Record<string, unknown>];

0 commit comments

Comments
 (0)