Skip to content

Commit

Permalink
Merge pull request #251 from core-ds/feat/swc-loader
Browse files Browse the repository at this point in the history
feat(*): add useSwc option
  • Loading branch information
heymdall-legal authored Oct 16, 2024
2 parents 8b75f20 + 4a60f85 commit 9581e06
Show file tree
Hide file tree
Showing 19 changed files with 576 additions and 152 deletions.
18 changes: 18 additions & 0 deletions .changeset/three-camels-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'arui-scripts': minor
---

Добавляем возможность использовать swc для загрузки кода в webpack и jest.

- Добавлена настройка `codeLoader` для выбора используемого загрузчика кода.
Настройка заменяет собой уже существовавшую `useTscLoader` и добавляет возможность использовать в качестве
загрузчика swc.
Использование swc значительно ускоряет сборку (до 2 раз), без особых негативных последствий.

- Добавлена настройка `jestCodeTransformer` для выбора обработчика кода для jest.
Заменяет собой `jestUseTsJest` и добавляет возможность использовать `@swc/jest`. swc в jest немного меняет поведение при использовании
spyOn для esm модулей.

- Флаг `useTscLoader` помечен как deprecated и будет удален в следующем мажорном релизе. Используйте `codeLoader: 'tsc'`.
- Флаг `jestUseTsJest` помечен как deprecated и будет удален в следующем мажорном релизе. Используйте `jestCodeTransformer: 'tsc'`.
- Флаг `webpack4Compatibility` помечен как deprecated и будет удален в следующем мажорном релизе.
2 changes: 2 additions & 0 deletions packages/arui-scripts/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ module.exports = {
'import/no-named-as-default': 'warn',
// чтобы могли использовать for и генераторы
'no-restricted-syntax': 'off',
// проект - cli-тулза, и она должна писать в консоль
'no-console': 'off',
},
};
3 changes: 3 additions & 0 deletions packages/arui-scripts/docs/overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ export default overrides;
- `start.sh` - шаблон entrypoint докер контейнера. Базовый шаблон [тут](../src/templates/start.template.ts).
- `serverExternalsExemptions` - список модулей, которые не будут добавлены в список внешних зависимостей сервера. [Подробнее](caveats.md#node-externals).
- `html` - шаблон для htmlWebpackPlugin, будет использоваться только в режиме [`clientOnly`](./settings.md#clientonly).
- `swc-client` - конфигурация `swc` для клиентского кода. Ключи: `swc`, `swcClient`.
- `swc-server` - конфигурация `swc` для серверного кода. Ключи: `swc`, `swcServer`.
- `swc-jest` - конфигурация `swc` для тестов. Ключи: `swc`, `swcJest`.

Для некоторых конфигураций определены несколько ключей, они будут применяться в том порядке, в котором они приведены в этом файле.

Expand Down
27 changes: 27 additions & 0 deletions packages/arui-scripts/docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ const settings = {
- `/^thrift-services\/proptypes/`

#### useTscLoader
**Deprecated** Используйте настройку [codeLoader](#codeloader)

Использовать ts-loader вместо babel-loader для обработки ts файлов. **Не рекомендуется к использованию**.

babel-loader является предпочтительным инструментом сборки, его стоят заменять только если в вашем проекте используется неподдерживаемый им синтаксис:
Expand All @@ -208,15 +210,40 @@ babel-loader является предпочтительным инструме

Рекомендуется обновить код проекта до поддерживаемого синтаксиса и использовать babel-loader.

#### codeLoader
Позволяет выбрать какой инструмент использовать для обработки js и ts кода приложения. По умолчанию `babel`.

Возможные значения:
- `babel` - для всего кода будет использоваться `babel-loader`;
- `tsc` - для ts кода будет использоваться `ts-loader`, для всего остального - `babel-loader`;
- `swc` - для всего кода будет использоваться `swc-loader`.

`swc` является предпочтительным режимом, дефолты не меняются для сохранения обратной совместимости.
Использование swc позволяет значительно ускорить сборку (до 2 раз на больших проектах), но не будет создавать полностью идентичный с babel код.
Итоговый бандл может получиться немного больше, чем при использовании babel, но разница полностью компенсируется при использовании сжатия.

#### webpack4Compatibility
**Deprecated** Эта настройка будет удалена в будущих версиях скриптов

Включить ли режим совместимости с webpack 4. По умолчанию `false`. Подробнее можно почитать в этом [issue](https://github.com/webpack/webpack/issues/14580).

#### installServerSourceMaps
Добавлять ли в серверную сборку пакет source-map-support. По умолчанию `false`.

#### jestUseTsJest
**Deprecated** Используйте настройку [jestCodeTransformer](#jestcodetransformer)

Позволяет использовать `ts-jest` вместо `babel-jest` для обработки `ts` файлов при запуске тестов. По умолчанию `false`.

#### jestCodeTransformer
Позволяет выбрать какой инструмент использовать для обработки js и ts кода приложения при запуске тестов. По умолчанию `babel`.

Возможные значения:
- `babel` - для всего кода будет использоваться `babel-jest`;
- `tsc` - для ts кода будет использоваться `ts-jest`, для всего остального - `babel-jest`;
- `swc` - для всего кода будет использоваться `@swc/jest`.
Swc более строго следует спецификациям и [не дает возможности](https://github.com/swc-project/swc/issues/5059) делать `spyOn` для экспортов из esm модулей.

#### collectCoverage
Добавлять ли инструменты для сборки coverage при сборке. По умолчанию определяется по env переменным - будет выставлено в `true` если `NODE_ENV = 'cypress'` или `USE_ISTANBUL = 'enabled'`.
Сбор coverage не будет работать при использовании `useTscLoader=true`.
Expand Down
4 changes: 4 additions & 0 deletions packages/arui-scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"@babel/runtime": "^7.23.8",
"@csstools/postcss-global-data": "^2.0.1",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.11",
"@swc/core": "^1.7.35",
"@swc/jest": "^0.2.36",
"assets-webpack-plugin": "7.1.1",
"autoprefixer": "^10.3.16",
"babel-core": "^7.0.0-bridge.0",
Expand Down Expand Up @@ -96,6 +98,8 @@
"shelljs": "0.8.5",
"strip-ansi": "6.0.1",
"style-loader": "3.3.3",
"swc-loader": "^0.2.6",
"swc-plugin-coverage-instrument": "^0.0.24",
"tar": "6.2.1",
"terser-webpack-plugin": "5.3.9",
"ts-jest": "28.0.8",
Expand Down
2 changes: 1 addition & 1 deletion packages/arui-scripts/src/commands/start-prod/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { configs } from '../../configs/app-configs';
import { getTscWatchCommand } from '../util/tsc';
import { runCompilers } from '../util/run-compilers';
import { getTscWatchCommand } from '../util/tsc';

process.env.BROWSERSLIST_CONFIG =
process.env.BROWSERSLIST_CONFIG || require.resolve('../../../.browserslistrc');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { AppConfigs, AppContext } from './types';
/**
* Обновление ключей конфига, зависящих от других. Это нужно делать в самый последний момент
*/
export function calculateDependentConfig(config: AppConfigs) {
export function calculateDependentConfig(config: AppConfigs): AppConfigs {
return {
...config,
codeLoader: config.useTscLoader ? 'tsc' : config.codeLoader,
jestCodeTransformer: config.jestUseTsJest ? 'tsc' : config.jestCodeTransformer,
clientPolyfillsEntry: getPolyfills(config),
};
}
Expand Down
2 changes: 2 additions & 0 deletions packages/arui-scripts/src/configs/app-configs/get-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ export function getDefaultAppConfig(): AppConfigs {
// build tuning
keepPropTypes: false,
useTscLoader: false,
codeLoader: 'babel',
webpack4Compatibility: false,
installServerSourceMaps: false,
disableDevWebpackTypecheck: true,
jestUseTsJest: false,
jestCodeTransformer: 'babel',
collectCoverage: process.env.NODE_ENV === 'cypress' || process.env.USE_ISTANBUL === 'enabled',

// image processing
Expand Down
8 changes: 8 additions & 0 deletions packages/arui-scripts/src/configs/app-configs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,18 @@ export type AppConfigs = {
* @deprecated использование ts-loader крайне не рекомендуется - он медленнее и не имеет преимуществ перед babel
*/
useTscLoader: boolean;
codeLoader: 'babel' | 'tsc' | 'swc';
/**
* @deprecated эта настройка будет удалена в будущих версиях скриптов
*/
webpack4Compatibility: boolean;
installServerSourceMaps: boolean;
disableDevWebpackTypecheck: boolean;
/**
* @deprecated используйте настройку jestCodeTransformer
*/
jestUseTsJest: boolean;
jestCodeTransformer: 'babel' | 'tsc' | 'swc';
collectCoverage: boolean;

// image processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import { AppContextWithConfigs } from './types';

export function warnAboutDeprecations(config: AppContextWithConfigs) {
if (config.useTscLoader) {
// eslint-disable-next-line no-console
console.warn(
'Использование опции `useTscLoader` не рекомендуется и будет удалено в будущих версиях. ',
'Обратитесь к документации https://github.com/core-ds/arui-scripts/blob/master/packages/arui-scripts/docs/settings.md#usetscloader',
'для получения дополнительной информации.'
);
}

if (config.webpack4Compatibility) {
console.warn(
'Опция `webpack4Compatibility` будет удалена в будущих версиях arui-scripts.',
'Обратитесь к issue в webpack https://github.com/webpack/webpack/issues/14580 для получения дополнительной информации',
);
}
}
51 changes: 36 additions & 15 deletions packages/arui-scripts/src/configs/jest/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,10 @@
const fs = require('fs');
const { pathsToModuleNameMapper } = require('ts-jest');
const { parseConfigFileTextToJson } = require('typescript');
const { swcJestConfig } = require('../swc');

const configs = require('../app-configs').default;

let tsConfigPaths = {};

if (configs.tsconfig) {
const tsConfigText = fs.readFileSync(configs.tsconfig, 'utf8');
const tsConfig = parseConfigFileTextToJson(configs.tsconfig, tsConfigText);

tsConfigPaths = tsConfig.config.compilerOptions?.paths || {};
}

module.exports = {
testRegex: 'src/.*(((/__test__/|/__tests__/).*)|(test|spec|tests)).(jsx?|tsx?)$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
Expand All @@ -26,17 +18,15 @@ module.exports = {
url: 'http://localhost',
},
transform: {
'^.+\\.jsx?$': require.resolve('./babel-transform'),
'^.+\\.mjs$': require.resolve('./babel-transform'),
'^.+\\.tsx?$': configs.jestUseTsJest
? require.resolve('ts-jest')
: require.resolve('./babel-transform'),
'^.+\\.jsx?$': getJsTransformer(),
'^.+\\.mjs$': getJsTransformer(),
'^.+\\.tsx?$': getTsTransformer(),
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': require.resolve('./file-transform'),
},
moduleNameMapper: {
// replace all css files with simple empty exports
'\\.css$': require.resolve('./css-mock'),
...pathsToModuleNameMapper(tsConfigPaths, { prefix: '<rootDir>/' }),
...pathsToModuleNameMapper(getPathMapping(), { prefix: '<rootDir>/' }),
},
snapshotSerializers: [require.resolve('jest-snapshot-serializer-class-name-to-string')],
globals: {
Expand All @@ -45,3 +35,34 @@ module.exports = {
},
},
};

function getPathMapping() {
if (!configs.tsconfig) {
return {};
}

const tsConfigText = fs.readFileSync(configs.tsconfig, 'utf8');
const tsConfig = parseConfigFileTextToJson(configs.tsconfig, tsConfigText);

return tsConfig.config.compilerOptions?.paths || {};
}

function getTsTransformer() {
if (configs.jestCodeTransformer === 'tsc') {
return require.resolve('ts-jest');
}

if (configs.jestCodeTransformer === 'swc') {
return [require.resolve('@swc/jest'), swcJestConfig];
}

return require.resolve('./babel-transform')
}

function getJsTransformer() {
if (configs.jestCodeTransformer === 'swc') {
return [require.resolve('@swc/jest'), swcJestConfig];
}

return require.resolve('./babel-transform');
}
35 changes: 35 additions & 0 deletions packages/arui-scripts/src/configs/swc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Options } from '@swc/core';

import applyOverrides from './util/apply-overrides';
import { configs } from './app-configs';

const swcConfig: Options = {
env: { coreJs: '3', mode: 'entry' },
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
decorators: true,
},
loose: true,
transform: {
legacyDecorator: true,
react: {
runtime: 'automatic',
},
},
experimental: configs.collectCoverage
? {
plugins: [
['swc-plugin-coverage-instrument', {}],
],
}
: {},
},
};

export const swcClientConfig = applyOverrides(['swc', 'swcClient'], swcConfig);

export const swcServerConfig = applyOverrides(['swc', 'swcServer'], swcConfig);

export const swcJestConfig = applyOverrides(['swc', 'swcJest'], swcConfig);
6 changes: 6 additions & 0 deletions packages/arui-scripts/src/configs/util/apply-overrides.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// TODO: remove eslint-disable-next-line
import type { Configuration as WebpackConfiguration, WebpackOptionsNormalized } from 'webpack';
import type { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
import type { Options as SwcOptions } from '@swc/core'

import appConfigs from '../app-configs';
import { AppContextWithConfigs } from '../app-configs/types';
Expand All @@ -27,6 +28,11 @@ type Overrides = {
babelServer: any;
babelDependencies: any;

swc: SwcOptions;
swcServer: SwcOptions;
swcClient: SwcOptions;
swcJest: SwcOptions;

postcss: any[]; // TODO: где взять typedef-ы для postcss
browsers: string[];
supportingBrowsers: string[];
Expand Down
Loading

0 comments on commit 9581e06

Please sign in to comment.