@vanilla-extract/next-plugin 0.0.0-inline-prototype-2023326232811 → 0.0.0-master-20240328032403

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,5 +1,5 @@
1
- import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin';
2
- import { NextConfig } from 'next/types';
1
+ import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin/next';
2
+ import { NextConfig } from 'next/dist/server/config-shared';
3
3
 
4
4
  type PluginOptions = ConstructorParameters<typeof VanillaExtractPlugin>[0];
5
5
  declare const createVanillaExtractPlugin: (pluginOptions?: PluginOptions) => (nextConfig?: NextConfig) => NextConfig;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vanilla-extract-next-plugin.cjs.d.ts","sourceRoot":"","sources":["./declarations/src/index.d.ts"],"names":[],"mappings":"AAAA"}
@@ -2,59 +2,186 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var webpackPlugin = require('@vanilla-extract/webpack-plugin');
6
- var browserslist = require('browserslist');
5
+ var browserslist = require('next/dist/compiled/browserslist');
6
+ var NextMiniCssExtractPluginDefault = require('next/dist/build/webpack/plugins/mini-css-extract-plugin');
7
+ var next = require('@vanilla-extract/webpack-plugin/next');
8
+ var findPagesDir = require('next/dist/lib/find-pages-dir');
7
9
  var css = require('next/dist/build/webpack/config/blocks/css');
8
- var loaders = require('next/dist/build/webpack/config/blocks/css/loaders');
10
+ var fileResolve = require('next/dist/build/webpack/config/blocks/css/loaders/file-resolve');
9
11
 
10
12
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
11
13
 
12
14
  var browserslist__default = /*#__PURE__*/_interopDefault(browserslist);
15
+ var NextMiniCssExtractPluginDefault__default = /*#__PURE__*/_interopDefault(NextMiniCssExtractPluginDefault);
13
16
 
