@wyw-in-js/nextjs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/esm/index.mjs +360 -0
- package/esm/index.mjs.map +1 -0
- package/lib/index.js +372 -0
- package/lib/index.js.map +1 -0
- package/package.json +47 -0
- package/types/index.d.ts +7 -0
- package/types/index.js +373 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# `@wyw-in-js/nextjs`
|
|
2
|
+
|
|
3
|
+
Next.js integration for WyW via `@wyw-in-js/webpack-loader`.
|
|
4
|
+
|
|
5
|
+
This package supports:
|
|
6
|
+
|
|
7
|
+
- Webpack pipeline (`next dev --webpack`, `next build`) via `@wyw-in-js/webpack-loader`.
|
|
8
|
+
- Turbopack pipeline (`next dev`) via `turbopack.rules` and `@wyw-in-js/turbopack-loader`.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
# npm
|
|
14
|
+
npm i -D @wyw-in-js/nextjs
|
|
15
|
+
# yarn
|
|
16
|
+
yarn add --dev @wyw-in-js/nextjs
|
|
17
|
+
# pnpm
|
|
18
|
+
pnpm add -D @wyw-in-js/nextjs
|
|
19
|
+
# bun
|
|
20
|
+
bun add -d @wyw-in-js/nextjs
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// next.config.js
|
|
27
|
+
const { withWyw } = require('@wyw-in-js/nextjs');
|
|
28
|
+
|
|
29
|
+
module.exports = withWyw({
|
|
30
|
+
// your Next config
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
By default, the plugin:
|
|
35
|
+
|
|
36
|
+
- injects `@wyw-in-js/webpack-loader` into Next's JS/TS pipeline;
|
|
37
|
+
- emits styles as `*.wyw-in-js.module.css` so imports are allowed from any module;
|
|
38
|
+
- keeps generated class names stable under Next CSS Modules (selectors are emitted as `:global(...)`).
|
|
39
|
+
- defaults `babelOptions` to `presets: ['next/babel']` so TS/JSX parsing works out of the box.
|
|
40
|
+
|
|
41
|
+
## Options
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import type { WywNextPluginOptions } from '@wyw-in-js/nextjs';
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use `loaderOptions` to pass options through to `@wyw-in-js/webpack-loader`.
|
|
48
|
+
|
|
49
|
+
Use `turbopackLoaderOptions` to pass JSON-serializable options to `@wyw-in-js/turbopack-loader` (use `configFile` for
|
|
50
|
+
function-based config).
|
|
51
|
+
|
|
52
|
+
To disable vendor prefixing (Stylis prefixer), set `prefixer: false` in `loaderOptions` and/or `turbopackLoaderOptions`.
|
package/esm/index.mjs
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const DEFAULT_EXTENSION = '.wyw-in-js.module.css';
|
|
4
|
+
const DEFAULT_TURBO_RULE_KEYS = ['*.js', '*.jsx', '*.ts', '*.tsx'];
|
|
5
|
+
const PLACEHOLDER_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx']);
|
|
6
|
+
const PLACEHOLDER_IGNORED_DIRS = new Set(['.git', '.next', '.turbo', 'node_modules']);
|
|
7
|
+
function isObject(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null;
|
|
9
|
+
}
|
|
10
|
+
function isUseLoaderObject(item) {
|
|
11
|
+
return isObject(item) && typeof item.loader === 'string';
|
|
12
|
+
}
|
|
13
|
+
function normalizeUseItems(use) {
|
|
14
|
+
if (!use) return null;
|
|
15
|
+
if (typeof use === 'function') return null;
|
|
16
|
+
const list = (Array.isArray(use) ? use : [use]).filter(Boolean);
|
|
17
|
+
return list.length ? list : null;
|
|
18
|
+
}
|
|
19
|
+
function getLoaderName(item) {
|
|
20
|
+
if (typeof item === 'string') return item;
|
|
21
|
+
if (isUseLoaderObject(item)) return item.loader;
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
function isWywLoaderPath(loader) {
|
|
25
|
+
return loader.includes('@wyw-in-js/webpack-loader') || /[\\/]webpack-loader[\\/]/.test(loader);
|
|
26
|
+
}
|
|
27
|
+
function convertLoaderRuleToUseRule(rule, wywLoaderItem) {
|
|
28
|
+
const {
|
|
29
|
+
loader
|
|
30
|
+
} = rule;
|
|
31
|
+
if (typeof loader !== 'string') return;
|
|
32
|
+
const alreadyInjected = isWywLoaderPath(loader);
|
|
33
|
+
if (alreadyInjected) return;
|
|
34
|
+
const isNextJsTranspileRule = ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some(needle => loader.includes(needle));
|
|
35
|
+
if (!isNextJsTranspileRule) return;
|
|
36
|
+
const {
|
|
37
|
+
options
|
|
38
|
+
} = rule;
|
|
39
|
+
const nextRule = rule;
|
|
40
|
+
delete nextRule.loader;
|
|
41
|
+
delete nextRule.options;
|
|
42
|
+
|
|
43
|
+
// Loader order is right-to-left. We want WyW to run first, so it should be last.
|
|
44
|
+
Object.assign(nextRule, {
|
|
45
|
+
use: [{
|
|
46
|
+
loader,
|
|
47
|
+
...(options !== undefined ? {
|
|
48
|
+
options
|
|
49
|
+
} : {})
|
|
50
|
+
}, wywLoaderItem]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function traverseRules(rules, visitor) {
|
|
54
|
+
for (const rule of rules) {
|
|
55
|
+
if (rule && typeof rule === 'object') {
|
|
56
|
+
visitor(rule);
|
|
57
|
+
if (Array.isArray(rule.oneOf)) {
|
|
58
|
+
traverseRules(rule.oneOf, visitor);
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(rule.rules)) {
|
|
61
|
+
traverseRules(rule.rules, visitor);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function escapeRegExp(value) {
|
|
67
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
68
|
+
}
|
|
69
|
+
function isPlainObject(value) {
|
|
70
|
+
if (!isObject(value)) return false;
|
|
71
|
+
const proto = Object.getPrototypeOf(value);
|
|
72
|
+
return proto === Object.prototype || proto === null;
|
|
73
|
+
}
|
|
74
|
+
function assertNoFunctions(value, name) {
|
|
75
|
+
const queue = [{
|
|
76
|
+
path: name,
|
|
77
|
+
value
|
|
78
|
+
}];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
while (queue.length) {
|
|
81
|
+
const current = queue.shift();
|
|
82
|
+
if (typeof current.value === 'function') {
|
|
83
|
+
throw new Error(`${current.path} must be JSON-serializable (functions are not supported in Turbopack loader options). Use "configFile" to pass non-JSON config.`);
|
|
84
|
+
}
|
|
85
|
+
if (current.value === null) {
|
|
86
|
+
// skip
|
|
87
|
+
} else if (Array.isArray(current.value)) {
|
|
88
|
+
if (!seen.has(current.value)) {
|
|
89
|
+
seen.add(current.value);
|
|
90
|
+
current.value.forEach((item, idx) => queue.push({
|
|
91
|
+
path: `${current.path}[${idx}]`,
|
|
92
|
+
value: item
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
} else if (isPlainObject(current.value)) {
|
|
96
|
+
if (!seen.has(current.value)) {
|
|
97
|
+
seen.add(current.value);
|
|
98
|
+
Object.entries(current.value).forEach(([key, item]) => queue.push({
|
|
99
|
+
path: `${current.path}.${key}`,
|
|
100
|
+
value: item
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function createWywCssModuleRule(baseRule, extensionSuffix) {
|
|
107
|
+
const use = normalizeUseItems(baseRule.use) ?? [];
|
|
108
|
+
const patchedUse = use.map(item => {
|
|
109
|
+
if (!isUseLoaderObject(item) || !item.loader.includes('css-loader')) {
|
|
110
|
+
return item;
|
|
111
|
+
}
|
|
112
|
+
const itemOptions = item.options;
|
|
113
|
+
if (!isObject(itemOptions)) {
|
|
114
|
+
return item;
|
|
115
|
+
}
|
|
116
|
+
const {
|
|
117
|
+
modules
|
|
118
|
+
} = itemOptions;
|
|
119
|
+
if (!isObject(modules)) {
|
|
120
|
+
return item;
|
|
121
|
+
}
|
|
122
|
+
const nextModules = {
|
|
123
|
+
...modules,
|
|
124
|
+
mode: 'global',
|
|
125
|
+
getLocalIdent: (_context, _localIdentName, localName) => localName
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
...item,
|
|
129
|
+
options: {
|
|
130
|
+
...itemOptions,
|
|
131
|
+
modules: nextModules
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
const nextRule = {
|
|
136
|
+
...baseRule,
|
|
137
|
+
sideEffects: true,
|
|
138
|
+
test: new RegExp(`${escapeRegExp(extensionSuffix)}$`),
|
|
139
|
+
use: patchedUse
|
|
140
|
+
};
|
|
141
|
+
return nextRule;
|
|
142
|
+
}
|
|
143
|
+
function ensureWywCssModuleRules(config, extensionSuffix) {
|
|
144
|
+
traverseRules(config.module?.rules ?? [], rule => {
|
|
145
|
+
if (!Array.isArray(rule.oneOf) || rule.oneOf.length === 0) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const expectedTestSource = `${escapeRegExp(extensionSuffix)}$`;
|
|
149
|
+
const alreadyPresent = rule.oneOf.some(candidate => {
|
|
150
|
+
if (!candidate || typeof candidate !== 'object') return false;
|
|
151
|
+
const {
|
|
152
|
+
test
|
|
153
|
+
} = candidate;
|
|
154
|
+
return test instanceof RegExp && test.source === expectedTestSource;
|
|
155
|
+
});
|
|
156
|
+
if (alreadyPresent) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const oneOf = rule.oneOf;
|
|
160
|
+
for (let idx = 0; idx < oneOf.length; idx += 1) {
|
|
161
|
+
const candidate = oneOf[idx];
|
|
162
|
+
if (candidate && typeof candidate === 'object') {
|
|
163
|
+
const candidateRule = candidate;
|
|
164
|
+
const {
|
|
165
|
+
test
|
|
166
|
+
} = candidateRule;
|
|
167
|
+
const isModuleCssRule = test instanceof RegExp && test.source.includes('\\.module\\.css');
|
|
168
|
+
if (isModuleCssRule) {
|
|
169
|
+
const use = normalizeUseItems(candidateRule.use);
|
|
170
|
+
if (use) {
|
|
171
|
+
const hasCssLoader = use.some(item => isUseLoaderObject(item) && item.loader.includes('css-loader'));
|
|
172
|
+
if (hasCssLoader) {
|
|
173
|
+
oneOf.splice(idx, 0, createWywCssModuleRule(candidateRule, extensionSuffix));
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function injectWywLoader(config, nextOptions, wywNext) {
|
|
183
|
+
const loader = require.resolve('@wyw-in-js/webpack-loader');
|
|
184
|
+
const nextBabelPreset = require.resolve('next/babel', {
|
|
185
|
+
paths: [process.cwd()]
|
|
186
|
+
});
|
|
187
|
+
const extension = wywNext.loaderOptions?.extension ?? DEFAULT_EXTENSION;
|
|
188
|
+
const babelOptions = wywNext.loaderOptions?.babelOptions ?? {
|
|
189
|
+
presets: [nextBabelPreset]
|
|
190
|
+
};
|
|
191
|
+
const loaderOptions = {
|
|
192
|
+
cssImport: 'import',
|
|
193
|
+
...wywNext.loaderOptions,
|
|
194
|
+
babelOptions,
|
|
195
|
+
extension,
|
|
196
|
+
sourceMap: wywNext.loaderOptions?.sourceMap ?? nextOptions.dev
|
|
197
|
+
};
|
|
198
|
+
const wywLoaderItem = {
|
|
199
|
+
loader,
|
|
200
|
+
options: loaderOptions
|
|
201
|
+
};
|
|
202
|
+
traverseRules(config.module?.rules ?? [], rule => {
|
|
203
|
+
convertLoaderRuleToUseRule(rule, wywLoaderItem);
|
|
204
|
+
const use = normalizeUseItems(rule.use);
|
|
205
|
+
if (!use) return;
|
|
206
|
+
const loaders = use.map(getLoaderName);
|
|
207
|
+
const alreadyInjected = loaders.some(l => l === loader || isWywLoaderPath(l));
|
|
208
|
+
if (alreadyInjected) return;
|
|
209
|
+
const isNextJsTranspileRule = loaders.some(l => ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some(needle => l.includes(needle)));
|
|
210
|
+
if (!isNextJsTranspileRule) return;
|
|
211
|
+
|
|
212
|
+
// Loader order is right-to-left. We want WyW to run first, so it should be last.
|
|
213
|
+
Object.assign(rule, {
|
|
214
|
+
use: [...use, wywLoaderItem]
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
ensureWywCssModuleRules(config, extension);
|
|
218
|
+
}
|
|
219
|
+
function ensureTurbopackCssPlaceholders(projectRoot) {
|
|
220
|
+
const queue = [projectRoot];
|
|
221
|
+
while (queue.length) {
|
|
222
|
+
const dir = queue.pop();
|
|
223
|
+
let entries;
|
|
224
|
+
try {
|
|
225
|
+
entries = fs.readdirSync(dir, {
|
|
226
|
+
withFileTypes: true
|
|
227
|
+
});
|
|
228
|
+
} catch {
|
|
229
|
+
entries = [];
|
|
230
|
+
}
|
|
231
|
+
for (const entry of entries) {
|
|
232
|
+
if (entry.name !== '.' && entry.name !== '..') {
|
|
233
|
+
const entryPath = path.join(dir, entry.name);
|
|
234
|
+
if (entry.isDirectory()) {
|
|
235
|
+
if (!PLACEHOLDER_IGNORED_DIRS.has(entry.name)) {
|
|
236
|
+
queue.push(entryPath);
|
|
237
|
+
}
|
|
238
|
+
} else if (entry.isFile()) {
|
|
239
|
+
const shouldIgnore = entry.name.startsWith('middleware.') || entry.name.endsWith('.d.ts');
|
|
240
|
+
if (!shouldIgnore) {
|
|
241
|
+
const ext = path.extname(entry.name);
|
|
242
|
+
if (PLACEHOLDER_EXTENSIONS.has(ext)) {
|
|
243
|
+
const baseName = path.basename(entry.name, ext);
|
|
244
|
+
const cssFilePath = path.join(path.dirname(entryPath), `${baseName}${DEFAULT_EXTENSION}`);
|
|
245
|
+
try {
|
|
246
|
+
fs.writeFileSync(cssFilePath, '', {
|
|
247
|
+
flag: 'wx'
|
|
248
|
+
});
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (err.code !== 'EEXIST') {
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function shouldUseTurbopackConfig(nextConfig) {
|
|
262
|
+
const explicit = nextConfig.turbopack;
|
|
263
|
+
if (typeof explicit !== 'undefined') {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
const pkgPath = require.resolve('next/package.json', {
|
|
268
|
+
paths: [process.cwd()]
|
|
269
|
+
});
|
|
270
|
+
const pkg = require(pkgPath);
|
|
271
|
+
const version = typeof pkg.version === 'string' ? pkg.version : '';
|
|
272
|
+
const major = Number.parseInt(version.split('.')[0] ?? '', 10);
|
|
273
|
+
return Number.isFinite(major) && major >= 16;
|
|
274
|
+
} catch {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function injectWywTurbopackRules(nextConfig, wywNext) {
|
|
279
|
+
const loader = require.resolve('@wyw-in-js/turbopack-loader');
|
|
280
|
+
const nextBabelPreset = require.resolve('next/babel', {
|
|
281
|
+
paths: [process.cwd()]
|
|
282
|
+
});
|
|
283
|
+
const userOptions = wywNext.turbopackLoaderOptions ?? {};
|
|
284
|
+
assertNoFunctions(userOptions, 'turbopackLoaderOptions');
|
|
285
|
+
const loaderOptions = {
|
|
286
|
+
babelOptions: {
|
|
287
|
+
presets: [nextBabelPreset]
|
|
288
|
+
},
|
|
289
|
+
sourceMap: process.env.NODE_ENV !== 'production',
|
|
290
|
+
...userOptions
|
|
291
|
+
};
|
|
292
|
+
const useTurbopackConfig = shouldUseTurbopackConfig(nextConfig);
|
|
293
|
+
const isNextBuild = process.argv.includes('build');
|
|
294
|
+
const isWebpackBuild = process.argv.includes('--webpack');
|
|
295
|
+
if (useTurbopackConfig && process.env.NODE_ENV === 'production' && isNextBuild && !isWebpackBuild) {
|
|
296
|
+
ensureTurbopackCssPlaceholders(process.cwd());
|
|
297
|
+
}
|
|
298
|
+
const ruleValue = useTurbopackConfig ? {
|
|
299
|
+
loaders: [{
|
|
300
|
+
loader,
|
|
301
|
+
options: loaderOptions
|
|
302
|
+
}],
|
|
303
|
+
condition: {
|
|
304
|
+
all: [{
|
|
305
|
+
not: 'foreign'
|
|
306
|
+
}, {
|
|
307
|
+
not: {
|
|
308
|
+
path: /(?:^|[\\/])middleware\.[jt]sx?$/
|
|
309
|
+
}
|
|
310
|
+
}]
|
|
311
|
+
}
|
|
312
|
+
} : [{
|
|
313
|
+
loader,
|
|
314
|
+
options: loaderOptions
|
|
315
|
+
}];
|
|
316
|
+
const wywRules = Object.fromEntries(DEFAULT_TURBO_RULE_KEYS.map(key => [key, ruleValue]));
|
|
317
|
+
if (useTurbopackConfig) {
|
|
318
|
+
const turbopackConfig = nextConfig.turbopack;
|
|
319
|
+
const userTurbopack = isPlainObject(turbopackConfig) ? turbopackConfig : {};
|
|
320
|
+
const userRules = isPlainObject(userTurbopack.rules) ? userTurbopack.rules : {};
|
|
321
|
+
return {
|
|
322
|
+
...nextConfig,
|
|
323
|
+
turbopack: {
|
|
324
|
+
...userTurbopack,
|
|
325
|
+
rules: {
|
|
326
|
+
...wywRules,
|
|
327
|
+
...userRules
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
const userExperimental = isPlainObject(nextConfig.experimental) ? nextConfig.experimental : {};
|
|
333
|
+
const userTurbo = isPlainObject(userExperimental.turbo) ? userExperimental.turbo : {};
|
|
334
|
+
const userRules = isPlainObject(userTurbo.rules) ? userTurbo.rules : {};
|
|
335
|
+
return {
|
|
336
|
+
...nextConfig,
|
|
337
|
+
experimental: {
|
|
338
|
+
...userExperimental,
|
|
339
|
+
turbo: {
|
|
340
|
+
...userTurbo,
|
|
341
|
+
rules: {
|
|
342
|
+
...wywRules,
|
|
343
|
+
...userRules
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
export function withWyw(nextConfig = {}, wywNext = {}) {
|
|
350
|
+
const userWebpack = nextConfig.webpack;
|
|
351
|
+
return {
|
|
352
|
+
...injectWywTurbopackRules(nextConfig, wywNext),
|
|
353
|
+
webpack(config, options) {
|
|
354
|
+
const resolvedConfig = typeof userWebpack === 'function' ? userWebpack(config, options) : config;
|
|
355
|
+
injectWywLoader(resolvedConfig, options, wywNext);
|
|
356
|
+
return resolvedConfig;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["fs","path","DEFAULT_EXTENSION","DEFAULT_TURBO_RULE_KEYS","PLACEHOLDER_EXTENSIONS","Set","PLACEHOLDER_IGNORED_DIRS","isObject","value","isUseLoaderObject","item","loader","normalizeUseItems","use","list","Array","isArray","filter","Boolean","length","getLoaderName","isWywLoaderPath","includes","test","convertLoaderRuleToUseRule","rule","wywLoaderItem","alreadyInjected","isNextJsTranspileRule","some","needle","options","nextRule","Object","assign","undefined","traverseRules","rules","visitor","oneOf","escapeRegExp","replace","isPlainObject","proto","getPrototypeOf","prototype","assertNoFunctions","name","queue","seen","current","shift","Error","has","add","forEach","idx","push","entries","key","createWywCssModuleRule","baseRule","extensionSuffix","patchedUse","map","itemOptions","modules","nextModules","mode","getLocalIdent","_context","_localIdentName","localName","sideEffects","RegExp","ensureWywCssModuleRules","config","module","expectedTestSource","alreadyPresent","candidate","source","candidateRule","isModuleCssRule","hasCssLoader","splice","injectWywLoader","nextOptions","wywNext","require","resolve","nextBabelPreset","paths","process","cwd","extension","loaderOptions","babelOptions","presets","cssImport","sourceMap","dev","loaders","l","ensureTurbopackCssPlaceholders","projectRoot","dir","pop","readdirSync","withFileTypes","entry","entryPath","join","isDirectory","isFile","shouldIgnore","startsWith","endsWith","ext","extname","baseName","basename","cssFilePath","dirname","writeFileSync","flag","err","code","shouldUseTurbopackConfig","nextConfig","explicit","turbopack","pkgPath","pkg","version","major","Number","parseInt","split","isFinite","injectWywTurbopackRules","userOptions","turbopackLoaderOptions","env","NODE_ENV","useTurbopackConfig","isNextBuild","argv","isWebpackBuild","ruleValue","condition","all","not","wywRules","fromEntries","turbopackConfig","userTurbopack","userRules","userExperimental","experimental","userTurbo","turbo","withWyw","userWebpack","webpack","resolvedConfig"],"sources":["../src/index.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { LoaderOptions as WywWebpackLoaderOptions } from '@wyw-in-js/webpack-loader';\nimport type { NextConfig } from 'next';\nimport type { Configuration, RuleSetRule, RuleSetUseItem } from 'webpack';\n\nconst DEFAULT_EXTENSION = '.wyw-in-js.module.css';\n\nconst DEFAULT_TURBO_RULE_KEYS = ['*.js', '*.jsx', '*.ts', '*.tsx'];\n\nconst PLACEHOLDER_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx']);\nconst PLACEHOLDER_IGNORED_DIRS = new Set([\n '.git',\n '.next',\n '.turbo',\n 'node_modules',\n]);\n\nexport type WywNextPluginOptions = {\n loaderOptions?: Omit<WywWebpackLoaderOptions, 'extension' | 'sourceMap'> &\n Partial<Pick<WywWebpackLoaderOptions, 'extension' | 'sourceMap'>>;\n turbopackLoaderOptions?: Record<string, unknown>;\n};\n\ntype NextWebpackConfigFn = NonNullable<NextConfig['webpack']>;\ntype NextWebpackOptions = Parameters<NextWebpackConfigFn>[1];\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isUseLoaderObject(\n item: RuleSetUseItem\n): item is Exclude<RuleSetUseItem, string> & { loader: string } {\n return (\n isObject(item) &&\n typeof (item as Record<string, unknown>).loader === 'string'\n );\n}\n\nfunction normalizeUseItems(use: RuleSetRule['use']): RuleSetUseItem[] | null {\n if (!use) return null;\n if (typeof use === 'function') return null;\n\n const list = (Array.isArray(use) ? use : [use]).filter(Boolean);\n return list.length ? (list as RuleSetUseItem[]) : null;\n}\n\nfunction getLoaderName(item: RuleSetUseItem): string {\n if (typeof item === 'string') return item;\n if (isUseLoaderObject(item)) return item.loader;\n return '';\n}\n\nfunction isWywLoaderPath(loader: string) {\n return (\n loader.includes('@wyw-in-js/webpack-loader') ||\n /[\\\\/]webpack-loader[\\\\/]/.test(loader)\n );\n}\n\nfunction convertLoaderRuleToUseRule(\n rule: RuleSetRule,\n wywLoaderItem: RuleSetUseItem\n) {\n const { loader } = rule as { loader?: unknown };\n if (typeof loader !== 'string') return;\n\n const alreadyInjected = isWywLoaderPath(loader);\n if (alreadyInjected) return;\n\n const isNextJsTranspileRule = [\n 'next-swc-loader',\n 'next-babel-loader',\n 'babel-loader',\n ].some((needle) => loader.includes(needle));\n if (!isNextJsTranspileRule) return;\n\n const { options } = rule as { options?: unknown };\n\n const nextRule = rule as RuleSetRule & {\n loader?: unknown;\n options?: unknown;\n };\n\n delete nextRule.loader;\n delete nextRule.options;\n\n // Loader order is right-to-left. We want WyW to run first, so it should be last.\n Object.assign(nextRule, {\n use: [\n { loader, ...(options !== undefined ? { options } : {}) },\n wywLoaderItem,\n ],\n });\n}\n\nfunction traverseRules(rules: unknown[], visitor: (rule: RuleSetRule) => void) {\n for (const rule of rules) {\n if (rule && typeof rule === 'object') {\n visitor(rule as RuleSetRule);\n\n if (Array.isArray((rule as RuleSetRule).oneOf)) {\n traverseRules((rule as RuleSetRule).oneOf!, visitor);\n }\n if (Array.isArray((rule as RuleSetRule).rules)) {\n traverseRules((rule as RuleSetRule).rules!, visitor);\n }\n }\n }\n}\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (!isObject(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction assertNoFunctions(value: unknown, name: string) {\n const queue: Array<{ path: string; value: unknown }> = [\n { path: name, value },\n ];\n const seen = new Set<unknown>();\n\n while (queue.length) {\n const current = queue.shift()!;\n\n if (typeof current.value === 'function') {\n throw new Error(\n `${current.path} must be JSON-serializable (functions are not supported in Turbopack loader options). Use \"configFile\" to pass non-JSON config.`\n );\n }\n\n if (current.value === null) {\n // skip\n } else if (Array.isArray(current.value)) {\n if (!seen.has(current.value)) {\n seen.add(current.value);\n current.value.forEach((item, idx) =>\n queue.push({ path: `${current.path}[${idx}]`, value: item })\n );\n }\n } else if (isPlainObject(current.value)) {\n if (!seen.has(current.value)) {\n seen.add(current.value);\n Object.entries(current.value).forEach(([key, item]) =>\n queue.push({ path: `${current.path}.${key}`, value: item })\n );\n }\n }\n }\n}\n\nfunction createWywCssModuleRule(\n baseRule: RuleSetRule,\n extensionSuffix: string\n): RuleSetRule {\n const use = normalizeUseItems(baseRule.use) ?? [];\n\n const patchedUse = use.map((item) => {\n if (!isUseLoaderObject(item) || !item.loader.includes('css-loader')) {\n return item;\n }\n\n const itemOptions = (item as { options?: unknown }).options;\n if (!isObject(itemOptions)) {\n return item;\n }\n\n const { modules } = itemOptions as { modules?: unknown };\n if (!isObject(modules)) {\n return item;\n }\n\n const nextModules = {\n ...(modules as Record<string, unknown>),\n mode: 'global',\n getLocalIdent: (\n _context: unknown,\n _localIdentName: string,\n localName: string\n ) => localName,\n };\n\n return {\n ...item,\n options: {\n ...(itemOptions as Record<string, unknown>),\n modules: nextModules,\n },\n };\n });\n\n const nextRule: RuleSetRule = {\n ...baseRule,\n sideEffects: true,\n test: new RegExp(`${escapeRegExp(extensionSuffix)}$`),\n use: patchedUse,\n };\n\n return nextRule;\n}\n\nfunction ensureWywCssModuleRules(\n config: Configuration,\n extensionSuffix: string\n) {\n traverseRules(config.module?.rules ?? [], (rule) => {\n if (!Array.isArray(rule.oneOf) || rule.oneOf.length === 0) {\n return;\n }\n\n const expectedTestSource = `${escapeRegExp(extensionSuffix)}$`;\n\n const alreadyPresent = rule.oneOf.some((candidate) => {\n if (!candidate || typeof candidate !== 'object') return false;\n\n const { test } = candidate as RuleSetRule;\n return test instanceof RegExp && test.source === expectedTestSource;\n });\n\n if (alreadyPresent) {\n return;\n }\n\n const oneOf = rule.oneOf as unknown[];\n for (let idx = 0; idx < oneOf.length; idx += 1) {\n const candidate = oneOf[idx];\n if (candidate && typeof candidate === 'object') {\n const candidateRule = candidate as RuleSetRule;\n const { test } = candidateRule;\n\n const isModuleCssRule =\n test instanceof RegExp && test.source.includes('\\\\.module\\\\.css');\n\n if (isModuleCssRule) {\n const use = normalizeUseItems(candidateRule.use);\n if (use) {\n const hasCssLoader = use.some(\n (item) =>\n isUseLoaderObject(item) && item.loader.includes('css-loader')\n );\n if (hasCssLoader) {\n oneOf.splice(\n idx,\n 0,\n createWywCssModuleRule(candidateRule, extensionSuffix)\n );\n break;\n }\n }\n }\n }\n }\n });\n}\n\nfunction injectWywLoader(\n config: Configuration,\n nextOptions: NextWebpackOptions,\n wywNext: WywNextPluginOptions\n) {\n const loader = require.resolve('@wyw-in-js/webpack-loader');\n const nextBabelPreset = require.resolve('next/babel', {\n paths: [process.cwd()],\n });\n\n const extension = wywNext.loaderOptions?.extension ?? DEFAULT_EXTENSION;\n const babelOptions = wywNext.loaderOptions?.babelOptions ?? {\n presets: [nextBabelPreset],\n };\n\n const loaderOptions = {\n cssImport: 'import',\n ...wywNext.loaderOptions,\n babelOptions,\n extension,\n sourceMap: wywNext.loaderOptions?.sourceMap ?? nextOptions.dev,\n } satisfies WywWebpackLoaderOptions;\n\n const wywLoaderItem: RuleSetUseItem = {\n loader,\n options: loaderOptions,\n };\n\n traverseRules(config.module?.rules ?? [], (rule) => {\n convertLoaderRuleToUseRule(rule, wywLoaderItem);\n\n const use = normalizeUseItems(rule.use);\n if (!use) return;\n\n const loaders = use.map(getLoaderName);\n\n const alreadyInjected = loaders.some(\n (l) => l === loader || isWywLoaderPath(l)\n );\n if (alreadyInjected) return;\n\n const isNextJsTranspileRule = loaders.some((l) =>\n ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some((needle) =>\n l.includes(needle)\n )\n );\n if (!isNextJsTranspileRule) return;\n\n // Loader order is right-to-left. We want WyW to run first, so it should be last.\n Object.assign(rule, { use: [...use, wywLoaderItem] });\n });\n\n ensureWywCssModuleRules(config, extension);\n}\n\nfunction ensureTurbopackCssPlaceholders(projectRoot: string) {\n const queue: string[] = [projectRoot];\n\n while (queue.length) {\n const dir = queue.pop()!;\n let entries: fs.Dirent[];\n\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n entries = [];\n }\n\n for (const entry of entries) {\n if (entry.name !== '.' && entry.name !== '..') {\n const entryPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!PLACEHOLDER_IGNORED_DIRS.has(entry.name)) {\n queue.push(entryPath);\n }\n } else if (entry.isFile()) {\n const shouldIgnore =\n entry.name.startsWith('middleware.') ||\n entry.name.endsWith('.d.ts');\n\n if (!shouldIgnore) {\n const ext = path.extname(entry.name);\n if (PLACEHOLDER_EXTENSIONS.has(ext)) {\n const baseName = path.basename(entry.name, ext);\n const cssFilePath = path.join(\n path.dirname(entryPath),\n `${baseName}${DEFAULT_EXTENSION}`\n );\n\n try {\n fs.writeFileSync(cssFilePath, '', { flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw err;\n }\n }\n }\n }\n }\n }\n }\n }\n}\n\nfunction shouldUseTurbopackConfig(nextConfig: NextConfig) {\n const explicit = (nextConfig as unknown as Record<string, unknown>).turbopack;\n if (typeof explicit !== 'undefined') {\n return true;\n }\n\n try {\n const pkgPath = require.resolve('next/package.json', {\n paths: [process.cwd()],\n });\n const pkg = require(pkgPath) as { version?: unknown };\n const version = typeof pkg.version === 'string' ? pkg.version : '';\n const major = Number.parseInt(version.split('.')[0] ?? '', 10);\n return Number.isFinite(major) && major >= 16;\n } catch {\n return false;\n }\n}\n\nfunction injectWywTurbopackRules(\n nextConfig: NextConfig,\n wywNext: WywNextPluginOptions\n): NextConfig {\n const loader = require.resolve('@wyw-in-js/turbopack-loader');\n const nextBabelPreset = require.resolve('next/babel', {\n paths: [process.cwd()],\n });\n\n const userOptions = wywNext.turbopackLoaderOptions ?? {};\n\n assertNoFunctions(userOptions, 'turbopackLoaderOptions');\n\n const loaderOptions = {\n babelOptions: { presets: [nextBabelPreset] },\n sourceMap: process.env.NODE_ENV !== 'production',\n ...userOptions,\n };\n\n const useTurbopackConfig = shouldUseTurbopackConfig(nextConfig);\n\n const isNextBuild = process.argv.includes('build');\n const isWebpackBuild = process.argv.includes('--webpack');\n\n if (\n useTurbopackConfig &&\n process.env.NODE_ENV === 'production' &&\n isNextBuild &&\n !isWebpackBuild\n ) {\n ensureTurbopackCssPlaceholders(process.cwd());\n }\n\n const ruleValue = useTurbopackConfig\n ? {\n loaders: [{ loader, options: loaderOptions }],\n condition: {\n all: [\n { not: 'foreign' },\n { not: { path: /(?:^|[\\\\/])middleware\\.[jt]sx?$/ } },\n ],\n },\n }\n : [{ loader, options: loaderOptions }];\n\n const wywRules = Object.fromEntries(\n DEFAULT_TURBO_RULE_KEYS.map((key) => [key, ruleValue])\n );\n\n if (useTurbopackConfig) {\n const turbopackConfig = (nextConfig as unknown as Record<string, unknown>)\n .turbopack;\n const userTurbopack = isPlainObject(turbopackConfig) ? turbopackConfig : {};\n\n const userRules = isPlainObject(userTurbopack.rules)\n ? (userTurbopack.rules as Record<string, unknown>)\n : {};\n\n return {\n ...nextConfig,\n turbopack: {\n ...userTurbopack,\n rules: {\n ...wywRules,\n ...userRules,\n },\n },\n } as NextConfig;\n }\n\n const userExperimental = isPlainObject(nextConfig.experimental)\n ? (nextConfig.experimental as Record<string, unknown>)\n : {};\n\n const userTurbo = isPlainObject(userExperimental.turbo)\n ? (userExperimental.turbo as Record<string, unknown>)\n : {};\n\n const userRules = isPlainObject(userTurbo.rules)\n ? (userTurbo.rules as Record<string, unknown>)\n : {};\n\n return {\n ...nextConfig,\n experimental: {\n ...userExperimental,\n turbo: {\n ...userTurbo,\n rules: {\n ...wywRules,\n ...userRules,\n },\n },\n },\n } as NextConfig;\n}\n\nexport function withWyw(\n nextConfig: NextConfig = {},\n wywNext: WywNextPluginOptions = {}\n): NextConfig {\n const userWebpack = nextConfig.webpack;\n\n return {\n ...injectWywTurbopackRules(nextConfig, wywNext),\n webpack(config: Configuration, options: NextWebpackOptions) {\n const resolvedConfig =\n typeof userWebpack === 'function'\n ? userWebpack(config, options)\n : config;\n\n injectWywLoader(resolvedConfig, options, wywNext);\n\n return resolvedConfig;\n },\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.withWyw = withWyw;
|
|
7
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
const DEFAULT_EXTENSION = '.wyw-in-js.module.css';
|
|
11
|
+
const DEFAULT_TURBO_RULE_KEYS = ['*.js', '*.jsx', '*.ts', '*.tsx'];
|
|
12
|
+
const PLACEHOLDER_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx']);
|
|
13
|
+
const PLACEHOLDER_IGNORED_DIRS = new Set(['.git', '.next', '.turbo', 'node_modules']);
|
|
14
|
+
function isObject(value) {
|
|
15
|
+
return typeof value === 'object' && value !== null;
|
|
16
|
+
}
|
|
17
|
+
function isUseLoaderObject(item) {
|
|
18
|
+
return isObject(item) && typeof item.loader === 'string';
|
|
19
|
+
}
|
|
20
|
+
function normalizeUseItems(use) {
|
|
21
|
+
if (!use) return null;
|
|
22
|
+
if (typeof use === 'function') return null;
|
|
23
|
+
const list = (Array.isArray(use) ? use : [use]).filter(Boolean);
|
|
24
|
+
return list.length ? list : null;
|
|
25
|
+
}
|
|
26
|
+
function getLoaderName(item) {
|
|
27
|
+
if (typeof item === 'string') return item;
|
|
28
|
+
if (isUseLoaderObject(item)) return item.loader;
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
function isWywLoaderPath(loader) {
|
|
32
|
+
return loader.includes('@wyw-in-js/webpack-loader') || /[\\/]webpack-loader[\\/]/.test(loader);
|
|
33
|
+
}
|
|
34
|
+
function convertLoaderRuleToUseRule(rule, wywLoaderItem) {
|
|
35
|
+
const {
|
|
36
|
+
loader
|
|
37
|
+
} = rule;
|
|
38
|
+
if (typeof loader !== 'string') return;
|
|
39
|
+
const alreadyInjected = isWywLoaderPath(loader);
|
|
40
|
+
if (alreadyInjected) return;
|
|
41
|
+
const isNextJsTranspileRule = ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some(needle => loader.includes(needle));
|
|
42
|
+
if (!isNextJsTranspileRule) return;
|
|
43
|
+
const {
|
|
44
|
+
options
|
|
45
|
+
} = rule;
|
|
46
|
+
const nextRule = rule;
|
|
47
|
+
delete nextRule.loader;
|
|
48
|
+
delete nextRule.options;
|
|
49
|
+
|
|
50
|
+
// Loader order is right-to-left. We want WyW to run first, so it should be last.
|
|
51
|
+
Object.assign(nextRule, {
|
|
52
|
+
use: [{
|
|
53
|
+
loader,
|
|
54
|
+
...(options !== undefined ? {
|
|
55
|
+
options
|
|
56
|
+
} : {})
|
|
57
|
+
}, wywLoaderItem]
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function traverseRules(rules, visitor) {
|
|
61
|
+
for (const rule of rules) {
|
|
62
|
+
if (rule && typeof rule === 'object') {
|
|
63
|
+
visitor(rule);
|
|
64
|
+
if (Array.isArray(rule.oneOf)) {
|
|
65
|
+
traverseRules(rule.oneOf, visitor);
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(rule.rules)) {
|
|
68
|
+
traverseRules(rule.rules, visitor);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function escapeRegExp(value) {
|
|
74
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
75
|
+
}
|
|
76
|
+
function isPlainObject(value) {
|
|
77
|
+
if (!isObject(value)) return false;
|
|
78
|
+
const proto = Object.getPrototypeOf(value);
|
|
79
|
+
return proto === Object.prototype || proto === null;
|
|
80
|
+
}
|
|
81
|
+
function assertNoFunctions(value, name) {
|
|
82
|
+
const queue = [{
|
|
83
|
+
path: name,
|
|
84
|
+
value
|
|
85
|
+
}];
|
|
86
|
+
const seen = new Set();
|
|
87
|
+
while (queue.length) {
|
|
88
|
+
const current = queue.shift();
|
|
89
|
+
if (typeof current.value === 'function') {
|
|
90
|
+
throw new Error(`${current.path} must be JSON-serializable (functions are not supported in Turbopack loader options). Use "configFile" to pass non-JSON config.`);
|
|
91
|
+
}
|
|
92
|
+
if (current.value === null) {
|
|
93
|
+
// skip
|
|
94
|
+
} else if (Array.isArray(current.value)) {
|
|
95
|
+
if (!seen.has(current.value)) {
|
|
96
|
+
seen.add(current.value);
|
|
97
|
+
current.value.forEach((item, idx) => queue.push({
|
|
98
|
+
path: `${current.path}[${idx}]`,
|
|
99
|
+
value: item
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
} else if (isPlainObject(current.value)) {
|
|
103
|
+
if (!seen.has(current.value)) {
|
|
104
|
+
seen.add(current.value);
|
|
105
|
+
Object.entries(current.value).forEach(([key, item]) => queue.push({
|
|
106
|
+
path: `${current.path}.${key}`,
|
|
107
|
+
value: item
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function createWywCssModuleRule(baseRule, extensionSuffix) {
|
|
114
|
+
var _normalizeUseItems;
|
|
115
|
+
const use = (_normalizeUseItems = normalizeUseItems(baseRule.use)) !== null && _normalizeUseItems !== void 0 ? _normalizeUseItems : [];
|
|
116
|
+
const patchedUse = use.map(item => {
|
|
117
|
+
if (!isUseLoaderObject(item) || !item.loader.includes('css-loader')) {
|
|
118
|
+
return item;
|
|
119
|
+
}
|
|
120
|
+
const itemOptions = item.options;
|
|
121
|
+
if (!isObject(itemOptions)) {
|
|
122
|
+
return item;
|
|
123
|
+
}
|
|
124
|
+
const {
|
|
125
|
+
modules
|
|
126
|
+
} = itemOptions;
|
|
127
|
+
if (!isObject(modules)) {
|
|
128
|
+
return item;
|
|
129
|
+
}
|
|
130
|
+
const nextModules = {
|
|
131
|
+
...modules,
|
|
132
|
+
mode: 'global',
|
|
133
|
+
getLocalIdent: (_context, _localIdentName, localName) => localName
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
...item,
|
|
137
|
+
options: {
|
|
138
|
+
...itemOptions,
|
|
139
|
+
modules: nextModules
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
const nextRule = {
|
|
144
|
+
...baseRule,
|
|
145
|
+
sideEffects: true,
|
|
146
|
+
test: new RegExp(`${escapeRegExp(extensionSuffix)}$`),
|
|
147
|
+
use: patchedUse
|
|
148
|
+
};
|
|
149
|
+
return nextRule;
|
|
150
|
+
}
|
|
151
|
+
function ensureWywCssModuleRules(config, extensionSuffix) {
|
|
152
|
+
var _config$module$rules, _config$module;
|
|
153
|
+
traverseRules((_config$module$rules = (_config$module = config.module) === null || _config$module === void 0 ? void 0 : _config$module.rules) !== null && _config$module$rules !== void 0 ? _config$module$rules : [], rule => {
|
|
154
|
+
if (!Array.isArray(rule.oneOf) || rule.oneOf.length === 0) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const expectedTestSource = `${escapeRegExp(extensionSuffix)}$`;
|
|
158
|
+
const alreadyPresent = rule.oneOf.some(candidate => {
|
|
159
|
+
if (!candidate || typeof candidate !== 'object') return false;
|
|
160
|
+
const {
|
|
161
|
+
test
|
|
162
|
+
} = candidate;
|
|
163
|
+
return test instanceof RegExp && test.source === expectedTestSource;
|
|
164
|
+
});
|
|
165
|
+
if (alreadyPresent) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const oneOf = rule.oneOf;
|
|
169
|
+
for (let idx = 0; idx < oneOf.length; idx += 1) {
|
|
170
|
+
const candidate = oneOf[idx];
|
|
171
|
+
if (candidate && typeof candidate === 'object') {
|
|
172
|
+
const candidateRule = candidate;
|
|
173
|
+
const {
|
|
174
|
+
test
|
|
175
|
+
} = candidateRule;
|
|
176
|
+
const isModuleCssRule = test instanceof RegExp && test.source.includes('\\.module\\.css');
|
|
177
|
+
if (isModuleCssRule) {
|
|
178
|
+
const use = normalizeUseItems(candidateRule.use);
|
|
179
|
+
if (use) {
|
|
180
|
+
const hasCssLoader = use.some(item => isUseLoaderObject(item) && item.loader.includes('css-loader'));
|
|
181
|
+
if (hasCssLoader) {
|
|
182
|
+
oneOf.splice(idx, 0, createWywCssModuleRule(candidateRule, extensionSuffix));
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
function injectWywLoader(config, nextOptions, wywNext) {
|
|
192
|
+
var _wywNext$loaderOption, _wywNext$loaderOption2, _wywNext$loaderOption3, _wywNext$loaderOption4, _wywNext$loaderOption5, _wywNext$loaderOption6, _config$module$rules2, _config$module2;
|
|
193
|
+
const loader = require.resolve('@wyw-in-js/webpack-loader');
|
|
194
|
+
const nextBabelPreset = require.resolve('next/babel', {
|
|
195
|
+
paths: [process.cwd()]
|
|
196
|
+
});
|
|
197
|
+
const extension = (_wywNext$loaderOption = (_wywNext$loaderOption2 = wywNext.loaderOptions) === null || _wywNext$loaderOption2 === void 0 ? void 0 : _wywNext$loaderOption2.extension) !== null && _wywNext$loaderOption !== void 0 ? _wywNext$loaderOption : DEFAULT_EXTENSION;
|
|
198
|
+
const babelOptions = (_wywNext$loaderOption3 = (_wywNext$loaderOption4 = wywNext.loaderOptions) === null || _wywNext$loaderOption4 === void 0 ? void 0 : _wywNext$loaderOption4.babelOptions) !== null && _wywNext$loaderOption3 !== void 0 ? _wywNext$loaderOption3 : {
|
|
199
|
+
presets: [nextBabelPreset]
|
|
200
|
+
};
|
|
201
|
+
const loaderOptions = {
|
|
202
|
+
cssImport: 'import',
|
|
203
|
+
...wywNext.loaderOptions,
|
|
204
|
+
babelOptions,
|
|
205
|
+
extension,
|
|
206
|
+
sourceMap: (_wywNext$loaderOption5 = (_wywNext$loaderOption6 = wywNext.loaderOptions) === null || _wywNext$loaderOption6 === void 0 ? void 0 : _wywNext$loaderOption6.sourceMap) !== null && _wywNext$loaderOption5 !== void 0 ? _wywNext$loaderOption5 : nextOptions.dev
|
|
207
|
+
};
|
|
208
|
+
const wywLoaderItem = {
|
|
209
|
+
loader,
|
|
210
|
+
options: loaderOptions
|
|
211
|
+
};
|
|
212
|
+
traverseRules((_config$module$rules2 = (_config$module2 = config.module) === null || _config$module2 === void 0 ? void 0 : _config$module2.rules) !== null && _config$module$rules2 !== void 0 ? _config$module$rules2 : [], rule => {
|
|
213
|
+
convertLoaderRuleToUseRule(rule, wywLoaderItem);
|
|
214
|
+
const use = normalizeUseItems(rule.use);
|
|
215
|
+
if (!use) return;
|
|
216
|
+
const loaders = use.map(getLoaderName);
|
|
217
|
+
const alreadyInjected = loaders.some(l => l === loader || isWywLoaderPath(l));
|
|
218
|
+
if (alreadyInjected) return;
|
|
219
|
+
const isNextJsTranspileRule = loaders.some(l => ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some(needle => l.includes(needle)));
|
|
220
|
+
if (!isNextJsTranspileRule) return;
|
|
221
|
+
|
|
222
|
+
// Loader order is right-to-left. We want WyW to run first, so it should be last.
|
|
223
|
+
Object.assign(rule, {
|
|
224
|
+
use: [...use, wywLoaderItem]
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
ensureWywCssModuleRules(config, extension);
|
|
228
|
+
}
|
|
229
|
+
function ensureTurbopackCssPlaceholders(projectRoot) {
|
|
230
|
+
const queue = [projectRoot];
|
|
231
|
+
while (queue.length) {
|
|
232
|
+
const dir = queue.pop();
|
|
233
|
+
let entries;
|
|
234
|
+
try {
|
|
235
|
+
entries = _fs.default.readdirSync(dir, {
|
|
236
|
+
withFileTypes: true
|
|
237
|
+
});
|
|
238
|
+
} catch {
|
|
239
|
+
entries = [];
|
|
240
|
+
}
|
|
241
|
+
for (const entry of entries) {
|
|
242
|
+
if (entry.name !== '.' && entry.name !== '..') {
|
|
243
|
+
const entryPath = _path.default.join(dir, entry.name);
|
|
244
|
+
if (entry.isDirectory()) {
|
|
245
|
+
if (!PLACEHOLDER_IGNORED_DIRS.has(entry.name)) {
|
|
246
|
+
queue.push(entryPath);
|
|
247
|
+
}
|
|
248
|
+
} else if (entry.isFile()) {
|
|
249
|
+
const shouldIgnore = entry.name.startsWith('middleware.') || entry.name.endsWith('.d.ts');
|
|
250
|
+
if (!shouldIgnore) {
|
|
251
|
+
const ext = _path.default.extname(entry.name);
|
|
252
|
+
if (PLACEHOLDER_EXTENSIONS.has(ext)) {
|
|
253
|
+
const baseName = _path.default.basename(entry.name, ext);
|
|
254
|
+
const cssFilePath = _path.default.join(_path.default.dirname(entryPath), `${baseName}${DEFAULT_EXTENSION}`);
|
|
255
|
+
try {
|
|
256
|
+
_fs.default.writeFileSync(cssFilePath, '', {
|
|
257
|
+
flag: 'wx'
|
|
258
|
+
});
|
|
259
|
+
} catch (err) {
|
|
260
|
+
if (err.code !== 'EEXIST') {
|
|
261
|
+
throw err;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function shouldUseTurbopackConfig(nextConfig) {
|
|
272
|
+
const explicit = nextConfig.turbopack;
|
|
273
|
+
if (typeof explicit !== 'undefined') {
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
var _version$split$;
|
|
278
|
+
const pkgPath = require.resolve('next/package.json', {
|
|
279
|
+
paths: [process.cwd()]
|
|
280
|
+
});
|
|
281
|
+
const pkg = require(pkgPath);
|
|
282
|
+
const version = typeof pkg.version === 'string' ? pkg.version : '';
|
|
283
|
+
const major = Number.parseInt((_version$split$ = version.split('.')[0]) !== null && _version$split$ !== void 0 ? _version$split$ : '', 10);
|
|
284
|
+
return Number.isFinite(major) && major >= 16;
|
|
285
|
+
} catch {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function injectWywTurbopackRules(nextConfig, wywNext) {
|
|
290
|
+
var _wywNext$turbopackLoa;
|
|
291
|
+
const loader = require.resolve('@wyw-in-js/turbopack-loader');
|
|
292
|
+
const nextBabelPreset = require.resolve('next/babel', {
|
|
293
|
+
paths: [process.cwd()]
|
|
294
|
+
});
|
|
295
|
+
const userOptions = (_wywNext$turbopackLoa = wywNext.turbopackLoaderOptions) !== null && _wywNext$turbopackLoa !== void 0 ? _wywNext$turbopackLoa : {};
|
|
296
|
+
assertNoFunctions(userOptions, 'turbopackLoaderOptions');
|
|
297
|
+
const loaderOptions = {
|
|
298
|
+
babelOptions: {
|
|
299
|
+
presets: [nextBabelPreset]
|
|
300
|
+
},
|
|
301
|
+
sourceMap: process.env.NODE_ENV !== 'production',
|
|
302
|
+
...userOptions
|
|
303
|
+
};
|
|
304
|
+
const useTurbopackConfig = shouldUseTurbopackConfig(nextConfig);
|
|
305
|
+
const isNextBuild = process.argv.includes('build');
|
|
306
|
+
const isWebpackBuild = process.argv.includes('--webpack');
|
|
307
|
+
if (useTurbopackConfig && process.env.NODE_ENV === 'production' && isNextBuild && !isWebpackBuild) {
|
|
308
|
+
ensureTurbopackCssPlaceholders(process.cwd());
|
|
309
|
+
}
|
|
310
|
+
const ruleValue = useTurbopackConfig ? {
|
|
311
|
+
loaders: [{
|
|
312
|
+
loader,
|
|
313
|
+
options: loaderOptions
|
|
314
|
+
}],
|
|
315
|
+
condition: {
|
|
316
|
+
all: [{
|
|
317
|
+
not: 'foreign'
|
|
318
|
+
}, {
|
|
319
|
+
not: {
|
|
320
|
+
path: /(?:^|[\\/])middleware\.[jt]sx?$/
|
|
321
|
+
}
|
|
322
|
+
}]
|
|
323
|
+
}
|
|
324
|
+
} : [{
|
|
325
|
+
loader,
|
|
326
|
+
options: loaderOptions
|
|
327
|
+
}];
|
|
328
|
+
const wywRules = Object.fromEntries(DEFAULT_TURBO_RULE_KEYS.map(key => [key, ruleValue]));
|
|
329
|
+
if (useTurbopackConfig) {
|
|
330
|
+
const turbopackConfig = nextConfig.turbopack;
|
|
331
|
+
const userTurbopack = isPlainObject(turbopackConfig) ? turbopackConfig : {};
|
|
332
|
+
const userRules = isPlainObject(userTurbopack.rules) ? userTurbopack.rules : {};
|
|
333
|
+
return {
|
|
334
|
+
...nextConfig,
|
|
335
|
+
turbopack: {
|
|
336
|
+
...userTurbopack,
|
|
337
|
+
rules: {
|
|
338
|
+
...wywRules,
|
|
339
|
+
...userRules
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
const userExperimental = isPlainObject(nextConfig.experimental) ? nextConfig.experimental : {};
|
|
345
|
+
const userTurbo = isPlainObject(userExperimental.turbo) ? userExperimental.turbo : {};
|
|
346
|
+
const userRules = isPlainObject(userTurbo.rules) ? userTurbo.rules : {};
|
|
347
|
+
return {
|
|
348
|
+
...nextConfig,
|
|
349
|
+
experimental: {
|
|
350
|
+
...userExperimental,
|
|
351
|
+
turbo: {
|
|
352
|
+
...userTurbo,
|
|
353
|
+
rules: {
|
|
354
|
+
...wywRules,
|
|
355
|
+
...userRules
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function withWyw(nextConfig = {}, wywNext = {}) {
|
|
362
|
+
const userWebpack = nextConfig.webpack;
|
|
363
|
+
return {
|
|
364
|
+
...injectWywTurbopackRules(nextConfig, wywNext),
|
|
365
|
+
webpack(config, options) {
|
|
366
|
+
const resolvedConfig = typeof userWebpack === 'function' ? userWebpack(config, options) : config;
|
|
367
|
+
injectWywLoader(resolvedConfig, options, wywNext);
|
|
368
|
+
return resolvedConfig;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["_fs","_interopRequireDefault","require","_path","e","__esModule","default","DEFAULT_EXTENSION","DEFAULT_TURBO_RULE_KEYS","PLACEHOLDER_EXTENSIONS","Set","PLACEHOLDER_IGNORED_DIRS","isObject","value","isUseLoaderObject","item","loader","normalizeUseItems","use","list","Array","isArray","filter","Boolean","length","getLoaderName","isWywLoaderPath","includes","test","convertLoaderRuleToUseRule","rule","wywLoaderItem","alreadyInjected","isNextJsTranspileRule","some","needle","options","nextRule","Object","assign","undefined","traverseRules","rules","visitor","oneOf","escapeRegExp","replace","isPlainObject","proto","getPrototypeOf","prototype","assertNoFunctions","name","queue","path","seen","current","shift","Error","has","add","forEach","idx","push","entries","key","createWywCssModuleRule","baseRule","extensionSuffix","_normalizeUseItems","patchedUse","map","itemOptions","modules","nextModules","mode","getLocalIdent","_context","_localIdentName","localName","sideEffects","RegExp","ensureWywCssModuleRules","config","_config$module$rules","_config$module","module","expectedTestSource","alreadyPresent","candidate","source","candidateRule","isModuleCssRule","hasCssLoader","splice","injectWywLoader","nextOptions","wywNext","_wywNext$loaderOption","_wywNext$loaderOption2","_wywNext$loaderOption3","_wywNext$loaderOption4","_wywNext$loaderOption5","_wywNext$loaderOption6","_config$module$rules2","_config$module2","resolve","nextBabelPreset","paths","process","cwd","extension","loaderOptions","babelOptions","presets","cssImport","sourceMap","dev","loaders","l","ensureTurbopackCssPlaceholders","projectRoot","dir","pop","fs","readdirSync","withFileTypes","entry","entryPath","join","isDirectory","isFile","shouldIgnore","startsWith","endsWith","ext","extname","baseName","basename","cssFilePath","dirname","writeFileSync","flag","err","code","shouldUseTurbopackConfig","nextConfig","explicit","turbopack","_version$split$","pkgPath","pkg","version","major","Number","parseInt","split","isFinite","injectWywTurbopackRules","_wywNext$turbopackLoa","userOptions","turbopackLoaderOptions","env","NODE_ENV","useTurbopackConfig","isNextBuild","argv","isWebpackBuild","ruleValue","condition","all","not","wywRules","fromEntries","turbopackConfig","userTurbopack","userRules","userExperimental","experimental","userTurbo","turbo","withWyw","userWebpack","webpack","resolvedConfig"],"sources":["../src/index.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { LoaderOptions as WywWebpackLoaderOptions } from '@wyw-in-js/webpack-loader';\nimport type { NextConfig } from 'next';\nimport type { Configuration, RuleSetRule, RuleSetUseItem } from 'webpack';\n\nconst DEFAULT_EXTENSION = '.wyw-in-js.module.css';\n\nconst DEFAULT_TURBO_RULE_KEYS = ['*.js', '*.jsx', '*.ts', '*.tsx'];\n\nconst PLACEHOLDER_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx']);\nconst PLACEHOLDER_IGNORED_DIRS = new Set([\n '.git',\n '.next',\n '.turbo',\n 'node_modules',\n]);\n\nexport type WywNextPluginOptions = {\n loaderOptions?: Omit<WywWebpackLoaderOptions, 'extension' | 'sourceMap'> &\n Partial<Pick<WywWebpackLoaderOptions, 'extension' | 'sourceMap'>>;\n turbopackLoaderOptions?: Record<string, unknown>;\n};\n\ntype NextWebpackConfigFn = NonNullable<NextConfig['webpack']>;\ntype NextWebpackOptions = Parameters<NextWebpackConfigFn>[1];\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isUseLoaderObject(\n item: RuleSetUseItem\n): item is Exclude<RuleSetUseItem, string> & { loader: string } {\n return (\n isObject(item) &&\n typeof (item as Record<string, unknown>).loader === 'string'\n );\n}\n\nfunction normalizeUseItems(use: RuleSetRule['use']): RuleSetUseItem[] | null {\n if (!use) return null;\n if (typeof use === 'function') return null;\n\n const list = (Array.isArray(use) ? use : [use]).filter(Boolean);\n return list.length ? (list as RuleSetUseItem[]) : null;\n}\n\nfunction getLoaderName(item: RuleSetUseItem): string {\n if (typeof item === 'string') return item;\n if (isUseLoaderObject(item)) return item.loader;\n return '';\n}\n\nfunction isWywLoaderPath(loader: string) {\n return (\n loader.includes('@wyw-in-js/webpack-loader') ||\n /[\\\\/]webpack-loader[\\\\/]/.test(loader)\n );\n}\n\nfunction convertLoaderRuleToUseRule(\n rule: RuleSetRule,\n wywLoaderItem: RuleSetUseItem\n) {\n const { loader } = rule as { loader?: unknown };\n if (typeof loader !== 'string') return;\n\n const alreadyInjected = isWywLoaderPath(loader);\n if (alreadyInjected) return;\n\n const isNextJsTranspileRule = [\n 'next-swc-loader',\n 'next-babel-loader',\n 'babel-loader',\n ].some((needle) => loader.includes(needle));\n if (!isNextJsTranspileRule) return;\n\n const { options } = rule as { options?: unknown };\n\n const nextRule = rule as RuleSetRule & {\n loader?: unknown;\n options?: unknown;\n };\n\n delete nextRule.loader;\n delete nextRule.options;\n\n // Loader order is right-to-left. We want WyW to run first, so it should be last.\n Object.assign(nextRule, {\n use: [\n { loader, ...(options !== undefined ? { options } : {}) },\n wywLoaderItem,\n ],\n });\n}\n\nfunction traverseRules(rules: unknown[], visitor: (rule: RuleSetRule) => void) {\n for (const rule of rules) {\n if (rule && typeof rule === 'object') {\n visitor(rule as RuleSetRule);\n\n if (Array.isArray((rule as RuleSetRule).oneOf)) {\n traverseRules((rule as RuleSetRule).oneOf!, visitor);\n }\n if (Array.isArray((rule as RuleSetRule).rules)) {\n traverseRules((rule as RuleSetRule).rules!, visitor);\n }\n }\n }\n}\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (!isObject(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction assertNoFunctions(value: unknown, name: string) {\n const queue: Array<{ path: string; value: unknown }> = [\n { path: name, value },\n ];\n const seen = new Set<unknown>();\n\n while (queue.length) {\n const current = queue.shift()!;\n\n if (typeof current.value === 'function') {\n throw new Error(\n `${current.path} must be JSON-serializable (functions are not supported in Turbopack loader options). Use \"configFile\" to pass non-JSON config.`\n );\n }\n\n if (current.value === null) {\n // skip\n } else if (Array.isArray(current.value)) {\n if (!seen.has(current.value)) {\n seen.add(current.value);\n current.value.forEach((item, idx) =>\n queue.push({ path: `${current.path}[${idx}]`, value: item })\n );\n }\n } else if (isPlainObject(current.value)) {\n if (!seen.has(current.value)) {\n seen.add(current.value);\n Object.entries(current.value).forEach(([key, item]) =>\n queue.push({ path: `${current.path}.${key}`, value: item })\n );\n }\n }\n }\n}\n\nfunction createWywCssModuleRule(\n baseRule: RuleSetRule,\n extensionSuffix: string\n): RuleSetRule {\n const use = normalizeUseItems(baseRule.use) ?? [];\n\n const patchedUse = use.map((item) => {\n if (!isUseLoaderObject(item) || !item.loader.includes('css-loader')) {\n return item;\n }\n\n const itemOptions = (item as { options?: unknown }).options;\n if (!isObject(itemOptions)) {\n return item;\n }\n\n const { modules } = itemOptions as { modules?: unknown };\n if (!isObject(modules)) {\n return item;\n }\n\n const nextModules = {\n ...(modules as Record<string, unknown>),\n mode: 'global',\n getLocalIdent: (\n _context: unknown,\n _localIdentName: string,\n localName: string\n ) => localName,\n };\n\n return {\n ...item,\n options: {\n ...(itemOptions as Record<string, unknown>),\n modules: nextModules,\n },\n };\n });\n\n const nextRule: RuleSetRule = {\n ...baseRule,\n sideEffects: true,\n test: new RegExp(`${escapeRegExp(extensionSuffix)}$`),\n use: patchedUse,\n };\n\n return nextRule;\n}\n\nfunction ensureWywCssModuleRules(\n config: Configuration,\n extensionSuffix: string\n) {\n traverseRules(config.module?.rules ?? [], (rule) => {\n if (!Array.isArray(rule.oneOf) || rule.oneOf.length === 0) {\n return;\n }\n\n const expectedTestSource = `${escapeRegExp(extensionSuffix)}$`;\n\n const alreadyPresent = rule.oneOf.some((candidate) => {\n if (!candidate || typeof candidate !== 'object') return false;\n\n const { test } = candidate as RuleSetRule;\n return test instanceof RegExp && test.source === expectedTestSource;\n });\n\n if (alreadyPresent) {\n return;\n }\n\n const oneOf = rule.oneOf as unknown[];\n for (let idx = 0; idx < oneOf.length; idx += 1) {\n const candidate = oneOf[idx];\n if (candidate && typeof candidate === 'object') {\n const candidateRule = candidate as RuleSetRule;\n const { test } = candidateRule;\n\n const isModuleCssRule =\n test instanceof RegExp && test.source.includes('\\\\.module\\\\.css');\n\n if (isModuleCssRule) {\n const use = normalizeUseItems(candidateRule.use);\n if (use) {\n const hasCssLoader = use.some(\n (item) =>\n isUseLoaderObject(item) && item.loader.includes('css-loader')\n );\n if (hasCssLoader) {\n oneOf.splice(\n idx,\n 0,\n createWywCssModuleRule(candidateRule, extensionSuffix)\n );\n break;\n }\n }\n }\n }\n }\n });\n}\n\nfunction injectWywLoader(\n config: Configuration,\n nextOptions: NextWebpackOptions,\n wywNext: WywNextPluginOptions\n) {\n const loader = require.resolve('@wyw-in-js/webpack-loader');\n const nextBabelPreset = require.resolve('next/babel', {\n paths: [process.cwd()],\n });\n\n const extension = wywNext.loaderOptions?.extension ?? DEFAULT_EXTENSION;\n const babelOptions = wywNext.loaderOptions?.babelOptions ?? {\n presets: [nextBabelPreset],\n };\n\n const loaderOptions = {\n cssImport: 'import',\n ...wywNext.loaderOptions,\n babelOptions,\n extension,\n sourceMap: wywNext.loaderOptions?.sourceMap ?? nextOptions.dev,\n } satisfies WywWebpackLoaderOptions;\n\n const wywLoaderItem: RuleSetUseItem = {\n loader,\n options: loaderOptions,\n };\n\n traverseRules(config.module?.rules ?? [], (rule) => {\n convertLoaderRuleToUseRule(rule, wywLoaderItem);\n\n const use = normalizeUseItems(rule.use);\n if (!use) return;\n\n const loaders = use.map(getLoaderName);\n\n const alreadyInjected = loaders.some(\n (l) => l === loader || isWywLoaderPath(l)\n );\n if (alreadyInjected) return;\n\n const isNextJsTranspileRule = loaders.some((l) =>\n ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some((needle) =>\n l.includes(needle)\n )\n );\n if (!isNextJsTranspileRule) return;\n\n // Loader order is right-to-left. We want WyW to run first, so it should be last.\n Object.assign(rule, { use: [...use, wywLoaderItem] });\n });\n\n ensureWywCssModuleRules(config, extension);\n}\n\nfunction ensureTurbopackCssPlaceholders(projectRoot: string) {\n const queue: string[] = [projectRoot];\n\n while (queue.length) {\n const dir = queue.pop()!;\n let entries: fs.Dirent[];\n\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n entries = [];\n }\n\n for (const entry of entries) {\n if (entry.name !== '.' && entry.name !== '..') {\n const entryPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!PLACEHOLDER_IGNORED_DIRS.has(entry.name)) {\n queue.push(entryPath);\n }\n } else if (entry.isFile()) {\n const shouldIgnore =\n entry.name.startsWith('middleware.') ||\n entry.name.endsWith('.d.ts');\n\n if (!shouldIgnore) {\n const ext = path.extname(entry.name);\n if (PLACEHOLDER_EXTENSIONS.has(ext)) {\n const baseName = path.basename(entry.name, ext);\n const cssFilePath = path.join(\n path.dirname(entryPath),\n `${baseName}${DEFAULT_EXTENSION}`\n );\n\n try {\n fs.writeFileSync(cssFilePath, '', { flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw err;\n }\n }\n }\n }\n }\n }\n }\n }\n}\n\nfunction shouldUseTurbopackConfig(nextConfig: NextConfig) {\n const explicit = (nextConfig as unknown as Record<string, unknown>).turbopack;\n if (typeof explicit !== 'undefined') {\n return true;\n }\n\n try {\n const pkgPath = require.resolve('next/package.json', {\n paths: [process.cwd()],\n });\n const pkg = require(pkgPath) as { version?: unknown };\n const version = typeof pkg.version === 'string' ? pkg.version : '';\n const major = Number.parseInt(version.split('.')[0] ?? '', 10);\n return Number.isFinite(major) && major >= 16;\n } catch {\n return false;\n }\n}\n\nfunction injectWywTurbopackRules(\n nextConfig: NextConfig,\n wywNext: WywNextPluginOptions\n): NextConfig {\n const loader = require.resolve('@wyw-in-js/turbopack-loader');\n const nextBabelPreset = require.resolve('next/babel', {\n paths: [process.cwd()],\n });\n\n const userOptions = wywNext.turbopackLoaderOptions ?? {};\n\n assertNoFunctions(userOptions, 'turbopackLoaderOptions');\n\n const loaderOptions = {\n babelOptions: { presets: [nextBabelPreset] },\n sourceMap: process.env.NODE_ENV !== 'production',\n ...userOptions,\n };\n\n const useTurbopackConfig = shouldUseTurbopackConfig(nextConfig);\n\n const isNextBuild = process.argv.includes('build');\n const isWebpackBuild = process.argv.includes('--webpack');\n\n if (\n useTurbopackConfig &&\n process.env.NODE_ENV === 'production' &&\n isNextBuild &&\n !isWebpackBuild\n ) {\n ensureTurbopackCssPlaceholders(process.cwd());\n }\n\n const ruleValue = useTurbopackConfig\n ? {\n loaders: [{ loader, options: loaderOptions }],\n condition: {\n all: [\n { not: 'foreign' },\n { not: { path: /(?:^|[\\\\/])middleware\\.[jt]sx?$/ } },\n ],\n },\n }\n : [{ loader, options: loaderOptions }];\n\n const wywRules = Object.fromEntries(\n DEFAULT_TURBO_RULE_KEYS.map((key) => [key, ruleValue])\n );\n\n if (useTurbopackConfig) {\n const turbopackConfig = (nextConfig as unknown as Record<string, unknown>)\n .turbopack;\n const userTurbopack = isPlainObject(turbopackConfig) ? turbopackConfig : {};\n\n const userRules = isPlainObject(userTurbopack.rules)\n ? (userTurbopack.rules as Record<string, unknown>)\n : {};\n\n return {\n ...nextConfig,\n turbopack: {\n ...userTurbopack,\n rules: {\n ...wywRules,\n ...userRules,\n },\n },\n } as NextConfig;\n }\n\n const userExperimental = isPlainObject(nextConfig.experimental)\n ? (nextConfig.experimental as Record<string, unknown>)\n : {};\n\n const userTurbo = isPlainObject(userExperimental.turbo)\n ? (userExperimental.turbo as Record<string, unknown>)\n : {};\n\n const userRules = isPlainObject(userTurbo.rules)\n ? (userTurbo.rules as Record<string, unknown>)\n : {};\n\n return {\n ...nextConfig,\n experimental: {\n ...userExperimental,\n turbo: {\n ...userTurbo,\n rules: {\n ...wywRules,\n ...userRules,\n },\n },\n },\n } as NextConfig;\n}\n\nexport function withWyw(\n nextConfig: NextConfig = {},\n wywNext: WywNextPluginOptions = {}\n): NextConfig {\n const userWebpack = nextConfig.webpack;\n\n return {\n ...injectWywTurbopackRules(nextConfig, wywNext),\n webpack(config: Configuration, options: NextWebpackOptions) {\n const resolvedConfig =\n typeof userWebpack === 'function'\n ? userWebpack(config, options)\n : config;\n\n injectWywLoader(resolvedConfig, options, wywNext);\n\n return resolvedConfig;\n },\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wyw-in-js/nextjs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@wyw-in-js/turbopack-loader": "workspace:*",
|
|
6
|
+
"@wyw-in-js/webpack-loader": "workspace:*"
|
|
7
|
+
},
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@types/node": "^16.18.55",
|
|
10
|
+
"@wyw-in-js/babel-config": "workspace:*",
|
|
11
|
+
"@wyw-in-js/eslint-config": "workspace:*",
|
|
12
|
+
"@wyw-in-js/ts-config": "workspace:*",
|
|
13
|
+
"next": ">=13.0.0",
|
|
14
|
+
"webpack": "^5.76.0"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=16.0.0"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
"import": "./esm/index.mjs",
|
|
21
|
+
"require": "./lib/index.js",
|
|
22
|
+
"types": "./types/index.d.ts"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"esm/",
|
|
26
|
+
"lib/",
|
|
27
|
+
"types/"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"main": "lib/index.js",
|
|
31
|
+
"module": "esm/index.mjs",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"next": ">=13.0.0",
|
|
34
|
+
"webpack": "^5.76.0"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build:esm": "babel src --out-dir esm --out-file-extension .mjs --extensions '.js,.jsx,.ts,.tsx' --source-maps --delete-dir-on-start",
|
|
41
|
+
"build:lib": "cross-env NODE_ENV=legacy babel src --out-dir lib --extensions '.js,.jsx,.ts,.tsx' --source-maps --delete-dir-on-start",
|
|
42
|
+
"build:types": "tsc --project ./tsconfig.lib.json --baseUrl . --rootDir ./src",
|
|
43
|
+
"lint": "eslint --ext .js,.ts .",
|
|
44
|
+
"test": "bun test src"
|
|
45
|
+
},
|
|
46
|
+
"types": "types/index.d.ts"
|
|
47
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LoaderOptions as WywWebpackLoaderOptions } from '@wyw-in-js/webpack-loader';
|
|
2
|
+
import type { NextConfig } from 'next';
|
|
3
|
+
export type WywNextPluginOptions = {
|
|
4
|
+
loaderOptions?: Omit<WywWebpackLoaderOptions, 'extension' | 'sourceMap'> & Partial<Pick<WywWebpackLoaderOptions, 'extension' | 'sourceMap'>>;
|
|
5
|
+
turbopackLoaderOptions?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
export declare function withWyw(nextConfig?: NextConfig, wywNext?: WywNextPluginOptions): NextConfig;
|
package/types/index.js
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.withWyw = withWyw;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const DEFAULT_EXTENSION = '.wyw-in-js.module.css';
|
|
10
|
+
const DEFAULT_TURBO_RULE_KEYS = ['*.js', '*.jsx', '*.ts', '*.tsx'];
|
|
11
|
+
const PLACEHOLDER_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx']);
|
|
12
|
+
const PLACEHOLDER_IGNORED_DIRS = new Set([
|
|
13
|
+
'.git',
|
|
14
|
+
'.next',
|
|
15
|
+
'.turbo',
|
|
16
|
+
'node_modules',
|
|
17
|
+
]);
|
|
18
|
+
function isObject(value) {
|
|
19
|
+
return typeof value === 'object' && value !== null;
|
|
20
|
+
}
|
|
21
|
+
function isUseLoaderObject(item) {
|
|
22
|
+
return (isObject(item) &&
|
|
23
|
+
typeof item.loader === 'string');
|
|
24
|
+
}
|
|
25
|
+
function normalizeUseItems(use) {
|
|
26
|
+
if (!use)
|
|
27
|
+
return null;
|
|
28
|
+
if (typeof use === 'function')
|
|
29
|
+
return null;
|
|
30
|
+
const list = (Array.isArray(use) ? use : [use]).filter(Boolean);
|
|
31
|
+
return list.length ? list : null;
|
|
32
|
+
}
|
|
33
|
+
function getLoaderName(item) {
|
|
34
|
+
if (typeof item === 'string')
|
|
35
|
+
return item;
|
|
36
|
+
if (isUseLoaderObject(item))
|
|
37
|
+
return item.loader;
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
function isWywLoaderPath(loader) {
|
|
41
|
+
return (loader.includes('@wyw-in-js/webpack-loader') ||
|
|
42
|
+
/[\\/]webpack-loader[\\/]/.test(loader));
|
|
43
|
+
}
|
|
44
|
+
function convertLoaderRuleToUseRule(rule, wywLoaderItem) {
|
|
45
|
+
const { loader } = rule;
|
|
46
|
+
if (typeof loader !== 'string')
|
|
47
|
+
return;
|
|
48
|
+
const alreadyInjected = isWywLoaderPath(loader);
|
|
49
|
+
if (alreadyInjected)
|
|
50
|
+
return;
|
|
51
|
+
const isNextJsTranspileRule = [
|
|
52
|
+
'next-swc-loader',
|
|
53
|
+
'next-babel-loader',
|
|
54
|
+
'babel-loader',
|
|
55
|
+
].some((needle) => loader.includes(needle));
|
|
56
|
+
if (!isNextJsTranspileRule)
|
|
57
|
+
return;
|
|
58
|
+
const { options } = rule;
|
|
59
|
+
const nextRule = rule;
|
|
60
|
+
delete nextRule.loader;
|
|
61
|
+
delete nextRule.options;
|
|
62
|
+
// Loader order is right-to-left. We want WyW to run first, so it should be last.
|
|
63
|
+
Object.assign(nextRule, {
|
|
64
|
+
use: [
|
|
65
|
+
{ loader, ...(options !== undefined ? { options } : {}) },
|
|
66
|
+
wywLoaderItem,
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function traverseRules(rules, visitor) {
|
|
71
|
+
for (const rule of rules) {
|
|
72
|
+
if (rule && typeof rule === 'object') {
|
|
73
|
+
visitor(rule);
|
|
74
|
+
if (Array.isArray(rule.oneOf)) {
|
|
75
|
+
traverseRules(rule.oneOf, visitor);
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(rule.rules)) {
|
|
78
|
+
traverseRules(rule.rules, visitor);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function escapeRegExp(value) {
|
|
84
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
85
|
+
}
|
|
86
|
+
function isPlainObject(value) {
|
|
87
|
+
if (!isObject(value))
|
|
88
|
+
return false;
|
|
89
|
+
const proto = Object.getPrototypeOf(value);
|
|
90
|
+
return proto === Object.prototype || proto === null;
|
|
91
|
+
}
|
|
92
|
+
function assertNoFunctions(value, name) {
|
|
93
|
+
const queue = [
|
|
94
|
+
{ path: name, value },
|
|
95
|
+
];
|
|
96
|
+
const seen = new Set();
|
|
97
|
+
while (queue.length) {
|
|
98
|
+
const current = queue.shift();
|
|
99
|
+
if (typeof current.value === 'function') {
|
|
100
|
+
throw new Error(`${current.path} must be JSON-serializable (functions are not supported in Turbopack loader options). Use "configFile" to pass non-JSON config.`);
|
|
101
|
+
}
|
|
102
|
+
if (current.value === null) {
|
|
103
|
+
// skip
|
|
104
|
+
}
|
|
105
|
+
else if (Array.isArray(current.value)) {
|
|
106
|
+
if (!seen.has(current.value)) {
|
|
107
|
+
seen.add(current.value);
|
|
108
|
+
current.value.forEach((item, idx) => queue.push({ path: `${current.path}[${idx}]`, value: item }));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (isPlainObject(current.value)) {
|
|
112
|
+
if (!seen.has(current.value)) {
|
|
113
|
+
seen.add(current.value);
|
|
114
|
+
Object.entries(current.value).forEach(([key, item]) => queue.push({ path: `${current.path}.${key}`, value: item }));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function createWywCssModuleRule(baseRule, extensionSuffix) {
|
|
120
|
+
const use = normalizeUseItems(baseRule.use) ?? [];
|
|
121
|
+
const patchedUse = use.map((item) => {
|
|
122
|
+
if (!isUseLoaderObject(item) || !item.loader.includes('css-loader')) {
|
|
123
|
+
return item;
|
|
124
|
+
}
|
|
125
|
+
const itemOptions = item.options;
|
|
126
|
+
if (!isObject(itemOptions)) {
|
|
127
|
+
return item;
|
|
128
|
+
}
|
|
129
|
+
const { modules } = itemOptions;
|
|
130
|
+
if (!isObject(modules)) {
|
|
131
|
+
return item;
|
|
132
|
+
}
|
|
133
|
+
const nextModules = {
|
|
134
|
+
...modules,
|
|
135
|
+
mode: 'global',
|
|
136
|
+
getLocalIdent: (_context, _localIdentName, localName) => localName,
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
...item,
|
|
140
|
+
options: {
|
|
141
|
+
...itemOptions,
|
|
142
|
+
modules: nextModules,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
const nextRule = {
|
|
147
|
+
...baseRule,
|
|
148
|
+
sideEffects: true,
|
|
149
|
+
test: new RegExp(`${escapeRegExp(extensionSuffix)}$`),
|
|
150
|
+
use: patchedUse,
|
|
151
|
+
};
|
|
152
|
+
return nextRule;
|
|
153
|
+
}
|
|
154
|
+
function ensureWywCssModuleRules(config, extensionSuffix) {
|
|
155
|
+
traverseRules(config.module?.rules ?? [], (rule) => {
|
|
156
|
+
if (!Array.isArray(rule.oneOf) || rule.oneOf.length === 0) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const expectedTestSource = `${escapeRegExp(extensionSuffix)}$`;
|
|
160
|
+
const alreadyPresent = rule.oneOf.some((candidate) => {
|
|
161
|
+
if (!candidate || typeof candidate !== 'object')
|
|
162
|
+
return false;
|
|
163
|
+
const { test } = candidate;
|
|
164
|
+
return test instanceof RegExp && test.source === expectedTestSource;
|
|
165
|
+
});
|
|
166
|
+
if (alreadyPresent) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const oneOf = rule.oneOf;
|
|
170
|
+
for (let idx = 0; idx < oneOf.length; idx += 1) {
|
|
171
|
+
const candidate = oneOf[idx];
|
|
172
|
+
if (candidate && typeof candidate === 'object') {
|
|
173
|
+
const candidateRule = candidate;
|
|
174
|
+
const { test } = candidateRule;
|
|
175
|
+
const isModuleCssRule = test instanceof RegExp && test.source.includes('\\.module\\.css');
|
|
176
|
+
if (isModuleCssRule) {
|
|
177
|
+
const use = normalizeUseItems(candidateRule.use);
|
|
178
|
+
if (use) {
|
|
179
|
+
const hasCssLoader = use.some((item) => isUseLoaderObject(item) && item.loader.includes('css-loader'));
|
|
180
|
+
if (hasCssLoader) {
|
|
181
|
+
oneOf.splice(idx, 0, createWywCssModuleRule(candidateRule, extensionSuffix));
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function injectWywLoader(config, nextOptions, wywNext) {
|
|
191
|
+
const loader = require.resolve('@wyw-in-js/webpack-loader');
|
|
192
|
+
const nextBabelPreset = require.resolve('next/babel', {
|
|
193
|
+
paths: [process.cwd()],
|
|
194
|
+
});
|
|
195
|
+
const extension = wywNext.loaderOptions?.extension ?? DEFAULT_EXTENSION;
|
|
196
|
+
const babelOptions = wywNext.loaderOptions?.babelOptions ?? {
|
|
197
|
+
presets: [nextBabelPreset],
|
|
198
|
+
};
|
|
199
|
+
const loaderOptions = {
|
|
200
|
+
cssImport: 'import',
|
|
201
|
+
...wywNext.loaderOptions,
|
|
202
|
+
babelOptions,
|
|
203
|
+
extension,
|
|
204
|
+
sourceMap: wywNext.loaderOptions?.sourceMap ?? nextOptions.dev,
|
|
205
|
+
};
|
|
206
|
+
const wywLoaderItem = {
|
|
207
|
+
loader,
|
|
208
|
+
options: loaderOptions,
|
|
209
|
+
};
|
|
210
|
+
traverseRules(config.module?.rules ?? [], (rule) => {
|
|
211
|
+
convertLoaderRuleToUseRule(rule, wywLoaderItem);
|
|
212
|
+
const use = normalizeUseItems(rule.use);
|
|
213
|
+
if (!use)
|
|
214
|
+
return;
|
|
215
|
+
const loaders = use.map(getLoaderName);
|
|
216
|
+
const alreadyInjected = loaders.some((l) => l === loader || isWywLoaderPath(l));
|
|
217
|
+
if (alreadyInjected)
|
|
218
|
+
return;
|
|
219
|
+
const isNextJsTranspileRule = loaders.some((l) => ['next-swc-loader', 'next-babel-loader', 'babel-loader'].some((needle) => l.includes(needle)));
|
|
220
|
+
if (!isNextJsTranspileRule)
|
|
221
|
+
return;
|
|
222
|
+
// Loader order is right-to-left. We want WyW to run first, so it should be last.
|
|
223
|
+
Object.assign(rule, { use: [...use, wywLoaderItem] });
|
|
224
|
+
});
|
|
225
|
+
ensureWywCssModuleRules(config, extension);
|
|
226
|
+
}
|
|
227
|
+
function ensureTurbopackCssPlaceholders(projectRoot) {
|
|
228
|
+
const queue = [projectRoot];
|
|
229
|
+
while (queue.length) {
|
|
230
|
+
const dir = queue.pop();
|
|
231
|
+
let entries;
|
|
232
|
+
try {
|
|
233
|
+
entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
entries = [];
|
|
237
|
+
}
|
|
238
|
+
for (const entry of entries) {
|
|
239
|
+
if (entry.name !== '.' && entry.name !== '..') {
|
|
240
|
+
const entryPath = path_1.default.join(dir, entry.name);
|
|
241
|
+
if (entry.isDirectory()) {
|
|
242
|
+
if (!PLACEHOLDER_IGNORED_DIRS.has(entry.name)) {
|
|
243
|
+
queue.push(entryPath);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else if (entry.isFile()) {
|
|
247
|
+
const shouldIgnore = entry.name.startsWith('middleware.') ||
|
|
248
|
+
entry.name.endsWith('.d.ts');
|
|
249
|
+
if (!shouldIgnore) {
|
|
250
|
+
const ext = path_1.default.extname(entry.name);
|
|
251
|
+
if (PLACEHOLDER_EXTENSIONS.has(ext)) {
|
|
252
|
+
const baseName = path_1.default.basename(entry.name, ext);
|
|
253
|
+
const cssFilePath = path_1.default.join(path_1.default.dirname(entryPath), `${baseName}${DEFAULT_EXTENSION}`);
|
|
254
|
+
try {
|
|
255
|
+
fs_1.default.writeFileSync(cssFilePath, '', { flag: 'wx' });
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
if (err.code !== 'EEXIST') {
|
|
259
|
+
throw err;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function shouldUseTurbopackConfig(nextConfig) {
|
|
270
|
+
const explicit = nextConfig.turbopack;
|
|
271
|
+
if (typeof explicit !== 'undefined') {
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
const pkgPath = require.resolve('next/package.json', {
|
|
276
|
+
paths: [process.cwd()],
|
|
277
|
+
});
|
|
278
|
+
const pkg = require(pkgPath);
|
|
279
|
+
const version = typeof pkg.version === 'string' ? pkg.version : '';
|
|
280
|
+
const major = Number.parseInt(version.split('.')[0] ?? '', 10);
|
|
281
|
+
return Number.isFinite(major) && major >= 16;
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function injectWywTurbopackRules(nextConfig, wywNext) {
|
|
288
|
+
const loader = require.resolve('@wyw-in-js/turbopack-loader');
|
|
289
|
+
const nextBabelPreset = require.resolve('next/babel', {
|
|
290
|
+
paths: [process.cwd()],
|
|
291
|
+
});
|
|
292
|
+
const userOptions = wywNext.turbopackLoaderOptions ?? {};
|
|
293
|
+
assertNoFunctions(userOptions, 'turbopackLoaderOptions');
|
|
294
|
+
const loaderOptions = {
|
|
295
|
+
babelOptions: { presets: [nextBabelPreset] },
|
|
296
|
+
sourceMap: process.env.NODE_ENV !== 'production',
|
|
297
|
+
...userOptions,
|
|
298
|
+
};
|
|
299
|
+
const useTurbopackConfig = shouldUseTurbopackConfig(nextConfig);
|
|
300
|
+
const isNextBuild = process.argv.includes('build');
|
|
301
|
+
const isWebpackBuild = process.argv.includes('--webpack');
|
|
302
|
+
if (useTurbopackConfig &&
|
|
303
|
+
process.env.NODE_ENV === 'production' &&
|
|
304
|
+
isNextBuild &&
|
|
305
|
+
!isWebpackBuild) {
|
|
306
|
+
ensureTurbopackCssPlaceholders(process.cwd());
|
|
307
|
+
}
|
|
308
|
+
const ruleValue = useTurbopackConfig
|
|
309
|
+
? {
|
|
310
|
+
loaders: [{ loader, options: loaderOptions }],
|
|
311
|
+
condition: {
|
|
312
|
+
all: [
|
|
313
|
+
{ not: 'foreign' },
|
|
314
|
+
{ not: { path: /(?:^|[\\/])middleware\.[jt]sx?$/ } },
|
|
315
|
+
],
|
|
316
|
+
},
|
|
317
|
+
}
|
|
318
|
+
: [{ loader, options: loaderOptions }];
|
|
319
|
+
const wywRules = Object.fromEntries(DEFAULT_TURBO_RULE_KEYS.map((key) => [key, ruleValue]));
|
|
320
|
+
if (useTurbopackConfig) {
|
|
321
|
+
const turbopackConfig = nextConfig
|
|
322
|
+
.turbopack;
|
|
323
|
+
const userTurbopack = isPlainObject(turbopackConfig) ? turbopackConfig : {};
|
|
324
|
+
const userRules = isPlainObject(userTurbopack.rules)
|
|
325
|
+
? userTurbopack.rules
|
|
326
|
+
: {};
|
|
327
|
+
return {
|
|
328
|
+
...nextConfig,
|
|
329
|
+
turbopack: {
|
|
330
|
+
...userTurbopack,
|
|
331
|
+
rules: {
|
|
332
|
+
...wywRules,
|
|
333
|
+
...userRules,
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
const userExperimental = isPlainObject(nextConfig.experimental)
|
|
339
|
+
? nextConfig.experimental
|
|
340
|
+
: {};
|
|
341
|
+
const userTurbo = isPlainObject(userExperimental.turbo)
|
|
342
|
+
? userExperimental.turbo
|
|
343
|
+
: {};
|
|
344
|
+
const userRules = isPlainObject(userTurbo.rules)
|
|
345
|
+
? userTurbo.rules
|
|
346
|
+
: {};
|
|
347
|
+
return {
|
|
348
|
+
...nextConfig,
|
|
349
|
+
experimental: {
|
|
350
|
+
...userExperimental,
|
|
351
|
+
turbo: {
|
|
352
|
+
...userTurbo,
|
|
353
|
+
rules: {
|
|
354
|
+
...wywRules,
|
|
355
|
+
...userRules,
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function withWyw(nextConfig = {}, wywNext = {}) {
|
|
362
|
+
const userWebpack = nextConfig.webpack;
|
|
363
|
+
return {
|
|
364
|
+
...injectWywTurbopackRules(nextConfig, wywNext),
|
|
365
|
+
webpack(config, options) {
|
|
366
|
+
const resolvedConfig = typeof userWebpack === 'function'
|
|
367
|
+
? userWebpack(config, options)
|
|
368
|
+
: config;
|
|
369
|
+
injectWywLoader(resolvedConfig, options, wywNext);
|
|
370
|
+
return resolvedConfig;
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
}
|