@vanilla-extract/next-plugin 2.4.17 → 2.5.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.
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin/next';
|
|
2
2
|
import { NextConfig } from 'next/dist/server/config-shared';
|
|
3
3
|
|
|
4
|
-
type PluginOptions = ConstructorParameters<typeof VanillaExtractPlugin>[0]
|
|
4
|
+
type PluginOptions = ConstructorParameters<typeof VanillaExtractPlugin>[0] & {
|
|
5
|
+
unstable_turbopack?: {
|
|
6
|
+
glob?: string[];
|
|
7
|
+
/**
|
|
8
|
+
* controls whether we attempt to configure turbopack
|
|
9
|
+
* auto: enable only when Next >= 16.0.0
|
|
10
|
+
* on: force enable regardless of detected Next version
|
|
11
|
+
* off: never configure turbopack, webpack only
|
|
12
|
+
*/
|
|
13
|
+
mode?: 'auto' | 'on' | 'off';
|
|
14
|
+
};
|
|
15
|
+
};
|
|
5
16
|
declare const createVanillaExtractPlugin: (pluginOptions?: PluginOptions) => (nextConfig?: NextConfig) => NextConfig;
|
|
6
17
|
|
|
7
18
|
export { createVanillaExtractPlugin };
|
|
@@ -9,11 +9,33 @@ var findPagesDir = require('next/dist/lib/find-pages-dir');
|
|
|
9
9
|
var css = require('next/dist/build/webpack/config/blocks/css');
|
|
10
10
|
var fileResolve = require('next/dist/build/webpack/config/blocks/css/loaders/file-resolve');
|
|
11
11
|
var node_module = require('node:module');
|
|
12
|
+
var path = require('node:path');
|
|
13
|
+
var semver = require('semver');
|
|
12
14
|
|
|
13
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
14
16
|
|
|
17
|
+
function _interopNamespace(e) {
|
|
18
|
+
if (e && e.__esModule) return e;
|
|
19
|
+
var n = Object.create(null);
|
|
20
|
+
if (e) {
|
|
21
|
+
Object.keys(e).forEach(function (k) {
|
|
22
|
+
if (k !== 'default') {
|
|
23
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
24
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return e[k]; }
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
n["default"] = e;
|
|
32
|
+
return Object.freeze(n);
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
var browserslist__default = /*#__PURE__*/_interopDefault(browserslist);
|
|
16
36
|
var NextMiniCssExtractPluginDefault__default = /*#__PURE__*/_interopDefault(NextMiniCssExtractPluginDefault);
|
|
37
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
38
|
+
var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
17
39
|
|
|
18
40
|
// @ts-expect-error
|
|
19
41
|
const require$1 = node_module.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('dist/vanilla-extract-next-plugin.cjs.dev.js', document.baseURI).href)));
|
|
@@ -113,77 +135,143 @@ const getVanillaExtractCssLoaders = (options, assetPrefix, hasAppDir) => {
|
|
|
113
135
|
return loaders;
|
|
114
136
|
};
|
|
115
137
|
const createVanillaExtractPlugin = (pluginOptions = {}) => {
|
|
116
|
-
return (nextConfig = {}) =>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
138
|
+
return (nextConfig = {}) => {
|
|
139
|
+
const {
|
|
140
|
+
unstable_turbopack: turbopackOptions = {},
|
|
141
|
+
...webpackPluginOptions
|
|
142
|
+
} = pluginOptions;
|
|
143
|
+
const {
|
|
144
|
+
mode: turbopackMode = 'off',
|
|
145
|
+
glob: turbopackGlob = ['**/*.css.{js,cjs,mjs,jsx,ts,tsx}']
|
|
146
|
+
} = turbopackOptions;
|
|
147
|
+
// detect Next version and decide whether to configure turbopack
|
|
148
|
+
const nextVersion = (() => {
|
|
149
|
+
try {
|
|
150
|
+
// resolve from the consumer app's cwd, not this package
|
|
151
|
+
const requireFromCwd = node_module.createRequire(path__namespace.join(process.cwd(), 'package.json'));
|
|
152
|
+
const pkg = requireFromCwd('next/package.json');
|
|
153
|
+
return (pkg === null || pkg === void 0 ? void 0 : pkg.version) ?? null;
|
|
154
|
+
} catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
})();
|
|
158
|
+
const coerced = nextVersion ? semver__default["default"].coerce(nextVersion) : null;
|
|
159
|
+
const supportsTurbopackRules = !!coerced && semver__default["default"].gte(coerced, '16.0.0');
|
|
160
|
+
const enableTurbopack = turbopackMode === 'on' || turbopackMode === 'auto' && supportsTurbopackRules;
|
|
161
|
+
if (turbopackMode === 'on' && !supportsTurbopackRules) {
|
|
162
|
+
console.warn(`[@vanilla-extract/next-plugin] Turbopack is configured but does not seem supported. Expected Next.js >= 16.0.0, got ${nextVersion}`);
|
|
163
|
+
}
|
|
164
|
+
let turbopack;
|
|
165
|
+
if (enableTurbopack) {
|
|
166
|
+
turbopack = {
|
|
167
|
+
...(nextConfig.turbopack || {})
|
|
168
|
+
};
|
|
169
|
+
if (turbopackGlob.some(glob => {
|
|
170
|
+
var _turbopack$rules;
|
|
171
|
+
return (_turbopack$rules = turbopack.rules) === null || _turbopack$rules === void 0 ? void 0 : _turbopack$rules[glob];
|
|
172
|
+
})) {
|
|
173
|
+
throw new Error('Vanilla extract could not be applied automatically due to conflicting turbopack rules');
|
|
174
|
+
}
|
|
175
|
+
const vanillaExtractRule = {
|
|
176
|
+
as: '*.js',
|
|
177
|
+
loaders: [{
|
|
178
|
+
loader: require$1.resolve('@vanilla-extract/turbopack-plugin'),
|
|
179
|
+
options: {
|
|
180
|
+
nextEnv: nextConfig.env ?? null,
|
|
181
|
+
outputCss: pluginOptions.outputCss ?? null,
|
|
182
|
+
identifiers: pluginOptions.identifiers ?? null
|
|
183
|
+
}
|
|
184
|
+
}]
|
|
185
|
+
};
|
|
186
|
+
const vanillaExtractCssRule = {
|
|
187
|
+
as: '*.css',
|
|
188
|
+
loaders: [require$1.resolve('@vanilla-extract/turbopack-plugin')]
|
|
189
|
+
};
|
|
190
|
+
turbopack.rules = {
|
|
191
|
+
...(turbopack.rules || {}),
|
|
192
|
+
...Object.fromEntries(turbopackGlob.map(glob => [glob, vanillaExtractRule])),
|
|
193
|
+
'vanilla.virtual.css': vanillaExtractCssRule
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const baseConfig = {
|
|
197
|
+
...nextConfig,
|
|
198
|
+
webpack(config, options) {
|
|
199
|
+
var _resolvedNextConfig$e;
|
|
200
|
+
const {
|
|
201
|
+
dir,
|
|
202
|
+
dev,
|
|
203
|
+
config: resolvedNextConfig
|
|
204
|
+
} = options;
|
|
205
|
+
|
|
206
|
+
// https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336
|
|
207
|
+
// https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626
|
|
208
|
+
// https://github.com/vercel/next.js/pull/43916
|
|
209
|
+
// on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object
|
|
210
|
+
const findPagesDirResult = findPagesDir.findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);
|
|
211
|
+
// Skip nextConfig check since appDir is stable feature after Next.js 13.4
|
|
212
|
+
const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir);
|
|
213
|
+
const outputCss = true;
|
|
214
|
+
|
|
215
|
+
// https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21
|
|
216
|
+
const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
|
|
217
|
+
test
|
|
218
|
+
}) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
|
|
219
|
+
|
|
220
|
+
// https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190
|
|
221
|
+
cssRules.unshift({
|
|
222
|
+
test: /vanilla\.virtual\.css/i,
|
|
223
|
+
sideEffects: true,
|
|
224
|
+
use: getVanillaExtractCssLoaders(options, resolvedNextConfig.assetPrefix, hasAppDir)
|
|
225
|
+
});
|
|
146
226
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
227
|
+
// vanilla-extract need to emit the css file on both server and client, both during the
|
|
228
|
+
// development and production.
|
|
229
|
+
// However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode.
|
|
230
|
+
//
|
|
231
|
+
// To simplify the logic at our side, we will add MiniCssExtractPlugin based on
|
|
232
|
+
// the "instanceof" check (We will only add our required MiniCssExtractPlugin if
|
|
233
|
+
// Next.js hasn't added it yet).
|
|
234
|
+
// This also prevent multiple MiniCssExtractPlugin being added (which will cause
|
|
235
|
+
// RealContentHashPlugin to panic)
|
|
236
|
+
if (!config.plugins.some(p => p instanceof NextMiniCssExtractPlugin)) {
|
|
237
|
+
// HMR reloads the CSS file when the content changes but does not use
|
|
238
|
+
// the new file name, which means it can't contain a hash.
|
|
239
|
+
const filename = dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
|
|
240
|
+
config.plugins.push(new NextMiniCssExtractPlugin({
|
|
241
|
+
filename,
|
|
242
|
+
chunkFilename: filename,
|
|
243
|
+
// Next.js guarantees that CSS order "doesn't matter", due to imposed
|
|
244
|
+
// restrictions:
|
|
245
|
+
// 1. Global CSS can only be defined in a single entrypoint (_app)
|
|
246
|
+
// 2. CSS Modules generate scoped class names by default and cannot
|
|
247
|
+
// include Global CSS (:global() selector).
|
|
248
|
+
//
|
|
249
|
+
// While not a perfect guarantee (e.g. liberal use of `:global()`
|
|
250
|
+
// selector), this assumption is required to code-split CSS.
|
|
251
|
+
//
|
|
252
|
+
// If this warning were to trigger, it'd be unactionable by the user,
|
|
253
|
+
// but likely not valid -- so just disable it.
|
|
254
|
+
ignoreOrder: true
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
config.plugins.push(new next.VanillaExtractPlugin({
|
|
258
|
+
outputCss,
|
|
259
|
+
...webpackPluginOptions
|
|
175
260
|
}));
|
|
261
|
+
if (typeof nextConfig.webpack === 'function') {
|
|
262
|
+
return nextConfig.webpack(config, options);
|
|
263
|
+
}
|
|
264
|
+
return config;
|
|
176
265
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
return config;
|
|
266
|
+
};
|
|
267
|
+
if (enableTurbopack && turbopack) {
|
|
268
|
+
return {
|
|
269
|
+
...baseConfig,
|
|
270
|
+
turbopack
|
|
271
|
+
};
|
|
185
272
|
}
|
|
186
|
-
|
|
273
|
+
return baseConfig;
|
|
274
|
+
};
|
|
187
275
|
};
|
|
188
276
|
|
|
189
277
|
exports.createVanillaExtractPlugin = createVanillaExtractPlugin;
|
|
@@ -9,11 +9,33 @@ var findPagesDir = require('next/dist/lib/find-pages-dir');
|
|
|
9
9
|
var css = require('next/dist/build/webpack/config/blocks/css');
|
|
10
10
|
var fileResolve = require('next/dist/build/webpack/config/blocks/css/loaders/file-resolve');
|
|
11
11
|
var node_module = require('node:module');
|
|
12
|
+
var path = require('node:path');
|
|
13
|
+
var semver = require('semver');
|
|
12
14
|
|
|
13
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
14
16
|
|
|
17
|
+
function _interopNamespace(e) {
|
|
18
|
+
if (e && e.__esModule) return e;
|
|
19
|
+
var n = Object.create(null);
|
|
20
|
+
if (e) {
|
|
21
|
+
Object.keys(e).forEach(function (k) {
|
|
22
|
+
if (k !== 'default') {
|
|
23
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
24
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return e[k]; }
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
n["default"] = e;
|
|
32
|
+
return Object.freeze(n);
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
var browserslist__default = /*#__PURE__*/_interopDefault(browserslist);
|
|
16
36
|
var NextMiniCssExtractPluginDefault__default = /*#__PURE__*/_interopDefault(NextMiniCssExtractPluginDefault);
|
|
37
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
38
|
+
var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
17
39
|
|
|
18
40
|
// @ts-expect-error
|
|
19
41
|
const require$1 = node_module.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('dist/vanilla-extract-next-plugin.cjs.prod.js', document.baseURI).href)));
|
|
@@ -113,77 +135,143 @@ const getVanillaExtractCssLoaders = (options, assetPrefix, hasAppDir) => {
|
|
|
113
135
|
return loaders;
|
|
114
136
|
};
|
|
115
137
|
const createVanillaExtractPlugin = (pluginOptions = {}) => {
|
|
116
|
-
return (nextConfig = {}) =>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
138
|
+
return (nextConfig = {}) => {
|
|
139
|
+
const {
|
|
140
|
+
unstable_turbopack: turbopackOptions = {},
|
|
141
|
+
...webpackPluginOptions
|
|
142
|
+
} = pluginOptions;
|
|
143
|
+
const {
|
|
144
|
+
mode: turbopackMode = 'off',
|
|
145
|
+
glob: turbopackGlob = ['**/*.css.{js,cjs,mjs,jsx,ts,tsx}']
|
|
146
|
+
} = turbopackOptions;
|
|
147
|
+
// detect Next version and decide whether to configure turbopack
|
|
148
|
+
const nextVersion = (() => {
|
|
149
|
+
try {
|
|
150
|
+
// resolve from the consumer app's cwd, not this package
|
|
151
|
+
const requireFromCwd = node_module.createRequire(path__namespace.join(process.cwd(), 'package.json'));
|
|
152
|
+
const pkg = requireFromCwd('next/package.json');
|
|
153
|
+
return (pkg === null || pkg === void 0 ? void 0 : pkg.version) ?? null;
|
|
154
|
+
} catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
})();
|
|
158
|
+
const coerced = nextVersion ? semver__default["default"].coerce(nextVersion) : null;
|
|
159
|
+
const supportsTurbopackRules = !!coerced && semver__default["default"].gte(coerced, '16.0.0');
|
|
160
|
+
const enableTurbopack = turbopackMode === 'on' || turbopackMode === 'auto' && supportsTurbopackRules;
|
|
161
|
+
if (turbopackMode === 'on' && !supportsTurbopackRules) {
|
|
162
|
+
console.warn(`[@vanilla-extract/next-plugin] Turbopack is configured but does not seem supported. Expected Next.js >= 16.0.0, got ${nextVersion}`);
|
|
163
|
+
}
|
|
164
|
+
let turbopack;
|
|
165
|
+
if (enableTurbopack) {
|
|
166
|
+
turbopack = {
|
|
167
|
+
...(nextConfig.turbopack || {})
|
|
168
|
+
};
|
|
169
|
+
if (turbopackGlob.some(glob => {
|
|
170
|
+
var _turbopack$rules;
|
|
171
|
+
return (_turbopack$rules = turbopack.rules) === null || _turbopack$rules === void 0 ? void 0 : _turbopack$rules[glob];
|
|
172
|
+
})) {
|
|
173
|
+
throw new Error('Vanilla extract could not be applied automatically due to conflicting turbopack rules');
|
|
174
|
+
}
|
|
175
|
+
const vanillaExtractRule = {
|
|
176
|
+
as: '*.js',
|
|
177
|
+
loaders: [{
|
|
178
|
+
loader: require$1.resolve('@vanilla-extract/turbopack-plugin'),
|
|
179
|
+
options: {
|
|
180
|
+
nextEnv: nextConfig.env ?? null,
|
|
181
|
+
outputCss: pluginOptions.outputCss ?? null,
|
|
182
|
+
identifiers: pluginOptions.identifiers ?? null
|
|
183
|
+
}
|
|
184
|
+
}]
|
|
185
|
+
};
|
|
186
|
+
const vanillaExtractCssRule = {
|
|
187
|
+
as: '*.css',
|
|
188
|
+
loaders: [require$1.resolve('@vanilla-extract/turbopack-plugin')]
|
|
189
|
+
};
|
|
190
|
+
turbopack.rules = {
|
|
191
|
+
...(turbopack.rules || {}),
|
|
192
|
+
...Object.fromEntries(turbopackGlob.map(glob => [glob, vanillaExtractRule])),
|
|
193
|
+
'vanilla.virtual.css': vanillaExtractCssRule
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const baseConfig = {
|
|
197
|
+
...nextConfig,
|
|
198
|
+
webpack(config, options) {
|
|
199
|
+
var _resolvedNextConfig$e;
|
|
200
|
+
const {
|
|
201
|
+
dir,
|
|
202
|
+
dev,
|
|
203
|
+
config: resolvedNextConfig
|
|
204
|
+
} = options;
|
|
205
|
+
|
|
206
|
+
// https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336
|
|
207
|
+
// https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626
|
|
208
|
+
// https://github.com/vercel/next.js/pull/43916
|
|
209
|
+
// on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object
|
|
210
|
+
const findPagesDirResult = findPagesDir.findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);
|
|
211
|
+
// Skip nextConfig check since appDir is stable feature after Next.js 13.4
|
|
212
|
+
const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir);
|
|
213
|
+
const outputCss = true;
|
|
214
|
+
|
|
215
|
+
// https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21
|
|
216
|
+
const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
|
|
217
|
+
test
|
|
218
|
+
}) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
|
|
219
|
+
|
|
220
|
+
// https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190
|
|
221
|
+
cssRules.unshift({
|
|
222
|
+
test: /vanilla\.virtual\.css/i,
|
|
223
|
+
sideEffects: true,
|
|
224
|
+
use: getVanillaExtractCssLoaders(options, resolvedNextConfig.assetPrefix, hasAppDir)
|
|
225
|
+
});
|
|
146
226
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
227
|
+
// vanilla-extract need to emit the css file on both server and client, both during the
|
|
228
|
+
// development and production.
|
|
229
|
+
// However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode.
|
|
230
|
+
//
|
|
231
|
+
// To simplify the logic at our side, we will add MiniCssExtractPlugin based on
|
|
232
|
+
// the "instanceof" check (We will only add our required MiniCssExtractPlugin if
|
|
233
|
+
// Next.js hasn't added it yet).
|
|
234
|
+
// This also prevent multiple MiniCssExtractPlugin being added (which will cause
|
|
235
|
+
// RealContentHashPlugin to panic)
|
|
236
|
+
if (!config.plugins.some(p => p instanceof NextMiniCssExtractPlugin)) {
|
|
237
|
+
// HMR reloads the CSS file when the content changes but does not use
|
|
238
|
+
// the new file name, which means it can't contain a hash.
|
|
239
|
+
const filename = dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
|
|
240
|
+
config.plugins.push(new NextMiniCssExtractPlugin({
|
|
241
|
+
filename,
|
|
242
|
+
chunkFilename: filename,
|
|
243
|
+
// Next.js guarantees that CSS order "doesn't matter", due to imposed
|
|
244
|
+
// restrictions:
|
|
245
|
+
// 1. Global CSS can only be defined in a single entrypoint (_app)
|
|
246
|
+
// 2. CSS Modules generate scoped class names by default and cannot
|
|
247
|
+
// include Global CSS (:global() selector).
|
|
248
|
+
//
|
|
249
|
+
// While not a perfect guarantee (e.g. liberal use of `:global()`
|
|
250
|
+
// selector), this assumption is required to code-split CSS.
|
|
251
|
+
//
|
|
252
|
+
// If this warning were to trigger, it'd be unactionable by the user,
|
|
253
|
+
// but likely not valid -- so just disable it.
|
|
254
|
+
ignoreOrder: true
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
config.plugins.push(new next.VanillaExtractPlugin({
|
|
258
|
+
outputCss,
|
|
259
|
+
...webpackPluginOptions
|
|
175
260
|
}));
|
|
261
|
+
if (typeof nextConfig.webpack === 'function') {
|
|
262
|
+
return nextConfig.webpack(config, options);
|
|
263
|
+
}
|
|
264
|
+
return config;
|
|
176
265
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
return config;
|
|
266
|
+
};
|
|
267
|
+
if (enableTurbopack && turbopack) {
|
|
268
|
+
return {
|
|
269
|
+
...baseConfig,
|
|
270
|
+
turbopack
|
|
271
|
+
};
|
|
185
272
|
}
|
|
186
|
-
|
|
273
|
+
return baseConfig;
|
|
274
|
+
};
|
|
187
275
|
};
|
|
188
276
|
|
|
189
277
|
exports.createVanillaExtractPlugin = createVanillaExtractPlugin;
|
|
@@ -5,6 +5,8 @@ import { findPagesDir } from 'next/dist/lib/find-pages-dir';
|
|
|
5
5
|
import { lazyPostCSS } from 'next/dist/build/webpack/config/blocks/css';
|
|
6
6
|
import { cssFileResolve } from 'next/dist/build/webpack/config/blocks/css/loaders/file-resolve';
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import semver from 'semver';
|
|
8
10
|
|
|
9
11
|
// @ts-expect-error
|
|
10
12
|
const require = createRequire(import.meta.url);
|
|
@@ -104,77 +106,143 @@ const getVanillaExtractCssLoaders = (options, assetPrefix, hasAppDir) => {
|
|
|
104
106
|
return loaders;
|
|
105
107
|
};
|
|
106
108
|
const createVanillaExtractPlugin = (pluginOptions = {}) => {
|
|
107
|
-
return (nextConfig = {}) =>
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
return (nextConfig = {}) => {
|
|
110
|
+
const {
|
|
111
|
+
unstable_turbopack: turbopackOptions = {},
|
|
112
|
+
...webpackPluginOptions
|
|
113
|
+
} = pluginOptions;
|
|
114
|
+
const {
|
|
115
|
+
mode: turbopackMode = 'off',
|
|
116
|
+
glob: turbopackGlob = ['**/*.css.{js,cjs,mjs,jsx,ts,tsx}']
|
|
117
|
+
} = turbopackOptions;
|
|
118
|
+
// detect Next version and decide whether to configure turbopack
|
|
119
|
+
const nextVersion = (() => {
|
|
120
|
+
try {
|
|
121
|
+
// resolve from the consumer app's cwd, not this package
|
|
122
|
+
const requireFromCwd = createRequire(path.join(process.cwd(), 'package.json'));
|
|
123
|
+
const pkg = requireFromCwd('next/package.json');
|
|
124
|
+
return (pkg === null || pkg === void 0 ? void 0 : pkg.version) ?? null;
|
|
125
|
+
} catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
const coerced = nextVersion ? semver.coerce(nextVersion) : null;
|
|
130
|
+
const supportsTurbopackRules = !!coerced && semver.gte(coerced, '16.0.0');
|
|
131
|
+
const enableTurbopack = turbopackMode === 'on' || turbopackMode === 'auto' && supportsTurbopackRules;
|
|
132
|
+
if (turbopackMode === 'on' && !supportsTurbopackRules) {
|
|
133
|
+
console.warn(`[@vanilla-extract/next-plugin] Turbopack is configured but does not seem supported. Expected Next.js >= 16.0.0, got ${nextVersion}`);
|
|
134
|
+
}
|
|
135
|
+
let turbopack;
|
|
136
|
+
if (enableTurbopack) {
|
|
137
|
+
turbopack = {
|
|
138
|
+
...(nextConfig.turbopack || {})
|
|
139
|
+
};
|
|
140
|
+
if (turbopackGlob.some(glob => {
|
|
141
|
+
var _turbopack$rules;
|
|
142
|
+
return (_turbopack$rules = turbopack.rules) === null || _turbopack$rules === void 0 ? void 0 : _turbopack$rules[glob];
|
|
143
|
+
})) {
|
|
144
|
+
throw new Error('Vanilla extract could not be applied automatically due to conflicting turbopack rules');
|
|
145
|
+
}
|
|
146
|
+
const vanillaExtractRule = {
|
|
147
|
+
as: '*.js',
|
|
148
|
+
loaders: [{
|
|
149
|
+
loader: require.resolve('@vanilla-extract/turbopack-plugin'),
|
|
150
|
+
options: {
|
|
151
|
+
nextEnv: nextConfig.env ?? null,
|
|
152
|
+
outputCss: pluginOptions.outputCss ?? null,
|
|
153
|
+
identifiers: pluginOptions.identifiers ?? null
|
|
154
|
+
}
|
|
155
|
+
}]
|
|
156
|
+
};
|
|
157
|
+
const vanillaExtractCssRule = {
|
|
158
|
+
as: '*.css',
|
|
159
|
+
loaders: [require.resolve('@vanilla-extract/turbopack-plugin')]
|
|
160
|
+
};
|
|
161
|
+
turbopack.rules = {
|
|
162
|
+
...(turbopack.rules || {}),
|
|
163
|
+
...Object.fromEntries(turbopackGlob.map(glob => [glob, vanillaExtractRule])),
|
|
164
|
+
'vanilla.virtual.css': vanillaExtractCssRule
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const baseConfig = {
|
|
168
|
+
...nextConfig,
|
|
169
|
+
webpack(config, options) {
|
|
170
|
+
var _resolvedNextConfig$e;
|
|
171
|
+
const {
|
|
172
|
+
dir,
|
|
173
|
+
dev,
|
|
174
|
+
config: resolvedNextConfig
|
|
175
|
+
} = options;
|
|
116
176
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
177
|
+
// https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336
|
|
178
|
+
// https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626
|
|
179
|
+
// https://github.com/vercel/next.js/pull/43916
|
|
180
|
+
// on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object
|
|
181
|
+
const findPagesDirResult = findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);
|
|
182
|
+
// Skip nextConfig check since appDir is stable feature after Next.js 13.4
|
|
183
|
+
const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir);
|
|
184
|
+
const outputCss = true;
|
|
125
185
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
186
|
+
// https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21
|
|
187
|
+
const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
|
|
188
|
+
test
|
|
189
|
+
}) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
|
|
130
190
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
191
|
+
// https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190
|
|
192
|
+
cssRules.unshift({
|
|
193
|
+
test: /vanilla\.virtual\.css/i,
|
|
194
|
+
sideEffects: true,
|
|
195
|
+
use: getVanillaExtractCssLoaders(options, resolvedNextConfig.assetPrefix, hasAppDir)
|
|
196
|
+
});
|
|
137
197
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
198
|
+
// vanilla-extract need to emit the css file on both server and client, both during the
|
|
199
|
+
// development and production.
|
|
200
|
+
// However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode.
|
|
201
|
+
//
|
|
202
|
+
// To simplify the logic at our side, we will add MiniCssExtractPlugin based on
|
|
203
|
+
// the "instanceof" check (We will only add our required MiniCssExtractPlugin if
|
|
204
|
+
// Next.js hasn't added it yet).
|
|
205
|
+
// This also prevent multiple MiniCssExtractPlugin being added (which will cause
|
|
206
|
+
// RealContentHashPlugin to panic)
|
|
207
|
+
if (!config.plugins.some(p => p instanceof NextMiniCssExtractPlugin)) {
|
|
208
|
+
// HMR reloads the CSS file when the content changes but does not use
|
|
209
|
+
// the new file name, which means it can't contain a hash.
|
|
210
|
+
const filename = dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
|
|
211
|
+
config.plugins.push(new NextMiniCssExtractPlugin({
|
|
212
|
+
filename,
|
|
213
|
+
chunkFilename: filename,
|
|
214
|
+
// Next.js guarantees that CSS order "doesn't matter", due to imposed
|
|
215
|
+
// restrictions:
|
|
216
|
+
// 1. Global CSS can only be defined in a single entrypoint (_app)
|
|
217
|
+
// 2. CSS Modules generate scoped class names by default and cannot
|
|
218
|
+
// include Global CSS (:global() selector).
|
|
219
|
+
//
|
|
220
|
+
// While not a perfect guarantee (e.g. liberal use of `:global()`
|
|
221
|
+
// selector), this assumption is required to code-split CSS.
|
|
222
|
+
//
|
|
223
|
+
// If this warning were to trigger, it'd be unactionable by the user,
|
|
224
|
+
// but likely not valid -- so just disable it.
|
|
225
|
+
ignoreOrder: true
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
228
|
+
config.plugins.push(new VanillaExtractPlugin({
|
|
229
|
+
outputCss,
|
|
230
|
+
...webpackPluginOptions
|
|
166
231
|
}));
|
|
232
|
+
if (typeof nextConfig.webpack === 'function') {
|
|
233
|
+
return nextConfig.webpack(config, options);
|
|
234
|
+
}
|
|
235
|
+
return config;
|
|
167
236
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
return config;
|
|
237
|
+
};
|
|
238
|
+
if (enableTurbopack && turbopack) {
|
|
239
|
+
return {
|
|
240
|
+
...baseConfig,
|
|
241
|
+
turbopack
|
|
242
|
+
};
|
|
176
243
|
}
|
|
177
|
-
|
|
244
|
+
return baseConfig;
|
|
245
|
+
};
|
|
178
246
|
};
|
|
179
247
|
|
|
180
248
|
export { createVanillaExtractPlugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanilla-extract/next-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Zero-runtime Stylesheets-in-TypeScript",
|
|
5
5
|
"main": "dist/vanilla-extract-next-plugin.cjs.js",
|
|
6
6
|
"module": "dist/vanilla-extract-next-plugin.esm.js",
|
|
@@ -21,12 +21,15 @@
|
|
|
21
21
|
"author": "SEEK",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"
|
|
24
|
+
"semver": "^7.6.3",
|
|
25
|
+
"@vanilla-extract/turbopack-plugin": "^0.1.0",
|
|
26
|
+
"@vanilla-extract/webpack-plugin": "^2.3.26"
|
|
25
27
|
},
|
|
26
28
|
"peerDependencies": {
|
|
27
29
|
"next": ">=12.1.7"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
32
|
+
"@types/semver": "^7.7.1",
|
|
30
33
|
"next": "12.3.4",
|
|
31
34
|
"webpack": "^5.90.0"
|
|
32
35
|
}
|