17
+ // @ts-expect-error
18
+ const NextMiniCssExtractPlugin = NextMiniCssExtractPluginDefault__default["default"];
19
+
20
+ // Adopted from https://github.com/vercel/next.js/blob/1f1632979c78b3edfe59fd85d8cce62efcdee688/packages/next/build/webpack-config.ts#L60-L72
14
21
  function getSupportedBrowsers(dir, isDevelopment) {
15
- let browsers;
16
22
  try {
17
- browsers = browserslist__default["default"].loadConfig({
23
+ return browserslist__default["default"].loadConfig({
18
24
  path: dir,
19
25
  env: isDevelopment ? 'development' : 'production'
20
26
  });
21
- } catch {}
22
- return browsers;
27
+ } catch (_) {
28
+ return undefined;
29
+ }
23
30
  }
24
- const createVanillaExtractPlugin = (pluginOptions = {}) => (nextConfig = {}) => Object.assign({}, nextConfig, {
25
- webpack(config, options) {
26
- var _nextConfig$experimen;
27
- const {
28
- dir,
29
- dev,
30
- isServer
31
- } = options;
32
- const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
33
- test
34
- }) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
35
- cssRules.unshift({
36
- test: /\.vanilla\.css$/i,
37
- sideEffects: true,
38
- use: loaders.getGlobalCssLoader({
39
- assetPrefix: config.assetPrefix,
40
- isClient: !isServer,
41
- isServer,
42
- isDevelopment: dev,
43
- future: nextConfig.future || {},
44
- experimental: nextConfig.experimental || {},
45
- // @ts-ignore -- 'appDir' config is in beta
46
- hasAppDir: (_nextConfig$experimen = nextConfig.experimental) === null || _nextConfig$experimen === void 0 ? void 0 : _nextConfig$experimen.appDir
47
- }, () => css.lazyPostCSS(dir, getSupportedBrowsers(dir, dev), undefined), [])
48
- });
49
- config.plugins.push(new webpackPlugin.VanillaExtractPlugin({
50
- outputCss: !isServer,
51
- ...pluginOptions
52
- }));
53
- if (typeof nextConfig.webpack === 'function') {
54
- return nextConfig.webpack(config, options);
31
+
32
+ // Adopt from Next.js' getGlobalCssLoader
33
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L7
34
+ const getVanillaExtractCssLoaders = (options, assetPrefix, hasAppDir) => {
35
+ const loaders = [];
36
+
37
+ // Adopt from Next.js' getClientStyleLoader
38
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L3
39
+ if (!options.isServer) {
40
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L16
41
+ // Keep next-style-loader for development mode in `pages/`
42
+ if (options.dev && !hasAppDir) {
43
+ loaders.push({
44
+ loader: 'next-style-loader',
45
+ options: {
46
+ insert: function (element) {
47
+ // By default, style-loader injects CSS into the bottom
48
+ // of <head>. This causes ordering problems between dev
49
+ // and prod. To fix this, we render a <noscript> tag as
50
+ // an anchor for the styles to be placed before. These
51
+ // styles will be applied _before_ <style jsx global>.
52
+
53
+ // These elements should always exist. If they do not,
54
+ // this code should fail.
55
+ const anchorElement = document.querySelector('#__next_css__DO_NOT_USE__');
56
+ const parentNode = anchorElement.parentNode; // Normally <head>
57
+
58
+ // Each style tag should be placed right before our
59
+ // anchor. By inserting before and not after, we do not
60
+ // need to track the last inserted element.
61
+ parentNode.insertBefore(element, anchorElement);
62
+ }
63
+ }
64
+ });
65
+ } else {
66
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L44
67
+ // next-style-loader will mess up css order in development mode.
68
+ // Next.js appDir doesn't use next-style-loader either.
69
+ // So we always use css-loader here, to simplify things and get proper order of output CSS
70
+ loaders.push({
71
+ loader: NextMiniCssExtractPlugin.loader,
72
+ options: {
73
+ publicPath: `${assetPrefix}/_next/`,
74
+ esModule: false
75
+ }
76
+ });
55
77
  }
56
- return config;
57
78
  }
58
- });
79
+ const postcss = () => css.lazyPostCSS(options.dir, getSupportedBrowsers(options.dir, options.dev), undefined);
80
+
81
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L28
82
+ loaders.push({
83
+ loader: require.resolve('next/dist/build/webpack/loaders/css-loader/src'),
84
+ options: {
85
+ postcss,
86
+ importLoaders: 1,
87
+ modules: false,
88
+ url: (url, resourcePath) => {
89
+ var _options$config$exper;
90
+ return fileResolve.cssFileResolve(url, resourcePath, (_options$config$exper = options.config.experimental) === null || _options$config$exper === void 0 ? void 0 : _options$config$exper.urlImports);
91
+ },
92
+ import: (url, _, resourcePath) => {
93
+ var _options$config$exper2;
94
+ return fileResolve.cssFileResolve(url, resourcePath, (_options$config$exper2 = options.config.experimental) === null || _options$config$exper2 === void 0 ? void 0 : _options$config$exper2.urlImports);
95
+ }
96
+ }
97
+ });
98
+
99
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L29-L38
100
+ loaders.push({
101
+ loader: require.resolve('next/dist/build/webpack/loaders/postcss-loader/src'),
102
+ options: {
103
+ postcss
104
+ }
105
+ });
106
+
107
+ // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L103-L105
108
+ loaders.push({
109
+ loader: next.VanillaExtractPlugin.loader
110
+ });
111
+ return loaders;
112
+ };
113
+ const createVanillaExtractPlugin = (pluginOptions = {}) => {
114
+ return (nextConfig = {}) => ({
115
+ ...nextConfig,
116
+ webpack(config, options) {
117
+ var _resolvedNextConfig$e;
118
+ const {
119
+ dir,
120
+ dev,
121
+ config: resolvedNextConfig
122
+ } = options;
123
+
124
+ // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336
125
+ // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626
126
+ // https://github.com/vercel/next.js/pull/43916
127
+ // on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object
128
+ const findPagesDirResult = findPagesDir.findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);
129
+ // Skip nextConfig check since appDir is stable feature after Next.js 13.4
130
+ const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir);
131
+ const outputCss = true;
132
+
133
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21
134
+ const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
135
+ test
136
+ }) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
137
+
138
+ // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190
139
+ cssRules.unshift({
140
+ test: /vanilla\.virtual\.css/i,
141
+ sideEffects: true,
142
+ use: getVanillaExtractCssLoaders(options, resolvedNextConfig.assetPrefix, hasAppDir)
143
+ });
144
+
145
+ // vanilla-extract need to emit the css file on both server and client, both during the
146
+ // development and production.
147
+ // However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode.
148
+ //
149
+ // To simplify the logic at our side, we will add MiniCssExtractPlugin based on
150
+ // the "instanceof" check (We will only add our required MiniCssExtractPlugin if
151
+ // Next.js hasn't added it yet).
152
+ // This also prevent multiple MiniCssExtractPlugin being added (which will cause
153
+ // RealContentHashPlugin to panic)
154
+ if (!config.plugins.some(p => p instanceof NextMiniCssExtractPlugin)) {
155
+ // HMR reloads the CSS file when the content changes but does not use
156
+ // the new file name, which means it can't contain a hash.
157
+ const filename = dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
158
+ config.plugins.push(new NextMiniCssExtractPlugin({
159
+ filename,
160
+ chunkFilename: filename,
161
+ // Next.js guarantees that CSS order "doesn't matter", due to imposed
162
+ // restrictions:
163
+ // 1. Global CSS can only be defined in a single entrypoint (_app)
164
+ // 2. CSS Modules generate scoped class names by default and cannot
165
+ // include Global CSS (:global() selector).
166
+ //
167
+ // While not a perfect guarantee (e.g. liberal use of `:global()`
168
+ // selector), this assumption is required to code-split CSS.
169
+ //
170
+ // If this warning were to trigger, it'd be unactionable by the user,
171
+ // but likely not valid -- so just disable it.
172
+ ignoreOrder: true
173
+ }));
174
+ }
175
+ config.plugins.push(new next.VanillaExtractPlugin({
176
+ outputCss,
177
+ ...pluginOptions
178
+ }));
179
+ if (typeof nextConfig.webpack === 'function') {
180
+ return nextConfig.webpack(config, options);
181
+ }
182
+ return config;
183
+ }
184
+ });
185
+ };
59
186
 
