Skip to content

Commit

Permalink
Merge branch 'main' into fix/runtime-types
Browse files Browse the repository at this point in the history
  • Loading branch information
xuchaobei authored Jul 18, 2023
2 parents eb3da5f + 3f79dd7 commit 8c73e56
Show file tree
Hide file tree
Showing 21 changed files with 319 additions and 19 deletions.
9 changes: 9 additions & 0 deletions .changeset/sour-dogs-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@modern-js/builder-webpack-provider': minor
'@modern-js/builder-rspack-provider': minor
'@modern-js/builder-shared': minor
---

feat(builder): add `source.aliasStrategy` option

feat(builder): 新增 `source.aliasStrategy` 选项
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ export const builderPluginResolve = (): BuilderPlugin => ({

api.modifyRspackConfig(async (rspackConfig, { isServer }) => {
const isTsProject = Boolean(api.context.tsconfigPath);
const config = api.getNormalizedConfig();

if (isTsProject) {
if (isTsProject && config.source.aliasStrategy === 'prefer-tsconfig') {
setConfig(
rspackConfig,
'resolve.tsConfigPath',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ describe('plugins/resolve', () => {
expect(bundlerConfigs[0].resolve?.tsConfigPath).toBeDefined();
});

it('should not apply tsConfigPath when aliasStrategy is "prefer-alias"', async () => {
vi.spyOn(builderShared, 'isFileExists').mockImplementation(() =>
Promise.resolve(true),
);

const builder = await createBuilder({
plugins: [builderPluginResolve()],
builderConfig: {
source: {
aliasStrategy: 'prefer-alias',
},
},
});

const {
origin: { bundlerConfigs },
} = await builder.inspectConfig();

expect(bundlerConfigs[0].resolve?.tsConfigPath).toBeUndefined();
});

it('should allow to use source.alias to config alias', async () => {
const builder = await createBuilder({
plugins: [builderPluginResolve()],
Expand Down
1 change: 1 addition & 0 deletions packages/builder/builder-shared/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const getDefaultDevConfig = (): NormalizedSharedDevConfig => ({

export const getDefaultSourceConfig = (): NormalizedSharedSourceConfig => ({
alias: {},
aliasStrategy: 'prefer-tsconfig',
preEntry: [],
globalVars: {},
compileJsDataURI: true,
Expand Down
1 change: 1 addition & 0 deletions packages/builder/builder-shared/src/schema/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const MainFieldsSchema: ZodType<MainFields> = z.array(

export const sharedSourceConfigSchema = z.partialObj({
alias: z.chained(z.record(z.arrayOrNot(z.string()))),
aliasStrategy: z.literals(['prefer-tsconfig', 'prefer-alias']),
include: z.array(z.union([z.string(), z.instanceof(RegExp)])),
exclude: z.array(z.union([z.string(), z.instanceof(RegExp)])),
preEntry: z.arrayOrNot(z.string()),
Expand Down
8 changes: 8 additions & 0 deletions packages/builder/builder-shared/src/types/config/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ export type ChainedGlobalVars = ChainedConfig<
Pick<ModifyChainUtils, 'env' | 'target'>
>;

export type AliasStrategy = 'prefer-tsconfig' | 'prefer-alias';

export interface SharedSourceConfig {
/**
* Create aliases to import or require certain modules,
* same as the [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) config of webpack.
*/
alias?: ChainedConfig<Alias>;
/**
* Used to control the priority between the `paths` option in `tsconfig.json`
* and the `alias` option in the bundler.
*/
aliasStrategy?: AliasStrategy;
/**
* Specify directories or modules that need additional compilation.
* In order to maintain faster compilation speed, Builder will not compile files under node_modules through
Expand Down Expand Up @@ -70,6 +77,7 @@ export type SharedTransformImport = {

export interface NormalizedSharedSourceConfig extends SharedSourceConfig {
alias: ChainedConfig<Alias>;
aliasStrategy: AliasStrategy;
preEntry: string[];
globalVars: ChainedGlobalVars;
compileJsDataURI: boolean;
Expand Down
23 changes: 10 additions & 13 deletions packages/builder/builder-webpack-provider/src/plugins/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { BuilderPlugin, WebpackChain } from '../types';
import { applyBuilderResolvePlugin } from '@modern-js/builder-shared';
import type { ChainIdentifier } from '@modern-js/utils/chain-id';
import type { BuilderPlugin, WebpackChain } from '../types';

async function applyTsProject({
async function applyTsConfigPathsPlugin({
chain,
CHAIN_ID,
cwd,
Expand Down Expand Up @@ -39,7 +39,6 @@ export const builderPluginResolve = (): BuilderPlugin => ({

api.modifyWebpackChain(async (chain, { CHAIN_ID }) => {
const config = api.getNormalizedConfig();

const isTsProject = Boolean(api.context.tsconfigPath);

if (config.source.compileJsDataURI) {
Expand All @@ -48,17 +47,15 @@ export const builderPluginResolve = (): BuilderPlugin => ({
.resolve.set('fullySpecified', false);
}

if (!isTsProject) {
return;
if (isTsProject && config.source.aliasStrategy === 'prefer-tsconfig') {
await applyTsConfigPathsPlugin({
chain,
CHAIN_ID,
cwd: api.context.rootPath,
extensions: chain.resolve.extensions.values(),
sourceBuild: config.experiments.sourceBuild,
});
}

await applyTsProject({
chain,
CHAIN_ID,
cwd: api.context.rootPath,
extensions: chain.resolve.extensions.values(),
sourceBuild: config.experiments.sourceBuild,
});
});
},
});
6 changes: 6 additions & 0 deletions packages/document/builder-doc/docs/en/api/config-source.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import Alias from '@en/config/source/alias.md';

<Alias />

## source.aliasStrategy

import AliasStrategy from '@en/config/source/aliasStrategy.md';

<AliasStrategy />

## source.include

import Include from '@en/config/source/include.md';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
- **Type:** `Record<string, string | string[]> | Function`
- **Default:** `undefined`

Create aliases to import or require certain modules, same as the [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) config of webpack.
Create aliases to import or require certain modules, same as the [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) config of webpack and Rspack.

:::tip
For TypeScript projects, you only need to configure [compilerOptions.paths](https://www.typescriptlang.org/tsconfig#paths) in the `tsconfig.json` file. The Builder will automatically recognize it, so there is no need to configure the `source.alias` option separately. For more details, please refer to [Path Aliases](https://modernjs.dev/builder/en/guide/advanced/alias.html).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
- **Type:** `'prefer-tsconfig' | 'prefer-alias'`
- **Default:** `'prefer-tsconfig'`

`source.aliasStrategy` is used to control the priority between the `paths` option in `tsconfig.json` and the `alias` option in the bundler.

### prefer-tsconfig

By default, `source.aliasStrategy` is set to `'prefer-tsconfig'`. In this case, both the `paths` option in `tsconfig.json` and the `alias` option in the bundler will take effect, but the `paths` option in tsconfig has a higher priority.

For example, if the following configurations are set at the same time:

- tsconfig paths:

```json title="tsconfig.json"
{
"compilerOptions": {
"paths": {
"@common/*": ["./src/common-1/*"]
}
}
}
```

- `source.alias`:

```ts
export default {
source: {
alias: {
'@common': './src/common-2',
'@utils': './src/utils',
},
},
};
```

Since the tsconfig paths have a higher priority, the following will happen:

- `@common` will use the value defined in tsconfig paths, pointing to `./src/common-1`
- `@utils` will use the value defined in `source.alias`, pointing to `./src/utils`

### prefer-alias

If the value of `source.aliasStrategy` is set to `prefer-alias`, the `paths` option in `tsconfig.json` will only be used to provide TypeScript type definitions and will not affect the bundling result. In this case, the bundler will only read the `alias` option as the path alias.

```ts
export default {
source: {
aliasStrategy: 'prefer-alias',
},
};
```

For example, if the following configurations are set at the same time:

- tsconfig paths:

```json title="tsconfig.json"
{
"compilerOptions": {
"paths": {
"@common/*": ["./src/common-1/*"],
"@utils/*": ["./src/utils/*"]
}
}
}
```

- `source.alias`:

```ts
export default {
source: {
alias: {
'@common': './src/common-2',
},
},
};
```

Since the tsconfig paths are only used to provide types, only the `@common` alias will be effective, pointing to the `./src/common-2` directory.

In most cases, you don't need to use `prefer-alias`, but you can consider using it if you need to dynamically generate some alias configurations. For example, generating the `alias` option based on environment variables:

```ts
export default {
source: {
alias: {
'@common':
process.env.NODE_ENV === 'production'
? './src/common-prod'
: './src/common-dev',
},
},
};
```
2 changes: 2 additions & 0 deletions packages/document/builder-doc/docs/en/guide/advanced/alias.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ export default {
### Priority

The `paths` configuration in `tsconfig.json` takes precedence over the `source.alias` configuration. When a path matches the rules defined in both `paths` and `source.alias`, the value defined in `paths` will be used.

You can adjust the priority of these two options using [source.aliasStrategy](/api/config-source.html#sourcealiasstrategy).
6 changes: 6 additions & 0 deletions packages/document/builder-doc/docs/zh/api/config-source.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import Alias from '@zh/config/source/alias.md';

<Alias />

## source.aliasStrategy

import AliasStrategy from '@zh/config/source/aliasStrategy.md';

<AliasStrategy />

## source.include

import Include from '@zh/config/source/include.md';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
- **类型:** `Record<string, string | string[]> | Function`
- **默认值:** `undefined`

设置文件引用的别名,对应 webpack 的 [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) 配置。
设置文件引用的别名,对应 webpack 和 Rspack [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) 配置。

:::tip
对于 TypeScript 项目,你只需要在 `tsconfig.json` 中配置 [compilerOptions.paths](https://www.typescriptlang.org/tsconfig#paths) 即可,Builder 会自动识别它,不需要额外配置 `source.alias` 字段,详见 [「路径别名」](https://modernjs.dev/builder/guide/advanced/alias.html)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
- **类型:** `'prefer-tsconfig' | 'prefer-alias'`
- **默认值:** `'prefer-tsconfig'`

`source.aliasStrategy` 用于控制 `tsconfig.json` 中的 `paths` 选项与打包工具的 `alias` 选项的优先级。

### prefer-tsconfig

`source.aliasStrategy` 默认为 `'prefer-tsconfig'`,此时 `tsconfig.json` 中的 `paths` 选项和打包工具的 `alias` 选项都会生效,但 tsconfig paths 选项的优先级更高。

比如同时配置以下内容:

- tsconfig paths:

```json title="tsconfig.json"
{
"compilerOptions": {
"paths": {
"@common/*": ["./src/common-1/*"]
}
}
}
```

- `source.alias`:

```ts
export default {
source: {
alias: {
'@common': './src/common-2',
'@utils': './src/utils',
},
},
};
```

由于 tsconfig paths 的优先级更高,所以:

- `@common` 会使用 tsconfig paths 定义的值,指向 `./src/common-1`
- `@utils` 会使用 `source.alias` 定义的值,指向 `./src/utils`

### prefer-alias

`source.aliasStrategy` 的值为 `prefer-alias` 时,`tsconfig.json` 中的 `paths` 选项只用于提供 TypeScript 类型定义,而不会对打包结果产生任何影响。此时,构建工具只会读取 `alias` 选项作为路径别名。

```ts
export default {
source: {
aliasStrategy: 'prefer-alias',
},
};
```

比如同时配置以下内容:

- tsconfig paths:

```json title="tsconfig.json"
{
"compilerOptions": {
"paths": {
"@common/*": ["./src/common-1/*"],
"@utils/*": ["./src/utils/*"]
}
}
}
```

- `source.alias`:

```ts
export default {
source: {
alias: {
'@common': './src/common-2',
},
},
};
```

由于 tsconfig paths 只用于提供类型,所以最终只有 `@common` 别名生效,并指向 `./src/common-2` 目录。

大部分情况下你不需要使用 `prefer-alias`,但当你需要动态生成一些别名配置时,可以考虑使用它。比如,基于环境变量来生成 `alias` 选项:

```ts
export default {
source: {
alias: {
'@common':
process.env.NODE_ENV === 'production'
? './src/common-prod'
: './src/common-dev',
},
},
};
```
2 changes: 2 additions & 0 deletions packages/document/builder-doc/docs/zh/guide/advanced/alias.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ export default {
### 优先级

`tsconfig.json``paths` 配置的优先级高于 `source.alias`,当一个路径同时匹配到这两者定义的规则时,会优先使用 `tsconfig.json``paths` 定义的值。

你可以通过 [source.aliasStrategy](/api/config-source.html#sourcealiasstrategy) 来调整这两个选项的优先级。
Loading

0 comments on commit 8c73e56

Please sign in to comment.