Skip to content

Commit 1235d52

Browse files
committed
Copy size-limit config from react-redux
1 parent ee6c57f commit 1235d52

File tree

1 file changed

+165
-197
lines changed

1 file changed

+165
-197
lines changed

packages/toolkit/.size-limit.mts

Lines changed: 165 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -1,208 +1,176 @@
1-
const webpack = require('webpack')
2-
let { join } = require('path')
3-
4-
const esmSuffixes = ['modern.mjs' /*, 'browser.mjs', 'legacy-esm.js'*/]
5-
const cjsSuffixes = [/*'development.cjs',*/ 'production.min.cjs']
6-
7-
function withRtkPath(suffix, cjs = false) {
8-
/**
9-
* @param {string} name
10-
*/
11-
function alias(name) {
12-
return `${cjs ? 'cjs/' : ''}${name}.${suffix}`
1+
import type { Check, SizeLimitConfig } from 'size-limit'
2+
import type { Configuration } from 'webpack'
3+
4+
/**
5+
* An array of all possible Node environments.
6+
*/
7+
const allNodeEnvs = ['development', 'production'] as const
8+
9+
/**
10+
* Represents a specific environment for a Node.js application.
11+
*/
12+
type NodeEnv = (typeof allNodeEnvs)[number]
13+
14+
/**
15+
* Set of entry points from the `package.json` file.
16+
*/
17+
const packageJsonEntryPoints = new Set<string>()
18+
19+
/**
20+
* Recursively collects entry points from the `package.json` exports field.
21+
*
22+
* @param packageJsonExports - The exports field from `package.json`.
23+
* @returns - A set of package entry points.
24+
*/
25+
const collectPackageJsonExports = async (
26+
packageJsonExports:
27+
| string
28+
| Record<string, any>
29+
| null
30+
| typeof import('./package.json').exports,
31+
) => {
32+
if (typeof packageJsonExports === 'string') {
33+
packageJsonEntryPoints.add(
34+
packageJsonExports.startsWith('./')
35+
? packageJsonExports
36+
: `./${packageJsonExports}`,
37+
)
38+
39+
return packageJsonEntryPoints
1340
}
14-
/**
15-
* @param {webpack.Configuration} config
16-
*/
17-
return (config) => {
18-
config.plugins.push(
19-
new webpack.NormalModuleReplacementPlugin(
20-
/@reduxjs\/toolkit\/query\/react/,
21-
join(__dirname, 'dist/query/react/rtk-query-react.modern.mjs'),
22-
),
23-
new webpack.NormalModuleReplacementPlugin(
24-
/@reduxjs\/toolkit\/query/,
25-
join(__dirname, 'dist/query/rtk-query.modern.mjs'),
26-
),
27-
new webpack.NormalModuleReplacementPlugin(
28-
/@reduxjs\/toolkit\/react/,
29-
join(__dirname, 'dist/react/redux-toolkit-react.modern.mjs'),
30-
),
31-
new webpack.NormalModuleReplacementPlugin(
32-
/@reduxjs\/toolkit/,
33-
join(__dirname, 'dist/redux-toolkit.modern.mjs'),
34-
),
35-
new webpack.NormalModuleReplacementPlugin(
36-
/rtk-query-react.modern.mjs/,
37-
(r) => {
38-
const old = r.request
39-
r.request = r.request.replace(
40-
/rtk-query-react.modern.mjs$/,
41-
alias('rtk-query-react'),
42-
)
43-
//console.log(old, '=>', r.request)
44-
},
45-
),
46-
new webpack.NormalModuleReplacementPlugin(/rtk-query.modern.mjs/, (r) => {
47-
const old = r.request
48-
r.request = r.request.replace(
49-
/rtk-query.modern.mjs$/,
50-
alias('rtk-query'),
41+
42+
if (typeof packageJsonExports === 'object' && packageJsonExports !== null) {
43+
await Promise.all(
44+
Object.entries(packageJsonExports)
45+
.filter(
46+
([condition]) =>
47+
condition !== './package.json' && condition !== 'types',
5148
)
52-
//console.log(old, '=>', r.request)
53-
}),
54-
new webpack.NormalModuleReplacementPlugin(
55-
/redux-toolkit-react.modern.mjs$/,
56-
(r) => {
57-
const old = r.request
58-
r.request = r.request.replace(
59-
/redux-toolkit-react.modern.mjs$/,
60-
alias('redux-toolkit-react'),
61-
)
62-
//console.log(old, '=>', r.request)
63-
},
64-
),
65-
new webpack.NormalModuleReplacementPlugin(
66-
/redux-toolkit.modern.mjs$/,
67-
(r) => {
68-
const old = r.request
69-
r.request = r.request.replace(
70-
/redux-toolkit.modern.mjs$/,
71-
alias('redux-toolkit'),
72-
)
73-
//console.log(old, '=>', r.request)
74-
},
75-
),
49+
.map(([_condition, entryPoint]) => entryPoint)
50+
.map(collectPackageJsonExports),
7651
)
77-
78-
if (suffix === 'production.min.cjs') {
79-
;(config.resolve ??= {}).mainFields = ['main', 'module']
80-
}
81-
;(config.optimization ??= {}).nodeEnv = 'production'
82-
return config
8352
}
53+
54+
return packageJsonEntryPoints
8455
}
8556

86-
const ignoreAll = [
87-
'@reduxjs/toolkit',
88-
'@reduxjs/toolkit/query',
89-
'immer',
90-
'redux',
91-
'reselect',
92-
'redux-thunk',
93-
]
94-
95-
const entryPoints = [
96-
{
97-
name: `1. entry point: @reduxjs/toolkit`,
98-
path: 'dist/redux-toolkit.modern.mjs',
99-
},
100-
{
101-
name: `1. entry point: @reduxjs/toolkit/react`,
102-
path: 'dist/react/redux-toolkit-react.modern.mjs',
103-
},
104-
{
105-
name: `1. entry point: @reduxjs/toolkit/query`,
106-
path: 'dist/query/rtk-query.modern.mjs',
107-
},
108-
{
109-
name: `1. entry point: @reduxjs/toolkit/query/react`,
110-
path: 'dist/query/react/rtk-query-react.modern.mjs',
111-
},
112-
{
113-
name: `2. entry point: @reduxjs/toolkit (without dependencies)`,
114-
path: 'dist/redux-toolkit.modern.mjs',
115-
ignore: ignoreAll,
116-
},
117-
{
118-
name: `2. entry point: @reduxjs/toolkit/react (without dependencies)`,
119-
path: 'dist/react/redux-toolkit-react.modern.mjs',
120-
ignore: ignoreAll,
121-
},
122-
{
123-
name: `2. entry point: @reduxjs/toolkit/query (without dependencies)`,
124-
path: 'dist/query/rtk-query.modern.mjs',
125-
ignore: ignoreAll,
126-
},
127-
{
128-
name: `2. entry point: @reduxjs/toolkit/query/react (without dependencies)`,
129-
path: 'dist/query/react/rtk-query-react.modern.mjs',
130-
ignore: ignoreAll,
131-
},
132-
]
133-
134-
module.exports = entryPoints
135-
.flatMap((e) =>
136-
esmSuffixes.map((suffix) => ({
137-
...e,
138-
name: e.name + ` (${suffix})`,
139-
modifyWebpackConfig: withRtkPath(suffix),
140-
})),
141-
)
142-
.concat(
143-
entryPoints.flatMap((e) =>
144-
cjsSuffixes.map((suffix) => ({
145-
...e,
146-
name: e.name + ` (cjs, ${suffix})`,
147-
modifyWebpackConfig: withRtkPath(suffix, true),
148-
})),
149-
),
150-
)
151-
.concat(
152-
[
153-
{
154-
name: `3. createSlice`,
155-
import: { '@reduxjs/toolkit': '{ createSlice }' },
156-
},
157-
{
158-
name: `3. createAsyncThunk`,
159-
import: { '@reduxjs/toolkit': '{ createAsyncThunk }' },
160-
},
161-
{
162-
name: `3. buildCreateSlice and asyncThunkCreator`,
163-
import: {
164-
'@reduxjs/toolkit': '{ buildCreateSlice, asyncThunkCreator }',
165-
},
166-
},
167-
{
168-
name: `3. createEntityAdapter`,
169-
import: { '@reduxjs/toolkit': '{ createEntityAdapter }' },
170-
},
171-
{
172-
name: `3. configureStore`,
173-
import: { '@reduxjs/toolkit': '{ configureStore }' },
174-
},
175-
{
176-
name: `3. combineSlices`,
177-
import: { '@reduxjs/toolkit': '{ combineSlices }' },
178-
},
179-
{
180-
name: `3. createDynamicMiddleware`,
181-
import: { '@reduxjs/toolkit': '{ createDynamicMiddleware }' },
182-
},
183-
{
184-
name: `3. createDynamicMiddleware (react)`,
185-
import: { '@reduxjs/toolkit/react': '{ createDynamicMiddleware }' },
186-
},
187-
{
188-
name: `3. createListenerMiddleware`,
189-
import: { '@reduxjs/toolkit': '{ createListenerMiddleware }' },
190-
},
191-
{
192-
name: `3. createApi`,
193-
import: { '@reduxjs/toolkit/query': '{ createApi }' },
194-
},
57+
/**
58+
* Gets all package entry points from the `package.json` file.
59+
*
60+
* @returns A promise that resolves to an array of unique package entry points.
61+
*/
62+
const getAllPackageEntryPoints = async () => {
63+
const packageJson = await import('./package.json', { with: { type: 'json' } })
64+
65+
const packageExports = await collectPackageJsonExports(packageJson.exports)
66+
67+
return [...packageExports]
68+
}
69+
70+
/**
71+
* Gets all import configurations for a given entry point.
72+
* This function dynamically imports the specified entry point and
73+
* generates a size limit configuration for each named export found
74+
* within the module. It includes configurations for named imports,
75+
* wildcard imports, and the default import.
76+
*
77+
* @param entryPoint - The entry point to import.
78+
* @param index - The index of the entry point in the list.
79+
* @returns A promise that resolves to a size limit configuration object.
80+
*/
81+
const getAllImportsForEntryPoint = async (
82+
entryPoint: string,
83+
index: number,
84+
): Promise<SizeLimitConfig> => {
85+
const allNamedImports: typeof import('./src/index') = await import(entryPoint)
86+
87+
return Object.keys(allNamedImports)
88+
.map<Check>((namedImport) => ({
89+
path: entryPoint,
90+
name: `${index + 1}. import { ${namedImport} } from "${entryPoint}"`,
91+
import: `{ ${namedImport} }`,
92+
}))
93+
.concat([
19594
{
196-
name: `3. createApi (react)`,
197-
import: { '@reduxjs/toolkit/query/react': '{ createApi }' },
95+
path: entryPoint,
96+
name: `${index + 1}. import * from "${entryPoint}"`,
97+
import: '*',
19898
},
19999
{
200-
name: `3. fetchBaseQuery`,
201-
import: { '@reduxjs/toolkit/query': '{ fetchBaseQuery }' },
100+
path: entryPoint,
101+
name: `${index + 1}. import "${entryPoint}"`,
202102
},
203-
].map((e) => ({
204-
...e,
205-
name: e.name + ` (.modern.mjs)`,
206-
modifyWebpackConfig: withRtkPath('modern.mjs'),
207-
})),
103+
])
104+
}
105+
106+
/**
107+
* Sets the `NODE_ENV` for a given Webpack configuration.
108+
*
109+
* @param nodeEnv - The `NODE_ENV` to set (either 'development' or 'production').
110+
* @returns A function that modifies the Webpack configuration.
111+
*/
112+
const setNodeEnv = (nodeEnv: NodeEnv) => {
113+
const modifyWebpackConfig = ((config: Configuration) => {
114+
;(config.optimization ??= {}).nodeEnv = nodeEnv
115+
return config
116+
}) satisfies Check['modifyWebpackConfig']
117+
118+
return modifyWebpackConfig
119+
}
120+
121+
/**
122+
* Gets all import configurations with a specified `NODE_ENV`.
123+
*
124+
* @param nodeEnv - The `NODE_ENV` to set (either 'development' or 'production').
125+
* @returns A promise that resolves to a size limit configuration object.
126+
*/
127+
const getAllImportsWithNodeEnv = async (nodeEnv: NodeEnv) => {
128+
const allPackageEntryPoints = await getAllPackageEntryPoints()
129+
130+
const allImportsFromAllEntryPoints = (
131+
await Promise.all(allPackageEntryPoints.map(getAllImportsForEntryPoint))
132+
).flat()
133+
134+
const modifyWebpackConfig = setNodeEnv(nodeEnv)
135+
136+
const allImportsWithNodeEnv = allImportsFromAllEntryPoints.map<Check>(
137+
(importsFromEntryPoint) => ({
138+
...importsFromEntryPoint,
139+
name: `${importsFromEntryPoint.name} ('${nodeEnv}' mode)`,
140+
modifyWebpackConfig,
141+
}),
208142
)
143+
144+
return allImportsWithNodeEnv
145+
}
146+
147+
/**
148+
* Gets the size limit configuration for all `NODE_ENV`s.
149+
*
150+
* @returns A promise that resolves to the size limit configuration object.
151+
*/
152+
const getSizeLimitConfig = async (): Promise<SizeLimitConfig> => {
153+
const packageJson = await import('./package.json', { with: { type: 'json' } })
154+
155+
const sizeLimitConfig = (
156+
await Promise.all(allNodeEnvs.map(getAllImportsWithNodeEnv))
157+
).flat()
158+
159+
if ('dependencies' in packageJson) {
160+
const sizeLimitConfigWithoutDependencies = sizeLimitConfig.map<Check>(
161+
(check) => ({
162+
...check,
163+
name: `${check.name} (excluding dependencies)`,
164+
ignore: Object.keys(packageJson.dependencies),
165+
}),
166+
)
167+
return sizeLimitConfig.concat(sizeLimitConfigWithoutDependencies)
168+
}
169+
170+
return sizeLimitConfig
171+
}
172+
173+
const sizeLimitConfig: Promise<SizeLimitConfig> = (async () =>
174+
await getSizeLimitConfig())()
175+
176+
export default sizeLimitConfig

0 commit comments

Comments
 (0)