60
187
  exports.createVanillaExtractPlugin = createVanillaExtractPlugin;
@@ -2,59 +2,186 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var webpackPlugin = require('@vanilla-extract/webpack-plugin');
6
- var browserslist = require('browserslist');
5
+ var browserslist = require('next/dist/compiled/browserslist');
6
+ var NextMiniCssExtractPluginDefault = require('next/dist/build/webpack/plugins/mini-css-extract-plugin');
7
+ var next = require('@vanilla-extract/webpack-plugin/next');
8
+ var findPagesDir = require('next/dist/lib/find-pages-dir');
7
9
  var css = require('next/dist/build/webpack/config/blocks/css');
8
- var loaders = require('next/dist/build/webpack/config/blocks/css/loaders');
10
+ var fileResolve = require('next/dist/build/webpack/config/blocks/css/loaders/file-resolve');
9
11
 
10
12
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
11
13
 
12
14
  var browserslist__default = /*#__PURE__*/_interopDefault(browserslist);
15
+ var NextMiniCssExtractPluginDefault__default = /*#__PURE__*/_interopDefault(NextMiniCssExtractPluginDefault);
13
16
 
17
+ // @ts-expect-error
18
+ const NextMiniCssExtractPlugin = NextMiniCssExtractPluginDefault__default["default"];
19
+
20
+ // Adopted from https://github.com/vercel/next.js/blob/1f1632979c78b3edfe59fd85d8cce62efcdee688/packages/next/build/webpack-config.ts#L60-L72
14
21
  function getSupportedBrowsers(dir, isDevelopment) {
15
- let browsers;
16
22
  try {
17
- browsers = browserslist__default["default"].loadConfig({
23
+ return browserslist__default["default"].loadConfig({
18
24
  path: dir,
19
25
  env: isDevelopment ? 'development' : 'production'
20
26
  });
21
- } catch {}
22
- return browsers;
27
+ } catch (_) {
28
+ return undefined;
29
+ }
23
30
  }
24
- const createVanillaExtractPlugin = (pluginOptions = {}) => (nextConfig = {}) => Object.assign({}, nextConfig, {
25
- webpack(config, options) {
26
- var _nextConfig$experimen;
27
- const {
28
- dir,
29
- dev,
30
- isServer
31
- } = options;
32
- const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
33
- test
34
- }) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
35
- cssRules.unshift({
36
- test: /\.vanilla\.css$/i,
37
- sideEffects: true,
38
- use: loaders.getGlobalCssLoader({
39
- assetPrefix: config.assetPrefix,
40
- isClient: !isServer,
41
- isServer,
42
- isDevelopment: dev,
43
- future: nextConfig.future || {},
44
- experimental: nextConfig.experimental || {},
45
- // @ts-ignore -- 'appDir' config is in beta
46
- hasAppDir: (_nextConfig$experimen = nextConfig.experimental) === null || _nextConfig$experimen === void 0 ? void 0 : _nextConfig$experimen.appDir
47
- }, () => css.lazyPostCSS(dir, getSupportedBrowsers(dir, dev), undefined), [])
48
- });
49
- config.plugins.push(new webpackPlugin.VanillaExtractPlugin({
50
- outputCss: !isServer,
51
- ...pluginOptions
52
- }));
53
- if (typeof nextConfig.webpack === 'function') {
54
- return nextConfig.webpack(config, options);
31
+
32
+ // Adopt from Next.js' getGlobalCssLoader
33
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L7
34
+ const getVanillaExtractCssLoaders = (options, assetPrefix, hasAppDir) => {
35
+ const loaders = [];
36
+
37
+ // Adopt from Next.js' getClientStyleLoader
38
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L3
39
+ if (!options.isServer) {
40
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L16
41
+ // Keep next-style-loader for development mode in `pages/`
42
+ if (options.dev && !hasAppDir) {
43
+ loaders.push({
44
+ loader: 'next-style-loader',
45
+ options: {
46
+ insert: function (element) {
47
+ // By default, style-loader injects CSS into the bottom
48
+ // of <head>. This causes ordering problems between dev
49
+ // and prod. To fix this, we render a <noscript> tag as
50
+ // an anchor for the styles to be placed before. These
51
+ // styles will be applied _before_ <style jsx global>.
52
+
53
+ // These elements should always exist. If they do not,
54
+ // this code should fail.
55
+ const anchorElement = document.querySelector('#__next_css__DO_NOT_USE__');
56
+ const parentNode = anchorElement.parentNode; // Normally <head>
57
+
58
+ // Each style tag should be placed right before our
59
+ // anchor. By inserting before and not after, we do not
60
+ // need to track the last inserted element.
61
+ parentNode.insertBefore(element, anchorElement);
62
+ }
63
+ }
64
+ });
65
+ } else {
66
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L44
67
+ // next-style-loader will mess up css order in development mode.
68
+ // Next.js appDir doesn't use next-style-loader either.
69
+ // So we always use css-loader here, to simplify things and get proper order of output CSS
70
+ loaders.push({
71
+ loader: NextMiniCssExtractPlugin.loader,
72
+ options: {
73
+ publicPath: `${assetPrefix}/_next/`,
74
+ esModule: false
75
+ }
76
+ });
55
77
  }
56
- return config;
57
78
  }
58
- });
79
+ const postcss = () => css.lazyPostCSS(options.dir, getSupportedBrowsers(options.dir, options.dev), undefined);
80
+
81
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L28
82
+ loaders.push({
83
+ loader: require.resolve('next/dist/build/webpack/loaders/css-loader/src'),
84
+ options: {
85
+ postcss,
86
+ importLoaders: 1,
87
+ modules: false,
88
+ url: (url, resourcePath) => {
89
+ var _options$config$exper;
90
+ return fileResolve.cssFileResolve(url, resourcePath, (_options$config$exper = options.config.experimental) === null || _options$config$exper === void 0 ? void 0 : _options$config$exper.urlImports);
91
+ },
92
+ import: (url, _, resourcePath) => {
93
+ var _options$config$exper2;
94
+ return fileResolve.cssFileResolve(url, resourcePath, (_options$config$exper2 = options.config.experimental) === null || _options$config$exper2 === void 0 ? void 0 : _options$config$exper2.urlImports);
95
+ }
96
+ }
97
+ });
98
+
99
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L29-L38
100
+ loaders.push({
101
+ loader: require.resolve('next/dist/build/webpack/loaders/postcss-loader/src'),
102
+ options: {
103
+ postcss
104
+ }
105
+ });
106
+
107
+ // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L103-L105
108
+ loaders.push({
109
+ loader: next.VanillaExtractPlugin.loader
110
+ });
111
+ return loaders;
112
+ };
113
+ const createVanillaExtractPlugin = (pluginOptions = {}) => {
114
+ return (nextConfig = {}) => ({
115
+ ...nextConfig,
116
+ webpack(config, options) {
117
+ var _resolvedNextConfig$e;
118
+ const {
119
+ dir,
120
+ dev,
121
+ config: resolvedNextConfig
122
+ } = options;
123
+
124
+ // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336
125
+ // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626
126
+ // https://github.com/vercel/next.js/pull/43916
127
+ // on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object
128
+ const findPagesDirResult = findPagesDir.findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);
129
+ // Skip nextConfig check since appDir is stable feature after Next.js 13.4
130
+ const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir);
131
+ const outputCss = true;
132
+
133
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21
134
+ const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
135
+ test
136
+ }) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
137
+
138
+ // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190
139
+ cssRules.unshift({
140
+ test: /vanilla\.virtual\.css/i,
141
+ sideEffects: true,
142
+ use: getVanillaExtractCssLoaders(options, resolvedNextConfig.assetPrefix, hasAppDir)
143
+ });
144
+
145
+ // vanilla-extract need to emit the css file on both server and client, both during the
146
+ // development and production.
147
+ // However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode.
148
+ //
149
+ // To simplify the logic at our side, we will add MiniCssExtractPlugin based on
150
+ // the "instanceof" check (We will only add our required MiniCssExtractPlugin if
151
+ // Next.js hasn't added it yet).
152
+ // This also prevent multiple MiniCssExtractPlugin being added (which will cause
153
+ // RealContentHashPlugin to panic)
154
+ if (!config.plugins.some(p => p instanceof NextMiniCssExtractPlugin)) {
155
+ // HMR reloads the CSS file when the content changes but does not use
156
+ // the new file name, which means it can't contain a hash.
157
+ const filename = dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
158
+ config.plugins.push(new NextMiniCssExtractPlugin({
159
+ filename,
160
+ chunkFilename: filename,
161
+ // Next.js guarantees that CSS order "doesn't matter", due to imposed
162
+ // restrictions:
163
+ // 1. Global CSS can only be defined in a single entrypoint (_app)
164
+ // 2. CSS Modules generate scoped class names by default and cannot
165
+ // include Global CSS (:global() selector).
166
+ //
167
+ // While not a perfect guarantee (e.g. liberal use of `:global()`
168
+ // selector), this assumption is required to code-split CSS.
169
+ //
170
+ // If this warning were to trigger, it'd be unactionable by the user,
171
+ // but likely not valid -- so just disable it.
172
+ ignoreOrder: true
173
+ }));
174
+ }
175
+ config.plugins.push(new next.VanillaExtractPlugin({
176
+ outputCss,
177
+ ...pluginOptions
178
+ }));
179
+ if (typeof nextConfig.webpack === 'function') {
180
+ return nextConfig.webpack(config, options);
181
+ }
182
+ return config;
183
+ }
184
+ });
185
+ };
59
186
 
