feat: add ts and babel loaders
This commit is contained in:
parent
cda2c48613
commit
f704c77546
2
.eslintignore
Normal file
2
.eslintignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": [
|
"extends": "ksv741",
|
||||||
"ksv741"
|
"rules": {
|
||||||
]
|
"@typescript-eslint/strict-boolean-expressions": "off"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
85
README.md
85
README.md
@ -13,10 +13,12 @@
|
|||||||
- [`Режим запуска`](#режим-запуска)
|
- [`Режим запуска`](#режим-запуска)
|
||||||
- [`Конфигурация путей`](#конфигурация-путей)
|
- [`Конфигурация путей`](#конфигурация-путей)
|
||||||
- [`Порт`](#порт)
|
- [`Порт`](#порт)
|
||||||
- [`Загрузчик`](#загрузчик)
|
- [`Загрузчики`](#загрузчики)
|
||||||
- [`Анализ`](#анализ)
|
- [`Анализ`](#анализ)
|
||||||
- [`Плагины`](#плагины)
|
- [`Плагины`](#плагины)
|
||||||
- [`Лоадеры`](#лоадеры)
|
- [`Лоадеры`](#лоадеры)
|
||||||
|
- [`Resolvers`](#resolvers)
|
||||||
|
- [`Кэширование`](#кэширование)
|
||||||
- [`Расширенная конфигурация`](#расширенная-конфигурация)
|
- [`Расширенная конфигурация`](#расширенная-конфигурация)
|
||||||
|
|
||||||
***
|
***
|
||||||
@ -127,7 +129,8 @@ root.render(
|
|||||||
};
|
};
|
||||||
port?: number;
|
port?: number;
|
||||||
devtool?: string | false;
|
devtool?: string | false;
|
||||||
mainLoader?: 'esbuild' | 'swc';
|
mainLoader?: 'esbuild' | 'swc' | 'babel' | 'ts-loader';
|
||||||
|
svgLoader?: 'inline' | 'svgr';
|
||||||
analyze?: boolean;
|
analyze?: boolean;
|
||||||
plugins?: {
|
plugins?: {
|
||||||
htmlWebpackPlugin?: object | 'off';
|
htmlWebpackPlugin?: object | 'off';
|
||||||
@ -142,16 +145,19 @@ root.render(
|
|||||||
analyzerPlugin?: object | 'off';
|
analyzerPlugin?: object | 'off';
|
||||||
}
|
}
|
||||||
loaders?: {
|
loaders?: {
|
||||||
esbuildLoader?: object | 'off';
|
babelLoader?: object | 'off';
|
||||||
swcLoader?: object | 'off';
|
|
||||||
svgrLoader?: object | 'off';
|
|
||||||
styleLoader?: object | 'off';
|
|
||||||
cssLoader?: object | 'off';
|
cssLoader?: object | 'off';
|
||||||
postCssLoader?: object | 'off';
|
esbuildLoader?: object | 'off';
|
||||||
miniCssLoader?: object | 'off';
|
|
||||||
sassLoader?: object | 'off';
|
|
||||||
imageLoader?: object | 'off';
|
|
||||||
fontLoader?: object | 'off';
|
fontLoader?: object | 'off';
|
||||||
|
imageLoader?: object | 'off';
|
||||||
|
inlineSvgLoader?: object | 'off';
|
||||||
|
miniCssLoader?: object | 'off';
|
||||||
|
postCssLoader?: object | 'off';
|
||||||
|
sassLoader?: object | 'off';
|
||||||
|
styleLoader?: object | 'off';
|
||||||
|
svgrLoader?: object | 'off';
|
||||||
|
swcLoader?: object | 'off';
|
||||||
|
tsLoader?: object | 'off';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -186,9 +192,11 @@ root.render(
|
|||||||
- `port` - порт, в котором будет запускаться dev server, для `mode = 'production'` настройка игнорируется
|
- `port` - порт, в котором будет запускаться dev server, для `mode = 'production'` настройка игнорируется
|
||||||
По умолчанию: `3000`
|
По умолчанию: `3000`
|
||||||
|
|
||||||
#### Загрузчик
|
#### Загрузчики
|
||||||
- `mainLoader` - главный загрузчик javascript/typescript файлов, доступны `esbuild` и `swc`
|
- `mainLoader` - главный загрузчик javascript/typescript файлов, доступны `esbuild`, `swc`, `babel`, `ts-loader`
|
||||||
По умолчанию: `esbuild`
|
По умолчанию: `esbuild`
|
||||||
|
- `svgLoader` - загрузчик `svg` файлов, доступны `inline` - загрузка файла строкой, `svgr` - загрузка файла как React компонент.
|
||||||
|
По умолчанию: `svgr`
|
||||||
|
|
||||||
#### Анализ
|
#### Анализ
|
||||||
- `analyze` - запуск сервера на порту `8888`, для анализа сборки. Рекомендуется запускать совместно с `mode = 'production'`. Но допустим запуск и в режиме `development`
|
- `analyze` - запуск сервера на порту `8888`, для анализа сборки. Рекомендуется запускать совместно с `mode = 'production'`. Но допустим запуск и в режиме `development`
|
||||||
@ -285,9 +293,12 @@ root.render(
|
|||||||
- `loaders` - объект с настройками лоадеров
|
- `loaders` - объект с настройками лоадеров
|
||||||
|
|
||||||
Список используемых лоадеров:
|
Список используемых лоадеров:
|
||||||
- [esbuild-loader](https://github.com/privatenumber/esbuild-loader) - лоадер для обработки `.tsx`, `.jsx`, `.ts`, `.js` файлов, при указании настройки [`mainLoader: 'esbuild'`](#загрузчик)
|
- [esbuild-loader](https://github.com/privatenumber/esbuild-loader) - лоадер для обработки `.tsx`, `.jsx`, `.ts`, `.js` файлов, при указании настройки [`mainLoader: 'esbuild'`](#загрузчики)
|
||||||
- [swc-loader](https://github.com/swc-project/pkgs/tree/main/packages/swc-loader) - лоадер для обработки `.tsx`, `.jsx`, `.ts`, `.js` файлов, при указании настройки [`mainLoader: 'swc'`](#загрузчик)
|
- [swc-loader](https://github.com/swc-project/pkgs/tree/main/packages/swc-loader) - лоадер для обработки `.tsx`, `.jsx`, `.ts`, `.js` файлов, при указании настройки [`mainLoader: 'swc'`](#загрузчики)
|
||||||
|
- [babel-loader](https://github.com/babel/babel-loader) - лоадер для обработки `.tsx`, `.jsx`, `.ts`, `.js` файлов, при указании настройки [`mainLoader: 'babel'`](#загрузчики)
|
||||||
|
- [ts-loader](https://github.com/TypeStrong/ts-loader) - лоадер для обработки `.tsx`, `.jsx`, `.ts`, `.js` файлов, при указании настройки [`mainLoader: 'ts-loader'`](#загрузчики)
|
||||||
- [@svgr/webpack](https://github.com/gregberge/svgr/tree/main/packages/webpack)- лоадер для обработки `.svg` файлов, для работы с файлами, как с React компонентами
|
- [@svgr/webpack](https://github.com/gregberge/svgr/tree/main/packages/webpack)- лоадер для обработки `.svg` файлов, для работы с файлами, как с React компонентами
|
||||||
|
- [svg-inline-loader](https://webpack.js.org/guides/asset-modules/)- лоадер для загрузки `.svg` файлов, для строки
|
||||||
- [style-loader](https://webpack.js.org/loaders/style-loader/) - лоадер для вставки стилей inline элементами в html, доступен в режиме `development`
|
- [style-loader](https://webpack.js.org/loaders/style-loader/) - лоадер для вставки стилей inline элементами в html, доступен в режиме `development`
|
||||||
- [mini-css-loader](https://webpack.js.org/plugins/mini-css-extract-plugin/#loader-options), доступен в режиме `production` - лоадер для формирование стилей `.css` файлами
|
- [mini-css-loader](https://webpack.js.org/plugins/mini-css-extract-plugin/#loader-options), доступен в режиме `production` - лоадер для формирование стилей `.css` файлами
|
||||||
- [css-loader](https://webpack.js.org/loaders/css-loader/) - лоадер для обработки `.css` файлов
|
- [css-loader](https://webpack.js.org/loaders/css-loader/) - лоадер для обработки `.css` файлов
|
||||||
@ -304,7 +315,7 @@ root.render(
|
|||||||
loader: 'tsx',
|
loader: 'tsx',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- `swcLoader` - настройкаи для [swc-loader](https://swc.rs/docs/configuration/swcrc)
|
- `swcLoader` - настройки для [swc-loader](https://swc.rs/docs/configuration/swcrc)
|
||||||
По умолчанию:
|
По умолчанию:
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
@ -337,6 +348,18 @@ root.render(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
- `babelLoader` - настройки для [babel-loader](https://github.com/babel/babel-loader?tab=readme-ov-file#options)
|
||||||
|
По умолчанию:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env', { targets: 'defaults' }],
|
||||||
|
['@babel/preset-react', { runtime: 'automatic' }],
|
||||||
|
['@babel/preset-typescript'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- `tsLoader` - настройки для [ts-loader](https://github.com/TypeStrong/ts-loader?tab=readme-ov-file#loader-options)
|
||||||
- `svgrLoader` - настройка для [@svgr/webpack](https://react-svgr.com/docs/webpack/#options)
|
- `svgrLoader` - настройка для [@svgr/webpack](https://react-svgr.com/docs/webpack/#options)
|
||||||
По умолчанию:
|
По умолчанию:
|
||||||
```js
|
```js
|
||||||
@ -344,6 +367,7 @@ root.render(
|
|||||||
icon: true,
|
icon: true,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
- `inlineSvgLoader` - настройка для опции `generator` [Assets Modules](https://webpack.js.org/guides/asset-modules/)
|
||||||
- `styleLoader` - настройка для [style-loader](https://webpack.js.org/loaders/style-loader/#options)
|
- `styleLoader` - настройка для [style-loader](https://webpack.js.org/loaders/style-loader/#options)
|
||||||
- `miniCssLoader` - настойка для [MiniCssExtractPlugin.loader](https://webpack.js.org/plugins/mini-css-extract-plugin/#loader-options)
|
- `miniCssLoader` - настойка для [MiniCssExtractPlugin.loader](https://webpack.js.org/plugins/mini-css-extract-plugin/#loader-options)
|
||||||
- `cssLoader` - настройка для [css-loader](https://webpack.js.org/loaders/css-loader/#options)
|
- `cssLoader` - настройка для [css-loader](https://webpack.js.org/loaders/css-loader/#options)
|
||||||
@ -392,6 +416,37 @@ root.render(
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Resolvers
|
||||||
|
- `resolver` - объект с настройками resolvers
|
||||||
|
|
||||||
|
Список используемых плагинов:
|
||||||
|
- [TsconfigPathsPlugin](https://github.com/dividab/tsconfig-paths-webpack-plugin)
|
||||||
|
|
||||||
|
Для настройки плагина необходимо передать объект с конфигурацией или строку `off` для того чтобы отключить плагин:
|
||||||
|
|
||||||
|
- `tsConfigPathsPlugin` - настройки плагина [TsconfigPathsPlugin](https://github.com/dividab/tsconfig-paths-webpack-plugin?tab=readme-ov-file#options)
|
||||||
|
По умолчанию:
|
||||||
|
```javascript
|
||||||
|
resolvers: {
|
||||||
|
plugins: {
|
||||||
|
tsConfigPathsPlugin: {
|
||||||
|
baseUrl: process.cwd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Кэширование
|
||||||
|
- `cache` - объект с настройками кэширования
|
||||||
|
По умолчанию:
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
type: 'filesystem',
|
||||||
|
buildDependencies: {
|
||||||
|
config: [__filename]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
### Расширенная конфигурация
|
### Расширенная конфигурация
|
||||||
Если текущей кастомизации не достаточно или Вы хотите добавить/изменить какой-то плагин или загрузчик,
|
Если текущей кастомизации не достаточно или Вы хотите добавить/изменить какой-то плагин или загрузчик,
|
||||||
то это можно легко сделать, т.к. функция `createConfig` возвращает обычный объект с конфигурацией webpack, который можно изменить.
|
то это можно легко сделать, т.к. функция `createConfig` возвращает обычный объект с конфигурацией webpack, который можно изменить.
|
||||||
|
|||||||
10
global.d.ts
vendored
10
global.d.ts
vendored
@ -22,6 +22,16 @@ declare module '*.scss' {
|
|||||||
export = content;
|
export = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.css' {
|
||||||
|
const content: Record<string, string>;
|
||||||
|
export = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*.sass' {
|
||||||
|
const content: Record<string, string>;
|
||||||
|
export = content;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '*.svg' {
|
declare module '*.svg' {
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
|
|
||||||
|
|||||||
27
package.json
27
package.json
@ -6,7 +6,8 @@
|
|||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"source": "./src/webpack/index.ts",
|
"source": "./src/webpack/index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rm -rf ./dist && tsc",
|
"prepare": "rm -rf dist && tsc && tsc-alias",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
"lint": "eslint --ignore-pattern node_modules --color src"
|
"lint": "eslint --ignore-pattern node_modules --color src"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -32,6 +33,10 @@
|
|||||||
"author": "Sergey <ksv741@gmail.com> Krylov",
|
"author": "Sergey <ksv741@gmail.com> Krylov",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/core": "7.24.0",
|
||||||
|
"@babel/preset-env": "7.24.0",
|
||||||
|
"@babel/preset-react": "7.23.3",
|
||||||
|
"@babel/preset-typescript": "7.23.3",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "0.5.11",
|
"@pmmmwh/react-refresh-webpack-plugin": "0.5.11",
|
||||||
"@svgr/webpack": "8.1.0",
|
"@svgr/webpack": "8.1.0",
|
||||||
"@swc/core": "1.4.0",
|
"@swc/core": "1.4.0",
|
||||||
@ -42,6 +47,7 @@
|
|||||||
"@types/sass-loader": "8.0.8",
|
"@types/sass-loader": "8.0.8",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-dev-server": "4.7.2",
|
"@types/webpack-dev-server": "4.7.2",
|
||||||
|
"babel-loader": "9.1.3",
|
||||||
"copy-webpack-plugin": "12.0.2",
|
"copy-webpack-plugin": "12.0.2",
|
||||||
"cross-spawn": "7.0.3",
|
"cross-spawn": "7.0.3",
|
||||||
"css-loader": "6.10.0",
|
"css-loader": "6.10.0",
|
||||||
@ -60,7 +66,10 @@
|
|||||||
"style-loader": "3.3.4",
|
"style-loader": "3.3.4",
|
||||||
"swc-loader": "0.2.6",
|
"swc-loader": "0.2.6",
|
||||||
"terser-webpack-plugin": "5.3.10",
|
"terser-webpack-plugin": "5.3.10",
|
||||||
|
"ts-loader": "9.5.1",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
|
"tsc-alias": "1.8.8",
|
||||||
|
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||||
"typescript": "5.3.3",
|
"typescript": "5.3.3",
|
||||||
"webpack": "5.90.1",
|
"webpack": "5.90.1",
|
||||||
"webpack-bundle-analyzer": "4.10.1",
|
"webpack-bundle-analyzer": "4.10.1",
|
||||||
@ -68,7 +77,19 @@
|
|||||||
"webpack-dev-server": "5.0.0"
|
"webpack-dev-server": "5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "8.56.0",
|
"eslint": "8.57.0",
|
||||||
"eslint-config-ksv741": "git+ssh://git@github.com:ksv741/eslint-config-ksv741.git"
|
"eslint-config-ksv741": "0.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": ">8.0.0",
|
||||||
|
"typescript": "^3.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"eslint": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/cache/index.ts
vendored
Normal file
25
src/cache/index.ts
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
import type webpack from 'webpack';
|
||||||
|
|
||||||
|
const getCache = (options: WebpackOptions): webpack.Configuration['cache'] => {
|
||||||
|
const { cache = {} } = options;
|
||||||
|
|
||||||
|
if (cache === 'off') {
|
||||||
|
// eslint-disable-next-line no-undefined
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'filesystem',
|
||||||
|
...cache,
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
|
buildDependencies: {
|
||||||
|
config: [__filename],
|
||||||
|
// @ts-ignore
|
||||||
|
...cache.buildDependencies,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getCache;
|
||||||
@ -1,24 +1,42 @@
|
|||||||
|
import getCache from 'cache';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import process from 'process';
|
import process from 'process';
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import { createDevServer } from '../dev-server';
|
import createDevServer from 'dev-server';
|
||||||
import { createLoaders } from '../loaders';
|
import createLoaders from 'loaders';
|
||||||
import { getOptimization } from '../optimization';
|
import getOptimization from 'optimization';
|
||||||
import { createOutput } from '../output';
|
import createOutput from 'output';
|
||||||
import { createPlugins } from '../plugins';
|
import createPlugins from 'plugins';
|
||||||
import { createResolvers } from '../resolvers';
|
import createResolvers from 'resolvers';
|
||||||
import type { WebpackMode, WebpackOptions, WebpackPaths } from '../types';
|
import type { WebpackMode, WebpackOptions, WebpackPaths } from 'types';
|
||||||
|
|
||||||
const getDefaultEntryPath = (rootDir: string) => {
|
const getDefaultEntryPath = (rootDir: string, some?: string[] | string): string[] | string => {
|
||||||
|
if (Array.isArray(some)) {
|
||||||
|
// @ts-ignore
|
||||||
|
return some.map((entry) => getDefaultEntryPath(rootDir, entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (some && path.isAbsolute(some)) {
|
||||||
|
return some;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definedFile = some && path.resolve(rootDir, some);
|
||||||
const indexTsx = path.resolve(rootDir, 'index.tsx');
|
const indexTsx = path.resolve(rootDir, 'index.tsx');
|
||||||
|
const indexTs = path.resolve(rootDir, 'index.ts');
|
||||||
const indexJsx = path.resolve(rootDir, 'index.jsx');
|
const indexJsx = path.resolve(rootDir, 'index.jsx');
|
||||||
const indexJs = path.resolve(rootDir, 'index.js');
|
const indexJs = path.resolve(rootDir, 'index.js');
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
case definedFile && fs.existsSync(definedFile):
|
||||||
|
return definedFile;
|
||||||
|
|
||||||
case fs.existsSync(indexTsx):
|
case fs.existsSync(indexTsx):
|
||||||
return indexTsx;
|
return indexTsx;
|
||||||
|
|
||||||
|
case fs.existsSync(indexTs):
|
||||||
|
return indexTs;
|
||||||
|
|
||||||
case fs.existsSync(indexJsx):
|
case fs.existsSync(indexJsx):
|
||||||
return indexJsx;
|
return indexJsx;
|
||||||
|
|
||||||
@ -26,18 +44,53 @@ const getDefaultEntryPath = (rootDir: string) => {
|
|||||||
return indexJs;
|
return indexJs;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Has no index.tsx/index.jsx/index.js file in ${rootDir} directory`);
|
throw new Error(`Has no ${definedFile ?? 'index.tsx/index.ts/index.jsx/index.js'} file in ${rootDir} directory`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getDefaultPath = ({ root, defaultDirectory, currentPath }: Record<string, string | undefined>) => {
|
||||||
|
if (!currentPath) {
|
||||||
|
// @ts-ignore
|
||||||
|
return path.resolve(root, defaultDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.isAbsolute(currentPath)) {
|
||||||
|
return currentPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return path.resolve(root, currentPath);
|
||||||
|
};
|
||||||
|
|
||||||
const getDefaultPaths = (initialPaths?: WebpackPaths): WebpackPaths => {
|
const getDefaultPaths = (initialPaths?: WebpackPaths): WebpackPaths => {
|
||||||
const root = initialPaths?.root ?? path.resolve(process.cwd());
|
const root = initialPaths?.root ?? path.resolve(process.cwd());
|
||||||
const publicPath = initialPaths?.public ?? path.resolve(root, 'public');
|
|
||||||
const src = initialPaths?.src ?? path.resolve(root, 'src');
|
const publicPath = getDefaultPath({
|
||||||
const assets = initialPaths?.assets ?? path.resolve(publicPath, 'assets');
|
root,
|
||||||
const build = initialPaths?.build ?? path.resolve(root, 'build');
|
defaultDirectory: 'public',
|
||||||
const entry = getDefaultEntryPath(src);
|
currentPath: initialPaths?.public,
|
||||||
const html = initialPaths?.html ?? path.resolve(publicPath, 'index.html');
|
});
|
||||||
|
const src = getDefaultPath({
|
||||||
|
root,
|
||||||
|
defaultDirectory: 'src',
|
||||||
|
currentPath: initialPaths?.src,
|
||||||
|
});
|
||||||
|
const assets = getDefaultPath({
|
||||||
|
root: publicPath,
|
||||||
|
defaultDirectory: 'assets',
|
||||||
|
currentPath: initialPaths?.assets,
|
||||||
|
});
|
||||||
|
const build = getDefaultPath({
|
||||||
|
root,
|
||||||
|
defaultDirectory: 'build',
|
||||||
|
currentPath: initialPaths?.build,
|
||||||
|
});
|
||||||
|
const html = getDefaultPath({
|
||||||
|
root: publicPath,
|
||||||
|
defaultDirectory: 'index.html',
|
||||||
|
currentPath: initialPaths?.html,
|
||||||
|
});
|
||||||
|
const entry = getDefaultEntryPath(src, initialPaths?.entry);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
root,
|
root,
|
||||||
@ -60,10 +113,12 @@ const createConfig = (params?: WebpackOptions): webpack.Configuration => {
|
|||||||
const {
|
const {
|
||||||
mode = getDefaultMode(),
|
mode = getDefaultMode(),
|
||||||
analyze = false,
|
analyze = false,
|
||||||
mainLoader = 'esbuild',
|
mainLoader,
|
||||||
|
svgLoader,
|
||||||
port = 3000,
|
port = 3000,
|
||||||
devtool = 'inline-source-map',
|
devtool = 'inline-source-map',
|
||||||
plugins,
|
plugins,
|
||||||
|
loaders,
|
||||||
} = params ?? {};
|
} = params ?? {};
|
||||||
const {
|
const {
|
||||||
assets,
|
assets,
|
||||||
@ -75,14 +130,11 @@ const createConfig = (params?: WebpackOptions): webpack.Configuration => {
|
|||||||
src,
|
src,
|
||||||
} = getDefaultPaths(params?.paths);
|
} = getDefaultPaths(params?.paths);
|
||||||
|
|
||||||
if (!fs.existsSync(html)) {
|
|
||||||
throw new Error(`index.html file not found. Define path to index.html file or create one in "${publicPath}" directory`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const options: WebpackOptions = {
|
const options: WebpackOptions = {
|
||||||
mode,
|
mode,
|
||||||
analyze,
|
analyze,
|
||||||
mainLoader,
|
mainLoader,
|
||||||
|
svgLoader,
|
||||||
port,
|
port,
|
||||||
paths: {
|
paths: {
|
||||||
assets,
|
assets,
|
||||||
@ -94,11 +146,13 @@ const createConfig = (params?: WebpackOptions): webpack.Configuration => {
|
|||||||
public: publicPath,
|
public: publicPath,
|
||||||
},
|
},
|
||||||
plugins,
|
plugins,
|
||||||
|
loaders,
|
||||||
};
|
};
|
||||||
|
|
||||||
const isDev = mode === 'development';
|
const isDev = mode === 'development';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
context: process.cwd(),
|
||||||
mode,
|
mode,
|
||||||
entry,
|
entry,
|
||||||
output: createOutput(options),
|
output: createOutput(options),
|
||||||
@ -111,7 +165,8 @@ const createConfig = (params?: WebpackOptions): webpack.Configuration => {
|
|||||||
devServer: createDevServer(options),
|
devServer: createDevServer(options),
|
||||||
// eslint-disable-next-line no-undefined
|
// eslint-disable-next-line no-undefined
|
||||||
optimization: !isDev ? getOptimization(options) : undefined,
|
optimization: !isDev ? getOptimization(options) : undefined,
|
||||||
|
cache: getCache(options),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export { createConfig };
|
export default createConfig;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { Configuration as DevServerConfiguration } from 'webpack-dev-server';
|
import type { Configuration as DevServerConfiguration } from 'webpack-dev-server';
|
||||||
import type { WebpackOptions } from '../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const createDevServer = (options: WebpackOptions): DevServerConfiguration => {
|
const createDevServer = (options: WebpackOptions): DevServerConfiguration => {
|
||||||
const {
|
const {
|
||||||
port,
|
port,
|
||||||
} = options;
|
} = options;
|
||||||
@ -20,3 +20,5 @@ export const createDevServer = (options: WebpackOptions): DevServerConfiguration
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default createDevServer;
|
||||||
|
|||||||
@ -5,4 +5,4 @@ export type {
|
|||||||
WebpackPaths,
|
WebpackPaths,
|
||||||
WebpackMainLoaders,
|
WebpackMainLoaders,
|
||||||
} from './types';
|
} from './types';
|
||||||
export { createConfig } from './config';
|
export { default as createConfig } from './config';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getFontLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
const getFontLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
const {
|
const {
|
||||||
loaders: {
|
loaders: {
|
||||||
fontLoader,
|
fontLoader,
|
||||||
@ -21,3 +21,5 @@ export const getFontLoader = (options: WebpackOptions): webpack.RuleSetRule | nu
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getFontLoader;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getImageLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
const getImageLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
const {
|
const {
|
||||||
loaders: {
|
loaders: {
|
||||||
imageLoader,
|
imageLoader,
|
||||||
@ -21,3 +21,5 @@ export const getImageLoader = (options: WebpackOptions): webpack.RuleSetRule | n
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getImageLoader;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
import { getFontLoader } from './font-loader';
|
import getFontLoader from './font-loader';
|
||||||
import { getImageLoader } from './image-loader';
|
import getImageLoader from './image-loader';
|
||||||
|
|
||||||
export const getAssetsLoaders = (options: WebpackOptions): (webpack.RuleSetRule | null)[] => [
|
export const getAssetsLoaders = (options: WebpackOptions): (webpack.RuleSetRule | null)[] => [
|
||||||
getImageLoader(options),
|
getImageLoader(options),
|
||||||
|
|||||||
@ -1,30 +1,15 @@
|
|||||||
|
import type { WebpackOptions } from 'types';
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../types';
|
|
||||||
import { getAssetsLoaders } from './asset-loaders';
|
import { getAssetsLoaders } from './asset-loaders';
|
||||||
|
import getMainLoader from './main-loaders';
|
||||||
import { getStyleLoaders } from './style-loaders';
|
import { getStyleLoaders } from './style-loaders';
|
||||||
import { getEsbuildLoader } from './esbuild-loader';
|
import getSvgLoader from './svg-loaders';
|
||||||
import { getSvgLoader } from './svgr-loader';
|
|
||||||
import { getSwcLoader } from './swc-loader';
|
|
||||||
|
|
||||||
export const createLoaders = (options: WebpackOptions): (webpack.RuleSetRule | null)[] => {
|
const createLoaders = (options: WebpackOptions): (webpack.RuleSetRule | null)[] => [
|
||||||
const {
|
getMainLoader(options),
|
||||||
mainLoader,
|
getSvgLoader(options),
|
||||||
} = options;
|
...getStyleLoaders(options),
|
||||||
|
...getAssetsLoaders(options),
|
||||||
|
].filter(Boolean);
|
||||||
|
|
||||||
const getMainLoader = () => {
|
export default createLoaders;
|
||||||
switch (mainLoader) {
|
|
||||||
case 'swc':
|
|
||||||
return getSwcLoader(options);
|
|
||||||
case 'esbuild':
|
|
||||||
default:
|
|
||||||
return getEsbuildLoader(options);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return [
|
|
||||||
getMainLoader(),
|
|
||||||
getSvgLoader(options),
|
|
||||||
...getStyleLoaders(options),
|
|
||||||
...getAssetsLoaders(options),
|
|
||||||
].filter(Boolean);
|
|
||||||
};
|
|
||||||
|
|||||||
31
src/loaders/main-loaders/babel-loader/index.ts
Normal file
31
src/loaders/main-loaders/babel-loader/index.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import type webpack from 'webpack';
|
||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
|
const getBabelLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
|
const {
|
||||||
|
loaders: {
|
||||||
|
babelLoader,
|
||||||
|
} = {},
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (babelLoader === 'off') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
test: /\.[j|t]sx?$/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
...babelLoader,
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env', { targets: 'defaults', ...babelLoader?.presets?.env }],
|
||||||
|
['@babel/preset-react', { runtime: 'automatic', ...babelLoader?.presets?.react }],
|
||||||
|
['@babel/preset-typescript', { ...babelLoader?.presets?.typescript }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
exclude: path.resolve('node_modules'),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getBabelLoader;
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getEsbuildLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
const getEsbuildLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
const {
|
const {
|
||||||
paths,
|
paths,
|
||||||
loaders: {
|
loaders: {
|
||||||
@ -19,8 +19,11 @@ export const getEsbuildLoader = (options: WebpackOptions): webpack.RuleSetRule |
|
|||||||
loader: 'esbuild-loader',
|
loader: 'esbuild-loader',
|
||||||
options: {
|
options: {
|
||||||
loader: 'tsx',
|
loader: 'tsx',
|
||||||
|
jsx: 'automatic',
|
||||||
...esbuildLoader,
|
...esbuildLoader,
|
||||||
},
|
},
|
||||||
exclude: path.resolve(paths.root, 'node_modules'),
|
exclude: path.resolve(paths.root, 'node_modules'),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getEsbuildLoader;
|
||||||
25
src/loaders/main-loaders/index.ts
Normal file
25
src/loaders/main-loaders/index.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
import getTsLoader from './ts-loader';
|
||||||
|
import getBabelLoader from './babel-loader';
|
||||||
|
import getSwcLoader from './swc-loader';
|
||||||
|
import getEsbuildLoader from './esbuild-loader';
|
||||||
|
|
||||||
|
const getMainLoader = (options: WebpackOptions) => {
|
||||||
|
const {
|
||||||
|
mainLoader = 'esbuild',
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
switch (mainLoader) {
|
||||||
|
case 'babel':
|
||||||
|
return getBabelLoader(options);
|
||||||
|
case 'ts-loader':
|
||||||
|
return getTsLoader(options);
|
||||||
|
case 'swc':
|
||||||
|
return getSwcLoader(options);
|
||||||
|
case 'esbuild':
|
||||||
|
default:
|
||||||
|
return getEsbuildLoader(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getMainLoader;
|
||||||
60
src/loaders/main-loaders/swc-loader/index.ts
Normal file
60
src/loaders/main-loaders/swc-loader/index.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import type webpack from 'webpack';
|
||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
|
const getSwcLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
|
const {
|
||||||
|
mode,
|
||||||
|
loaders: {
|
||||||
|
swcLoader,
|
||||||
|
} = {},
|
||||||
|
plugins: {
|
||||||
|
reactRefreshPlugin,
|
||||||
|
} = {},
|
||||||
|
} = options;
|
||||||
|
const isDev = mode === 'development';
|
||||||
|
|
||||||
|
if (swcLoader === 'off') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
test: /\.[j|t]sx?$/,
|
||||||
|
exclude: /(node_modules|bower_components)/,
|
||||||
|
loader: 'swc-loader',
|
||||||
|
options: {
|
||||||
|
...swcLoader,
|
||||||
|
sync: true,
|
||||||
|
jsc: {
|
||||||
|
loose: false,
|
||||||
|
externalHelpers: false,
|
||||||
|
keepClassNames: false,
|
||||||
|
...swcLoader?.jsc,
|
||||||
|
parser: {
|
||||||
|
syntax: 'typescript',
|
||||||
|
tsx: true,
|
||||||
|
dynamicImport: true,
|
||||||
|
privateMethod: true,
|
||||||
|
functionBind: true,
|
||||||
|
exportDefaultFrom: true,
|
||||||
|
exportNamespaceFrom: true,
|
||||||
|
decorators: true,
|
||||||
|
decoratorsBeforeExport: true,
|
||||||
|
topLevelAwait: true,
|
||||||
|
importMeta: true,
|
||||||
|
...swcLoader?.jsc?.parser,
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
...swcLoader?.jsc?.transform,
|
||||||
|
react: {
|
||||||
|
runtime: 'automatic',
|
||||||
|
development: isDev,
|
||||||
|
refresh: isDev && reactRefreshPlugin !== 'off',
|
||||||
|
...swcLoader?.jsc?.transform?.react,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getSwcLoader;
|
||||||
26
src/loaders/main-loaders/ts-loader/index.ts
Normal file
26
src/loaders/main-loaders/ts-loader/index.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import type webpack from 'webpack';
|
||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
|
const getTsLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
|
const {
|
||||||
|
loaders: {
|
||||||
|
tsLoader,
|
||||||
|
} = {},
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (tsLoader === 'off') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
test: /\.[j|t]sx?$/,
|
||||||
|
loader: 'ts-loader',
|
||||||
|
options: {
|
||||||
|
...tsLoader,
|
||||||
|
},
|
||||||
|
exclude: path.resolve('node_modules'),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getTsLoader;
|
||||||
@ -2,9 +2,9 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment, no-unsafe-optional-chaining, @typescript-eslint/no-unsafe-member-access, no-nested-ternary */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment, no-unsafe-optional-chaining, @typescript-eslint/no-unsafe-member-access, no-nested-ternary */
|
||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getCssLoader = (options: WebpackOptions): webpack.RuleSetRule => {
|
const getCssLoader = (options: WebpackOptions): webpack.RuleSetRule => {
|
||||||
const {
|
const {
|
||||||
mode,
|
mode,
|
||||||
loaders: {
|
loaders: {
|
||||||
@ -39,6 +39,11 @@ export const getCssLoader = (options: WebpackOptions): webpack.RuleSetRule => {
|
|||||||
options: {
|
options: {
|
||||||
sourceMap: isDev,
|
sourceMap: isDev,
|
||||||
...cssLoader,
|
...cssLoader,
|
||||||
|
modules: {
|
||||||
|
localIdentName: '[local]--[hash:5]',
|
||||||
|
// @ts-ignore
|
||||||
|
...cssLoader?.modules,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
postCssLoader === 'off'
|
postCssLoader === 'off'
|
||||||
@ -46,7 +51,9 @@ export const getCssLoader = (options: WebpackOptions): webpack.RuleSetRule => {
|
|||||||
: {
|
: {
|
||||||
loader: 'postcss-loader',
|
loader: 'postcss-loader',
|
||||||
options: {
|
options: {
|
||||||
|
...postCssLoader,
|
||||||
postcssOptions: {
|
postcssOptions: {
|
||||||
|
...postCssLoader?.postcssOptions,
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
'postcss-preset-env',
|
'postcss-preset-env',
|
||||||
@ -57,11 +64,12 @@ export const getCssLoader = (options: WebpackOptions): webpack.RuleSetRule => {
|
|||||||
],
|
],
|
||||||
...postCssLoader?.postcssOptions?.plugins ?? [],
|
...postCssLoader?.postcssOptions?.plugins ?? [],
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
...postCssLoader?.postcssOptions,
|
|
||||||
},
|
},
|
||||||
...postCssLoader,
|
sourceMap: isDev,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getCssLoader;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
import { getCssLoader } from './css-loader';
|
import getCssLoader from './css-loader';
|
||||||
import { getSassLoader } from './sass-loader';
|
import getSassLoader from './sass-loader';
|
||||||
|
|
||||||
export const getStyleLoaders = (options: WebpackOptions): (webpack.RuleSetRule | null)[] => [
|
export const getStyleLoaders = (options: WebpackOptions): (webpack.RuleSetRule | null)[] => [
|
||||||
getCssLoader(options),
|
getCssLoader(options),
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
import { getCssLoader } from '../css-loader';
|
import getCssLoader from '../css-loader';
|
||||||
|
|
||||||
export const getSassLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
const getSassLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
const {
|
const {
|
||||||
mode,
|
mode,
|
||||||
loaders: {
|
loaders: {
|
||||||
@ -30,3 +30,5 @@ export const getSassLoader = (options: WebpackOptions): webpack.RuleSetRule | nu
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getSassLoader;
|
||||||
|
|||||||
20
src/loaders/svg-loaders/index.ts
Normal file
20
src/loaders/svg-loaders/index.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import getInlineSvgLoader from 'loaders/svg-loaders/inline-svg-loader';
|
||||||
|
import getSvgrLoader from 'loaders/svg-loaders/svgr-loader';
|
||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
|
const getSvgLoader = (options: WebpackOptions) => {
|
||||||
|
const {
|
||||||
|
svgLoader = 'svgr',
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
switch (svgLoader) {
|
||||||
|
case 'inline':
|
||||||
|
return getInlineSvgLoader(options);
|
||||||
|
|
||||||
|
case 'svgr':
|
||||||
|
default:
|
||||||
|
return getSvgrLoader(options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getSvgLoader;
|
||||||
24
src/loaders/svg-loaders/inline-svg-loader/index.ts
Normal file
24
src/loaders/svg-loaders/inline-svg-loader/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
|
const getInlineSvgLoader = (options: WebpackOptions) => {
|
||||||
|
const {
|
||||||
|
loaders: {
|
||||||
|
inlineSvgLoader,
|
||||||
|
} = {},
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (inlineSvgLoader === 'off') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
test: /\.svg$/i,
|
||||||
|
type: 'asset/source',
|
||||||
|
generator: {
|
||||||
|
filename: 'static/icons/[hash][ext][query]',
|
||||||
|
...inlineSvgLoader,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getInlineSvgLoader;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getSvgLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
const getSvgrLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
||||||
const {
|
const {
|
||||||
loaders: {
|
loaders: {
|
||||||
svgrLoader,
|
svgrLoader,
|
||||||
@ -24,3 +24,5 @@ export const getSvgLoader = (options: WebpackOptions): webpack.RuleSetRule | nul
|
|||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getSvgrLoader;
|
||||||
@ -1,58 +0,0 @@
|
|||||||
import type webpack from 'webpack';
|
|
||||||
import type { WebpackOptions } from '../../types';
|
|
||||||
|
|
||||||
export const getSwcLoader = (options: WebpackOptions): webpack.RuleSetRule | null => {
|
|
||||||
const {
|
|
||||||
mode,
|
|
||||||
loaders: {
|
|
||||||
swcLoader,
|
|
||||||
} = {},
|
|
||||||
} = options;
|
|
||||||
const isDev = mode === 'development';
|
|
||||||
|
|
||||||
if (swcLoader === 'off') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
test: /\.[j|t]sx?$/,
|
|
||||||
exclude: /(node_modules|bower_components)/,
|
|
||||||
use: {
|
|
||||||
loader: 'swc-loader',
|
|
||||||
options: {
|
|
||||||
sync: true,
|
|
||||||
jsc: {
|
|
||||||
parser: {
|
|
||||||
syntax: 'typescript',
|
|
||||||
tsx: true,
|
|
||||||
dynamicImport: true,
|
|
||||||
privateMethod: true,
|
|
||||||
functionBind: true,
|
|
||||||
exportDefaultFrom: true,
|
|
||||||
exportNamespaceFrom: true,
|
|
||||||
decorators: true,
|
|
||||||
decoratorsBeforeExport: true,
|
|
||||||
topLevelAwait: true,
|
|
||||||
importMeta: true,
|
|
||||||
...swcLoader?.jsc?.parser,
|
|
||||||
},
|
|
||||||
transform: {
|
|
||||||
react: {
|
|
||||||
runtime: 'automatic',
|
|
||||||
development: isDev,
|
|
||||||
refresh: isDev,
|
|
||||||
...swcLoader?.jsc?.transform?.react,
|
|
||||||
},
|
|
||||||
...swcLoader?.jsc?.transform,
|
|
||||||
},
|
|
||||||
target: 'es2015',
|
|
||||||
loose: false,
|
|
||||||
externalHelpers: false,
|
|
||||||
keepClassNames: false,
|
|
||||||
...swcLoader?.jsc,
|
|
||||||
},
|
|
||||||
...swcLoader,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
|
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
|
||||||
import TerserPlugin from 'terser-webpack-plugin';
|
import TerserPlugin from 'terser-webpack-plugin';
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getOptimization = (options: WebpackOptions): webpack.Configuration['optimization'] => {
|
const getOptimization = (options: WebpackOptions): webpack.Configuration['optimization'] => {
|
||||||
const {
|
const {
|
||||||
mode,
|
mode,
|
||||||
} = options;
|
} = options;
|
||||||
@ -24,3 +24,5 @@ export const getOptimization = (options: WebpackOptions): webpack.Configuration[
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getOptimization;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const createOutput = (options: WebpackOptions): webpack.Configuration['output'] => {
|
const createOutput = (options: WebpackOptions): webpack.Configuration['output'] => {
|
||||||
const {
|
const {
|
||||||
paths,
|
paths,
|
||||||
mode,
|
mode,
|
||||||
@ -27,3 +27,5 @@ export const createOutput = (options: WebpackOptions): webpack.Configuration['ou
|
|||||||
|
|
||||||
return isDev ? devOutput : productionOutput;
|
return isDev ? devOutput : productionOutput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default createOutput;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getBundleAnalyzerPlugin = (options: WebpackOptions) => {
|
const getBundleAnalyzerPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
analyze,
|
analyze,
|
||||||
plugins: {
|
plugins: {
|
||||||
@ -15,3 +15,5 @@ export const getBundleAnalyzerPlugin = (options: WebpackOptions) => {
|
|||||||
|
|
||||||
return new BundleAnalyzerPlugin(analyzerPlugin);
|
return new BundleAnalyzerPlugin(analyzerPlugin);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getBundleAnalyzerPlugin;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import CopyPlugin from 'copy-webpack-plugin';
|
import CopyPlugin from 'copy-webpack-plugin';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getCopyPlugin = (options: WebpackOptions) => {
|
const getCopyPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
paths,
|
paths,
|
||||||
plugins: {
|
plugins: {
|
||||||
@ -25,10 +25,12 @@ export const getCopyPlugin = (options: WebpackOptions) => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
to: path.resolve(paths.root, paths.build),
|
to: path.resolve(paths.root, paths.build),
|
||||||
|
noErrorOnMissing: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
...copyPlugin?.patterns ?? [],
|
...copyPlugin?.patterns ?? [],
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
options: copyPlugin?.options,
|
options: copyPlugin?.options,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getCopyPlugin;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getDefinePlugin = (options: WebpackOptions) => {
|
const getDefinePlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
mode,
|
mode,
|
||||||
plugins: {
|
plugins: {
|
||||||
@ -20,3 +20,5 @@ export const getDefinePlugin = (options: WebpackOptions) => {
|
|||||||
...definePlugin,
|
...definePlugin,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getDefinePlugin;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import ESLintPlugin from 'eslint-webpack-plugin';
|
import ESLintPlugin from 'eslint-webpack-plugin';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
import { hasPackage } from 'utils/helpers';
|
||||||
|
|
||||||
export const getEslintPlugin = (options: WebpackOptions) => {
|
const getEslintPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
paths,
|
paths,
|
||||||
plugins: {
|
plugins: {
|
||||||
@ -10,36 +11,21 @@ export const getEslintPlugin = (options: WebpackOptions) => {
|
|||||||
} = {},
|
} = {},
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const hasEslintPackage = Boolean(process.env.npm_package_dependencies_eslint
|
if (!hasPackage('eslint') || eslintPlugin === 'off') {
|
||||||
?? process.env.npm_package_devDependencies_eslint);
|
|
||||||
|
|
||||||
if (!hasEslintPackage || eslintPlugin === 'off') {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getExcludeArray = () => {
|
|
||||||
// todo fixme
|
|
||||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
||||||
if (!eslintPlugin?.exclude) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(eslintPlugin.exclude)) {
|
|
||||||
return eslintPlugin.exclude;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [eslintPlugin.exclude];
|
|
||||||
};
|
|
||||||
|
|
||||||
return new ESLintPlugin({
|
return new ESLintPlugin({
|
||||||
extensions: ['.js', '.jsx', '.tsx', '.ts'],
|
extensions: ['.js', '.jsx', '.tsx', '.ts'],
|
||||||
failOnError: false,
|
failOnError: false,
|
||||||
lintDirtyModulesOnly: true,
|
lintDirtyModulesOnly: true,
|
||||||
|
...eslintPlugin,
|
||||||
exclude: [
|
exclude: [
|
||||||
path.resolve(paths.root, 'node_modules'),
|
path.resolve(paths.root, 'node_modules'),
|
||||||
paths.build,
|
paths.build,
|
||||||
...getExcludeArray(),
|
...eslintPlugin?.exclude ?? [],
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
...eslintPlugin,
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getEslintPlugin;
|
||||||
|
|||||||
@ -1,16 +1,24 @@
|
|||||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
import { hasPackage } from 'utils/helpers';
|
||||||
|
|
||||||
export const getForkTsCheckerPlugin = (options: WebpackOptions) => {
|
const getForkTsCheckerPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
plugins: {
|
plugins: {
|
||||||
forkTsCheckerPlugin,
|
forkTsCheckerPlugin,
|
||||||
} = {},
|
} = {},
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
if (forkTsCheckerPlugin === 'off') {
|
if (forkTsCheckerPlugin === 'off' || !hasPackage('typescript')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ForkTsCheckerWebpackPlugin(forkTsCheckerPlugin);
|
return new ForkTsCheckerWebpackPlugin({
|
||||||
|
...forkTsCheckerPlugin,
|
||||||
|
typescript: {
|
||||||
|
...forkTsCheckerPlugin?.typescript,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getForkTsCheckerPlugin;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
|
import fs from 'fs';
|
||||||
import HTMLWebpackPlugin from 'html-webpack-plugin';
|
import HTMLWebpackPlugin from 'html-webpack-plugin';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getHtmlPlugin = (options: WebpackOptions) => {
|
const getHtmlPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
paths,
|
paths,
|
||||||
plugins: {
|
plugins: {
|
||||||
@ -14,10 +15,18 @@ export const getHtmlPlugin = (options: WebpackOptions) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(paths.html)) {
|
||||||
|
throw new Error(`index.html file not found. Define path to index.html file or create one in "${paths.public}" directory`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isExistFavicon = fs.existsSync(path.resolve(paths.assets, 'favicon.ico'));
|
||||||
|
|
||||||
return new HTMLWebpackPlugin({
|
return new HTMLWebpackPlugin({
|
||||||
template: paths.html,
|
template: paths.html,
|
||||||
favicon: path.resolve(paths.assets, 'favicon.ico'),
|
favicon: isExistFavicon && path.resolve(paths.assets, 'favicon.ico'),
|
||||||
title: 'My App',
|
title: 'My App',
|
||||||
...htmlWebpackPlugin,
|
...htmlWebpackPlugin,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getHtmlPlugin;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getIgnorePlugin = (options: WebpackOptions) => {
|
const getIgnorePlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
plugins: {
|
plugins: {
|
||||||
ignorePlugin,
|
ignorePlugin,
|
||||||
@ -18,3 +18,5 @@ export const getIgnorePlugin = (options: WebpackOptions) => {
|
|||||||
...ignorePlugin,
|
...ignorePlugin,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getIgnorePlugin;
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../types';
|
import type { WebpackOptions } from 'types';
|
||||||
import { getBundleAnalyzerPlugin } from './bundle-analyzer-plugin';
|
import getBundleAnalyzerPlugin from './bundle-analyzer-plugin';
|
||||||
import { getCopyPlugin } from './copy-plugin';
|
import getCopyPlugin from './copy-plugin';
|
||||||
import { getDefinePlugin } from './define-plugin';
|
import getDefinePlugin from './define-plugin';
|
||||||
import { getEslintPlugin } from './eslint-plugin';
|
import getEslintPlugin from './eslint-plugin';
|
||||||
import { getForkTsCheckerPlugin } from './fork-ts-checker-plugin';
|
import getForkTsCheckerPlugin from './fork-ts-checker-plugin';
|
||||||
import { getHtmlPlugin } from './html-plugin';
|
import getHtmlPlugin from './html-plugin';
|
||||||
import { getIgnorePlugin } from './ignore-plugin';
|
import getIgnorePlugin from './ignore-plugin';
|
||||||
import { getMiniCssPlugin } from './mini-css-plugin';
|
import getMiniCssPlugin from './mini-css-plugin';
|
||||||
import { getProgressPlugin } from './progress';
|
import getProgressPlugin from './progress';
|
||||||
import { getReactRefreshPlugin } from './react-refresh-plugin';
|
import getReactRefreshPlugin from './react-refresh-plugin';
|
||||||
|
|
||||||
export const createPlugins = (options: WebpackOptions): webpack.Configuration['plugins'] => {
|
const createPlugins = (options: WebpackOptions): webpack.Configuration['plugins'] => {
|
||||||
const {
|
const {
|
||||||
mode,
|
mode,
|
||||||
} = options;
|
} = options;
|
||||||
@ -39,5 +39,8 @@ export const createPlugins = (options: WebpackOptions): webpack.Configuration['p
|
|||||||
|
|
||||||
const plugins = isDev ? developmentPlugins : productionPlugins;
|
const plugins = isDev ? developmentPlugins : productionPlugins;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
return plugins.filter(Boolean);
|
return plugins.filter(Boolean);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default createPlugins;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getMiniCssPlugin = (options: WebpackOptions) => {
|
const getMiniCssPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
plugins: {
|
plugins: {
|
||||||
miniCssPlugin,
|
miniCssPlugin,
|
||||||
@ -18,3 +18,5 @@ export const getMiniCssPlugin = (options: WebpackOptions) => {
|
|||||||
...miniCssPlugin,
|
...miniCssPlugin,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getMiniCssPlugin;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getProgressPlugin = (options: WebpackOptions) => {
|
const getProgressPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
plugins: {
|
plugins: {
|
||||||
progressPlugin,
|
progressPlugin,
|
||||||
@ -14,3 +14,5 @@ export const getProgressPlugin = (options: WebpackOptions) => {
|
|||||||
|
|
||||||
return new webpack.ProgressPlugin(progressPlugin);
|
return new webpack.ProgressPlugin(progressPlugin);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getProgressPlugin;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
||||||
import type { WebpackOptions } from '../../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
|
||||||
export const getReactRefreshPlugin = (options: WebpackOptions) => {
|
const getReactRefreshPlugin = (options: WebpackOptions) => {
|
||||||
const {
|
const {
|
||||||
plugins: {
|
plugins: {
|
||||||
reactRefreshPlugin,
|
reactRefreshPlugin,
|
||||||
@ -17,3 +17,5 @@ export const getReactRefreshPlugin = (options: WebpackOptions) => {
|
|||||||
...reactRefreshPlugin,
|
...reactRefreshPlugin,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default getReactRefreshPlugin;
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { WebpackOptions } from '../types';
|
import type { WebpackOptions } from 'types';
|
||||||
|
import getResolversPlugins from './plugins';
|
||||||
|
|
||||||
export const createResolvers = (options: WebpackOptions): webpack.ResolveOptions => {
|
const createResolvers = (options: WebpackOptions): webpack.ResolveOptions => {
|
||||||
const {
|
const {
|
||||||
paths,
|
paths,
|
||||||
} = options;
|
} = options;
|
||||||
@ -16,5 +17,8 @@ export const createResolvers = (options: WebpackOptions): webpack.ResolveOptions
|
|||||||
path.resolve(paths.root),
|
path.resolve(paths.root),
|
||||||
path.resolve(paths.root, 'node_modules'),
|
path.resolve(paths.root, 'node_modules'),
|
||||||
],
|
],
|
||||||
|
plugins: getResolversPlugins(options),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default createResolvers;
|
||||||
|
|||||||
9
src/resolvers/plugins/index.ts
Normal file
9
src/resolvers/plugins/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type webpack from 'webpack';
|
||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
import getTsConfigPathsPlugin from './tsconfig-paths-webpack-plugin';
|
||||||
|
|
||||||
|
const getResolversPlugins = (options: WebpackOptions): webpack.ResolveOptions['plugins'] => [
|
||||||
|
getTsConfigPathsPlugin(options),
|
||||||
|
].filter(Boolean);
|
||||||
|
|
||||||
|
export default getResolversPlugins;
|
||||||
25
src/resolvers/plugins/tsconfig-paths-webpack-plugin/index.ts
Normal file
25
src/resolvers/plugins/tsconfig-paths-webpack-plugin/index.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import process from 'process';
|
||||||
|
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||||
|
import type { WebpackOptions } from 'types';
|
||||||
|
import { hasPackage } from 'utils/helpers';
|
||||||
|
|
||||||
|
const getTsConfigPathsPlugin = (options: WebpackOptions) => {
|
||||||
|
const {
|
||||||
|
resolvers: {
|
||||||
|
plugins: {
|
||||||
|
tsConfigPathsPlugin = {},
|
||||||
|
} = {},
|
||||||
|
} = {},
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (tsConfigPathsPlugin === 'off' || !hasPackage('typescript')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TsconfigPathsPlugin({
|
||||||
|
baseUrl: process.cwd(),
|
||||||
|
...tsConfigPathsPlugin,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getTsConfigPathsPlugin;
|
||||||
@ -12,10 +12,17 @@ import type { PostCSSLoaderOptions } from 'postcss-loader/dist/config';
|
|||||||
import type webpack from 'webpack';
|
import type webpack from 'webpack';
|
||||||
import type { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
import type { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
||||||
import type SassLoader from 'sass-loader';
|
import type SassLoader from 'sass-loader';
|
||||||
|
import type { Options as TsconfigPathsPluginOptions } from 'tsconfig-paths-webpack-plugin/lib/options';
|
||||||
|
import type { Options as TsLoaderOptions } from 'ts-loader';
|
||||||
|
|
||||||
|
type PackageJson = {
|
||||||
|
dependencies: Record<string, string>;
|
||||||
|
devDependencies: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
type WebpackMode = 'development' | 'production';
|
type WebpackMode = 'development' | 'production';
|
||||||
|
|
||||||
type WebpackMainLoaders = 'esbuild' | 'swc';
|
type WebpackMainLoaders = 'babel' | 'esbuild' | 'swc' | 'ts-loader';
|
||||||
|
|
||||||
type WebpackPaths = {
|
type WebpackPaths = {
|
||||||
entry: string[] | string;
|
entry: string[] | string;
|
||||||
@ -130,11 +137,89 @@ declare namespace CssLoader {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
declare namespace BabelLoader {
|
||||||
|
type CallerData = {
|
||||||
|
name: string;
|
||||||
|
supportsStaticESM?: boolean;
|
||||||
|
supportsDynamicImport?: boolean;
|
||||||
|
supportsTopLevelAwait?: boolean;
|
||||||
|
supportsExportNamespaceFrom?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MatchPatternFunc = (
|
||||||
|
filename: string,
|
||||||
|
context: { caller?: { name: string }; envName: string; dirname: string }
|
||||||
|
) => boolean;
|
||||||
|
type MatchPattern = MatchPatternFunc | RegExp | string;
|
||||||
|
|
||||||
|
type EntryTarget = () => Record<string, unknown> | string ;
|
||||||
|
type EntryOptions = Record<string, unknown> | false | undefined;
|
||||||
|
type PluginEntry = EntryTarget | [EntryTarget, EntryOptions, string] | [EntryTarget, EntryOptions];
|
||||||
|
type PresetEntry = EntryTarget | [EntryTarget, EntryOptions, string] | [EntryTarget, EntryOptions];
|
||||||
|
type Options = {
|
||||||
|
cwd?: string;
|
||||||
|
caller?: CallerData;
|
||||||
|
filename?: string;
|
||||||
|
filenameRelative?: string;
|
||||||
|
code?: boolean;
|
||||||
|
ast?: boolean;
|
||||||
|
cloneInputAst?: boolean;
|
||||||
|
root?: string;
|
||||||
|
rootMode?: 'root' | 'upward-optional' | 'upward';
|
||||||
|
envName?: string;
|
||||||
|
configFile?: boolean | string;
|
||||||
|
babelrc?: boolean;
|
||||||
|
babelrcRoots?: MatchPattern | MatchPattern[] | boolean;
|
||||||
|
plugins?: PluginEntry[];
|
||||||
|
presets?: {
|
||||||
|
env: EntryOptions;
|
||||||
|
react: EntryOptions;
|
||||||
|
typescript: EntryOptions;
|
||||||
|
};
|
||||||
|
passPerPreset?: boolean;
|
||||||
|
targets?: Record<string, string> | string[] | string;
|
||||||
|
browserslistConfigFile?: boolean;
|
||||||
|
browserslistEnv?: string;
|
||||||
|
extends?: string;
|
||||||
|
env?: Record<string, unknown>;
|
||||||
|
overrides?: unknown[];
|
||||||
|
test?: MatchPattern | MatchPattern[];
|
||||||
|
include?: MatchPattern | MatchPattern[];
|
||||||
|
exclude?: MatchPattern | MatchPattern[];
|
||||||
|
ignore?: MatchPattern[];
|
||||||
|
only?: MatchPattern[];
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
||||||
|
inputSourceMap?: webpack.Configuration['devtool'] | boolean; // todo
|
||||||
|
sourceMaps?: boolean | 'both' | 'inline';
|
||||||
|
sourceFileName?: string;
|
||||||
|
sourceRoot?: string;
|
||||||
|
sourceType?: 'module' | 'script' | 'unambiguous';
|
||||||
|
assumptions?: Record<string, boolean>;
|
||||||
|
highlightCode?: boolean;
|
||||||
|
wrapPluginVisitorMethod?: unknown;
|
||||||
|
parserOpts?: Record<string, unknown>;
|
||||||
|
generatorOpts?: Record<string, unknown>;
|
||||||
|
retainLines?: boolean;
|
||||||
|
compact?: boolean | 'auto';
|
||||||
|
minified?: boolean;
|
||||||
|
auxiliaryCommentBefore?: string;
|
||||||
|
auxiliaryCommentAfter?: string;
|
||||||
|
comments?: boolean;
|
||||||
|
shouldPrintComment?: (value: string) => boolean;
|
||||||
|
moduleIds?: boolean;
|
||||||
|
moduleId?: string;
|
||||||
|
getModuleId?: (name: string) => string;
|
||||||
|
moduleRoot?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
type WebpackOptions = {
|
type WebpackOptions = {
|
||||||
mode: WebpackMode;
|
mode: WebpackMode;
|
||||||
paths: WebpackPaths;
|
paths: WebpackPaths;
|
||||||
port: number;
|
port: number;
|
||||||
mainLoader: WebpackMainLoaders;
|
mainLoader?: WebpackMainLoaders;
|
||||||
|
svgLoader?: 'inline' | 'svgr';
|
||||||
analyze: boolean;
|
analyze: boolean;
|
||||||
devtool?: webpack.Configuration['devtool'];
|
devtool?: webpack.Configuration['devtool'];
|
||||||
plugins?: {
|
plugins?: {
|
||||||
@ -153,6 +238,7 @@ type WebpackOptions = {
|
|||||||
esbuildLoader?: EsbuildLoaderOptions | 'off';
|
esbuildLoader?: EsbuildLoaderOptions | 'off';
|
||||||
swcLoader?: SwcLoaderOptions | 'off';
|
swcLoader?: SwcLoaderOptions | 'off';
|
||||||
svgrLoader?: SvgrLoaderOptions | 'off';
|
svgrLoader?: SvgrLoaderOptions | 'off';
|
||||||
|
inlineSvgLoader?: AssetsLoader.Options | 'off';
|
||||||
styleLoader?: StyleLoader.Options | 'off';
|
styleLoader?: StyleLoader.Options | 'off';
|
||||||
cssLoader?: CssLoader.Options | 'off';
|
cssLoader?: CssLoader.Options | 'off';
|
||||||
miniCssLoader?: MiniCssLoaderOptions | 'off';
|
miniCssLoader?: MiniCssLoaderOptions | 'off';
|
||||||
@ -161,7 +247,15 @@ type WebpackOptions = {
|
|||||||
sassLoader?: SassLoader.Options | 'off';
|
sassLoader?: SassLoader.Options | 'off';
|
||||||
imageLoader?: AssetsLoader.Options | 'off';
|
imageLoader?: AssetsLoader.Options | 'off';
|
||||||
fontLoader?: AssetsLoader.Options | 'off';
|
fontLoader?: AssetsLoader.Options | 'off';
|
||||||
|
babelLoader?: BabelLoader.Options | 'off';
|
||||||
|
tsLoader?: TsLoaderOptions | 'off';
|
||||||
};
|
};
|
||||||
|
resolvers?: {
|
||||||
|
plugins: {
|
||||||
|
tsConfigPathsPlugin?: TsconfigPathsPluginOptions | 'off';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
cache?: webpack.Configuration['cache'] | 'off';
|
||||||
};
|
};
|
||||||
|
|
||||||
type WebpackEnv = {
|
type WebpackEnv = {
|
||||||
@ -177,4 +271,5 @@ export type {
|
|||||||
WebpackOptions,
|
WebpackOptions,
|
||||||
WebpackEnv,
|
WebpackEnv,
|
||||||
WebpackMainLoaders,
|
WebpackMainLoaders,
|
||||||
|
PackageJson,
|
||||||
};
|
};
|
||||||
|
|||||||
13
src/utils/helpers.ts
Normal file
13
src/utils/helpers.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import type { PackageJson } from 'types';
|
||||||
|
|
||||||
|
export const hasPackage = (packageName: string) => {
|
||||||
|
if (!packageName) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-non-null-assertion
|
||||||
|
const packageJson: PackageJson = JSON.parse(fs.readFileSync(process.env.npm_package_json!, 'utf8'));
|
||||||
|
|
||||||
|
return Boolean(packageJson.dependencies[packageName] || packageJson.devDependencies[packageName]);
|
||||||
|
};
|
||||||
@ -12,7 +12,10 @@
|
|||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"lib": [
|
"lib": [
|
||||||
"DOM"
|
"DOM"
|
||||||
]
|
],
|
||||||
|
"paths": {
|
||||||
|
"*": ["./src/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user