60
187
  exports.createVanillaExtractPlugin = createVanillaExtractPlugin;
@@ -1,52 +1,178 @@
1
- import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin';
2
- import browserslist from 'browserslist';
1
+ import browserslist from 'next/dist/compiled/browserslist';
2
+ import NextMiniCssExtractPluginDefault from 'next/dist/build/webpack/plugins/mini-css-extract-plugin';
3
+ import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin/next';
4
+ import { findPagesDir } from 'next/dist/lib/find-pages-dir';
3
5
  import { lazyPostCSS } from 'next/dist/build/webpack/config/blocks/css';
4
- import { getGlobalCssLoader } from 'next/dist/build/webpack/config/blocks/css/loaders';
6
+ import { cssFileResolve } from 'next/dist/build/webpack/config/blocks/css/loaders/file-resolve';
5
7
 
8
+ // @ts-expect-error
9
+ const NextMiniCssExtractPlugin = NextMiniCssExtractPluginDefault;
10
+
11
+ // Adopted from https://github.com/vercel/next.js/blob/1f1632979c78b3edfe59fd85d8cce62efcdee688/packages/next/build/webpack-config.ts#L60-L72
6
12
  function getSupportedBrowsers(dir, isDevelopment) {
7
- let browsers;
8
13
  try {
9
- browsers = browserslist.loadConfig({
14
+ return browserslist.loadConfig({
10
15
  path: dir,
11
16
  env: isDevelopment ? 'development' : 'production'
12
17
  });
13
- } catch {}
14
- return browsers;
18
+ } catch (_) {
19
+ return undefined;
20
+ }
15
21
  }
16
- const createVanillaExtractPlugin = (pluginOptions = {}) => (nextConfig = {}) => Object.assign({}, nextConfig, {
17
- webpack(config, options) {
18
- var _nextConfig$experimen;
19
- const {
20
- dir,
21
- dev,
22
- isServer
23
- } = options;
24
- const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
25
- test
26
- }) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
27
- cssRules.unshift({
28
- test: /\.vanilla\.css$/i,
29
- sideEffects: true,
30
- use: getGlobalCssLoader({
31
- assetPrefix: config.assetPrefix,
32
- isClient: !isServer,
33
- isServer,
34
- isDevelopment: dev,
35
- future: nextConfig.future || {},
36
- experimental: nextConfig.experimental || {},
37
- // @ts-ignore -- 'appDir' config is in beta
38
- hasAppDir: (_nextConfig$experimen = nextConfig.experimental) === null || _nextConfig$experimen === void 0 ? void 0 : _nextConfig$experimen.appDir
39
- }, () => lazyPostCSS(dir, getSupportedBrowsers(dir, dev), undefined), [])
40
- });
41
- config.plugins.push(new VanillaExtractPlugin({
42
- outputCss: !isServer,
43
- ...pluginOptions
44
- }));
45
- if (typeof nextConfig.webpack === 'function') {
46
- return nextConfig.webpack(config, options);
22
+
23
+ // Adopt from Next.js' getGlobalCssLoader
24
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L7
25
+ const getVanillaExtractCssLoaders = (options, assetPrefix, hasAppDir) => {
26
+ const loaders = [];
27
+
28
+ // Adopt from Next.js' getClientStyleLoader
29
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L3
30
+ if (!options.isServer) {
31
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L16
32
+ // Keep next-style-loader for development mode in `pages/`
33
+ if (options.dev && !hasAppDir) {
34
+ loaders.push({
35
+ loader: 'next-style-loader',
36
+ options: {
37
+ insert: function (element) {
38
+ // By default, style-loader injects CSS into the bottom
39
+ // of <head>. This causes ordering problems between dev
40
+ // and prod. To fix this, we render a <noscript> tag as
41
+ // an anchor for the styles to be placed before. These
42
+ // styles will be applied _before_ <style jsx global>.
43
+
44
+ // These elements should always exist. If they do not,
45
+ // this code should fail.
46
+ const anchorElement = document.querySelector('#__next_css__DO_NOT_USE__');
47
+ const parentNode = anchorElement.parentNode; // Normally <head>
48
+
49
+ // Each style tag should be placed right before our
50
+ // anchor. By inserting before and not after, we do not
51
+ // need to track the last inserted element.
52
+ parentNode.insertBefore(element, anchorElement);
53
+ }
54
+ }
55
+ });
56
+ } else {
57
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L44
58
+ // next-style-loader will mess up css order in development mode.
59
+ // Next.js appDir doesn't use next-style-loader either.
60
+ // So we always use css-loader here, to simplify things and get proper order of output CSS
61
+ loaders.push({
62
+ loader: NextMiniCssExtractPlugin.loader,
63
+ options: {
64
+ publicPath: `${assetPrefix}/_next/`,
65
+ esModule: false
66
+ }
67
+ });
47
68
  }
48
- return config;
49
69
  }
50
- });
70
+ const postcss = () => lazyPostCSS(options.dir, getSupportedBrowsers(options.dir, options.dev), undefined);
71
+
72
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L28
73
+ loaders.push({
74
+ loader: require.resolve('next/dist/build/webpack/loaders/css-loader/src'),
75
+ options: {
76
+ postcss,
77
+ importLoaders: 1,
78
+ modules: false,
79
+ url: (url, resourcePath) => {
80
+ var _options$config$exper;
81
+ return cssFileResolve(url, resourcePath, (_options$config$exper = options.config.experimental) === null || _options$config$exper === void 0 ? void 0 : _options$config$exper.urlImports);
82
+ },
83
+ import: (url, _, resourcePath) => {
84
+ var _options$config$exper2;
85
+ return cssFileResolve(url, resourcePath, (_options$config$exper2 = options.config.experimental) === null || _options$config$exper2 === void 0 ? void 0 : _options$config$exper2.urlImports);
86
+ }
87
+ }
88
+ });
89
+
90
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L29-L38
91
+ loaders.push({
92
+ loader: require.resolve('next/dist/build/webpack/loaders/postcss-loader/src'),
93
+ options: {
94
+ postcss
95
+ }
96
+ });
97
+
98
+ // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L103-L105
99
+ loaders.push({
100
+ loader: VanillaExtractPlugin.loader
101
+ });
102
+ return loaders;
103
+ };
104
+ const createVanillaExtractPlugin = (pluginOptions = {}) => {
105
+ return (nextConfig = {}) => ({
106
+ ...nextConfig,
107
+ webpack(config, options) {
108
+ var _resolvedNextConfig$e;
109
+ const {
110
+ dir,
111
+ dev,
112
+ config: resolvedNextConfig
113
+ } = options;
114
+
115
+ // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336
116
+ // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626
117
+ // https://github.com/vercel/next.js/pull/43916
118
+ // on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object
119
+ const findPagesDirResult = findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);
120
+ // Skip nextConfig check since appDir is stable feature after Next.js 13.4
121
+ const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir);
122
+ const outputCss = true;
123
+
124
+ // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21
125
+ const cssRules = config.module.rules.find(rule => Array.isArray(rule.oneOf) && rule.oneOf.some(({
126
+ test
127
+ }) => typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
128
+
129
+ // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190
130
+ cssRules.unshift({
131
+ test: /vanilla\.virtual\.css/i,
132
+ sideEffects: true,
133
+ use: getVanillaExtractCssLoaders(options, resolvedNextConfig.assetPrefix, hasAppDir)
134
+ });
135
+
136
+ // vanilla-extract need to emit the css file on both server and client, both during the
137
+ // development and production.
138
+ // However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode.
139
+ //
140
+ // To simplify the logic at our side, we will add MiniCssExtractPlugin based on
141
+ // the "instanceof" check (We will only add our required MiniCssExtractPlugin if
142
+ // Next.js hasn't added it yet).
143
+ // This also prevent multiple MiniCssExtractPlugin being added (which will cause
144
+ // RealContentHashPlugin to panic)
145
+ if (!config.plugins.some(p => p instanceof NextMiniCssExtractPlugin)) {
146
+ // HMR reloads the CSS file when the content changes but does not use
147
+ // the new file name, which means it can't contain a hash.
148
+ const filename = dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
149
+ config.plugins.push(new NextMiniCssExtractPlugin({
150
+ filename,
151
+ chunkFilename: filename,
152
+ // Next.js guarantees that CSS order "doesn't matter", due to imposed
153
+ // restrictions:
154
+ // 1. Global CSS can only be defined in a single entrypoint (_app)
155
+ // 2. CSS Modules generate scoped class names by default and cannot
156
+ // include Global CSS (:global() selector).
157
+ //
158
+ // While not a perfect guarantee (e.g. liberal use of `:global()`
159
+ // selector), this assumption is required to code-split CSS.
160
+ //
161
+ // If this warning were to trigger, it'd be unactionable by the user,
162
+ // but likely not valid -- so just disable it.
163
+ ignoreOrder: true
164
+ }));
165
+ }
166
+ config.plugins.push(new VanillaExtractPlugin({
167
+ outputCss,
168
+ ...pluginOptions
169
+ }));
170
+ if (typeof nextConfig.webpack === 'function') {
171
+ return nextConfig.webpack(config, options);
172
+ }
173
+ return config;
174
+ }
175
+ });
176
+ };
51
177
 
52
178
  export { createVanillaExtractPlugin };
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@vanilla-extract/next-plugin",
3
- "version": "0.0.0-inline-prototype-2023326232811",
3
+ "version": "0.0.0-master-20240328032403",
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",
7
+ "preconstruct": {
8
+ "entrypoints": [
9
+ "index.ts"
10
+ ]
11
+ },
7
12
  "files": [
8
13
  "/dist"
9
14
  ],
@@ -15,13 +20,13 @@
15
20
  "author": "SEEK",
16
21
  "license": "MIT",
17
22
  "dependencies": {
18
- "@vanilla-extract/webpack-plugin": "^0.0.0-inline-prototype-2023326232811",
19
- "browserslist": "^4.19.1"
23
+ "@vanilla-extract/webpack-plugin": "^2.3.7"
20
24
  },
21
25
  "peerDependencies": {
22
- "next": ">=12.0.5"
26
+ "next": ">=12.1.7"
23
27
  },
24
28
  "devDependencies": {
25
- "next": "^12.0.5"
29
+ "next": "12.3.4",
30
+ "webpack": "^5.90.0"
26
31
  }
27
32
  }