index.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.lazyPostCSS = lazyPostCSS;
  6. exports.css = exports.regexLikeCss = void 0;
  7. var _lodashCurry = _interopRequireDefault(require("next/dist/compiled/lodash.curry"));
  8. var _helpers = require("../../helpers");
  9. var _utils = require("../../utils");
  10. var _loaders = require("./loaders");
  11. var _messages = require("./messages");
  12. var _plugins = require("./plugins");
  13. function _interopRequireDefault(obj) {
  14. return obj && obj.__esModule ? obj : {
  15. default: obj
  16. };
  17. }
  18. const regexLikeCss = /\.(css|scss|sass)$/;
  19. exports.regexLikeCss = regexLikeCss;
  20. // RegExps for Style Sheets
  21. const regexCssGlobal = /(?<!\.module)\.css$/;
  22. const regexCssModules = /\.module\.css$/;
  23. // RegExps for Syntactically Awesome Style Sheets
  24. const regexSassGlobal = /(?<!\.module)\.(scss|sass)$/;
  25. const regexSassModules = /\.module\.(scss|sass)$/;
  26. // Also match the virtual client entry which doesn't have file path
  27. const regexClientEntry = /^$/;
  28. /**
  29. * Mark a rule as removable if built-in CSS support is disabled
  30. *
  31. * @param {webpack.RuleSetRule} r the rule to mark
  32. *
  33. * @returns {webpack.RuleSetRule} the marked rule
  34. */ function markRemovable(r) {
  35. Object.defineProperty(r, Symbol.for("__next_css_remove"), {
  36. enumerable: false,
  37. value: true
  38. });
  39. return r;
  40. }
  41. let postcssInstancePromise;
  42. async function lazyPostCSS(rootDirectory, supportedBrowsers, disablePostcssPresetEnv) {
  43. if (!postcssInstancePromise) {
  44. postcssInstancePromise = (async ()=>{
  45. const postcss = require("postcss");
  46. // @ts-ignore backwards compat
  47. postcss.plugin = function postcssPlugin(name, initializer) {
  48. function creator(...args) {
  49. let transformer = initializer(...args);
  50. transformer.postcssPlugin = name;
  51. // transformer.postcssVersion = new Processor().version
  52. return transformer;
  53. }
  54. let cache;
  55. Object.defineProperty(creator, "postcss", {
  56. get () {
  57. if (!cache) cache = creator();
  58. return cache;
  59. }
  60. });
  61. creator.process = function(css1, processOpts, pluginOpts) {
  62. return postcss([
  63. creator(pluginOpts)
  64. ]).process(css1, processOpts);
  65. };
  66. return creator;
  67. };
  68. // @ts-ignore backwards compat
  69. postcss.vendor = {
  70. /**
  71. * Returns the vendor prefix extracted from an input string.
  72. *
  73. * @param {string} prop String with or without vendor prefix.
  74. *
  75. * @return {string} vendor prefix or empty string
  76. *
  77. * @example
  78. * postcss.vendor.prefix('-moz-tab-size') //=> '-moz-'
  79. * postcss.vendor.prefix('tab-size') //=> ''
  80. */ prefix: function prefix(prop) {
  81. const match = prop.match(/^(-\w+-)/);
  82. if (match) {
  83. return match[0];
  84. }
  85. return "";
  86. },
  87. /**
  88. * Returns the input string stripped of its vendor prefix.
  89. *
  90. * @param {string} prop String with or without vendor prefix.
  91. *
  92. * @return {string} String name without vendor prefixes.
  93. *
  94. * @example
  95. * postcss.vendor.unprefixed('-moz-tab-size') //=> 'tab-size'
  96. */ unprefixed: function unprefixed(prop) {
  97. return prop.replace(/^-\w+-/, "");
  98. }
  99. };
  100. const postCssPlugins = await (0, _plugins).getPostCssPlugins(rootDirectory, supportedBrowsers, disablePostcssPresetEnv);
  101. return {
  102. postcss,
  103. postcssWithPlugins: postcss(postCssPlugins)
  104. };
  105. })();
  106. }
  107. return postcssInstancePromise;
  108. }
  109. const css = (0, _lodashCurry).default(async function css(ctx, config) {
  110. const { prependData: sassPrependData , additionalData: sassAdditionalData , ...sassOptions } = ctx.sassOptions;
  111. const lazyPostCSSInitializer = ()=>lazyPostCSS(ctx.rootDirectory, ctx.supportedBrowsers, ctx.experimental.disablePostcssPresetEnv);
  112. const sassPreprocessors = [
  113. // First, process files with `sass-loader`: this inlines content, and
  114. // compiles away the proprietary syntax.
  115. {
  116. loader: require.resolve("next/dist/compiled/sass-loader"),
  117. options: {
  118. // Source maps are required so that `resolve-url-loader` can locate
  119. // files original to their source directory.
  120. sourceMap: true,
  121. sassOptions,
  122. additionalData: sassPrependData || sassAdditionalData
  123. }
  124. },
  125. // Then, `sass-loader` will have passed-through CSS imports as-is instead
  126. // of inlining them. Because they were inlined, the paths are no longer
  127. // correct.
  128. // To fix this, we use `resolve-url-loader` to rewrite the CSS
  129. // imports to real file paths.
  130. {
  131. loader: require.resolve("../../../loaders/resolve-url-loader/index"),
  132. options: {
  133. postcss: lazyPostCSSInitializer,
  134. // Source maps are not required here, but we may as well emit
  135. // them.
  136. sourceMap: true
  137. }
  138. },
  139. ];
  140. const fns = [];
  141. // CSS cannot be imported in _document. This comes before everything because
  142. // global CSS nor CSS modules work in said file.
  143. fns.push((0, _helpers).loader({
  144. oneOf: [
  145. markRemovable({
  146. test: regexLikeCss,
  147. // Use a loose regex so we don't have to crawl the file system to
  148. // find the real file name (if present).
  149. issuer: /pages[\\/]_document\./,
  150. use: {
  151. loader: "error-loader",
  152. options: {
  153. reason: (0, _messages).getCustomDocumentError()
  154. }
  155. }
  156. }),
  157. ]
  158. }));
  159. // CSS Modules support must be enabled on the server and client so the class
  160. // names are available for SSR or Prerendering.
  161. if (ctx.experimental.appDir && !ctx.isProduction) {
  162. fns.push((0, _helpers).loader({
  163. oneOf: [
  164. markRemovable({
  165. // CSS Modules should never have side effects. This setting will
  166. // allow unused CSS to be removed from the production build.
  167. // We ensure this by disallowing `:global()` CSS at the top-level
  168. // via the `pure` mode in `css-loader`.
  169. sideEffects: false,
  170. // CSS Modules are activated via this specific extension.
  171. test: regexCssModules,
  172. // CSS Modules are only supported in the user's application. We're
  173. // not yet allowing CSS imports _within_ `node_modules`.
  174. issuer: {
  175. and: [
  176. {
  177. or: [
  178. ctx.rootDirectory,
  179. regexClientEntry
  180. ]
  181. },
  182. ],
  183. not: [
  184. /node_modules/
  185. ]
  186. },
  187. use: [
  188. require.resolve("../../../loaders/next-flight-css-dev-loader"),
  189. ...(0, _loaders).getCssModuleLoader(ctx, lazyPostCSSInitializer),
  190. ]
  191. }),
  192. ]
  193. }));
  194. fns.push((0, _helpers).loader({
  195. oneOf: [
  196. // Opt-in support for Sass (using .scss or .sass extensions).
  197. markRemovable({
  198. // Sass Modules should never have side effects. This setting will
  199. // allow unused Sass to be removed from the production build.
  200. // We ensure this by disallowing `:global()` Sass at the top-level
  201. // via the `pure` mode in `css-loader`.
  202. sideEffects: false,
  203. // Sass Modules are activated via this specific extension.
  204. test: regexSassModules,
  205. // Sass Modules are only supported in the user's application. We're
  206. // not yet allowing Sass imports _within_ `node_modules`.
  207. issuer: {
  208. and: [
  209. ctx.rootDirectory
  210. ],
  211. not: [
  212. /node_modules/
  213. ]
  214. },
  215. use: [
  216. require.resolve("../../../loaders/next-flight-css-dev-loader"),
  217. ...(0, _loaders).getCssModuleLoader(ctx, lazyPostCSSInitializer, sassPreprocessors),
  218. ]
  219. }),
  220. ]
  221. }));
  222. } else {
  223. fns.push((0, _helpers).loader({
  224. oneOf: [
  225. markRemovable({
  226. // CSS Modules should never have side effects. This setting will
  227. // allow unused CSS to be removed from the production build.
  228. // We ensure this by disallowing `:global()` CSS at the top-level
  229. // via the `pure` mode in `css-loader`.
  230. sideEffects: false,
  231. // CSS Modules are activated via this specific extension.
  232. test: regexCssModules,
  233. // CSS Modules are only supported in the user's application. We're
  234. // not yet allowing CSS imports _within_ `node_modules`.
  235. issuer: {
  236. and: [
  237. {
  238. or: [
  239. ctx.rootDirectory,
  240. regexClientEntry
  241. ]
  242. },
  243. ],
  244. not: [
  245. /node_modules/
  246. ]
  247. },
  248. use: (0, _loaders).getCssModuleLoader(ctx, lazyPostCSSInitializer)
  249. }),
  250. ]
  251. }));
  252. fns.push((0, _helpers).loader({
  253. oneOf: [
  254. // Opt-in support for Sass (using .scss or .sass extensions).
  255. markRemovable({
  256. // Sass Modules should never have side effects. This setting will
  257. // allow unused Sass to be removed from the production build.
  258. // We ensure this by disallowing `:global()` Sass at the top-level
  259. // via the `pure` mode in `css-loader`.
  260. sideEffects: false,
  261. // Sass Modules are activated via this specific extension.
  262. test: regexSassModules,
  263. // Sass Modules are only supported in the user's application. We're
  264. // not yet allowing Sass imports _within_ `node_modules`.
  265. issuer: {
  266. and: [
  267. ctx.rootDirectory
  268. ],
  269. not: [
  270. /node_modules/
  271. ]
  272. },
  273. use: (0, _loaders).getCssModuleLoader(ctx, lazyPostCSSInitializer, sassPreprocessors)
  274. }),
  275. ]
  276. }));
  277. }
  278. if (!ctx.experimental.appDir) {
  279. // Throw an error for CSS Modules used outside their supported scope
  280. fns.push((0, _helpers).loader({
  281. oneOf: [
  282. markRemovable({
  283. test: [
  284. regexCssModules,
  285. regexSassModules
  286. ],
  287. use: {
  288. loader: "error-loader",
  289. options: {
  290. reason: (0, _messages).getLocalModuleImportError()
  291. }
  292. }
  293. }),
  294. ]
  295. }));
  296. }
  297. if (ctx.isServer) {
  298. if (ctx.experimental.appDir && !ctx.isProduction) {
  299. fns.push((0, _helpers).loader({
  300. oneOf: [
  301. markRemovable({
  302. sideEffects: true,
  303. test: [
  304. regexCssGlobal,
  305. regexSassGlobal
  306. ],
  307. use: require.resolve("../../../loaders/next-flight-css-dev-loader")
  308. }),
  309. ]
  310. }));
  311. } else {
  312. fns.push((0, _helpers).loader({
  313. oneOf: [
  314. markRemovable({
  315. test: [
  316. regexCssGlobal,
  317. regexSassGlobal
  318. ],
  319. use: require.resolve("next/dist/compiled/ignore-loader")
  320. }),
  321. ]
  322. }));
  323. }
  324. } else {
  325. if (ctx.experimental.appDir) {
  326. fns.push((0, _helpers).loader({
  327. oneOf: [
  328. markRemovable({
  329. // A global CSS import always has side effects. Webpack will tree
  330. // shake the CSS without this option if the issuer claims to have
  331. // no side-effects.
  332. // See https://github.com/webpack/webpack/issues/6571
  333. sideEffects: true,
  334. test: regexCssGlobal,
  335. use: [
  336. require.resolve("../../../loaders/next-flight-css-dev-loader"),
  337. ...(0, _loaders).getGlobalCssLoader(ctx, lazyPostCSSInitializer),
  338. ]
  339. }),
  340. ]
  341. }));
  342. fns.push((0, _helpers).loader({
  343. oneOf: [
  344. markRemovable({
  345. sideEffects: false,
  346. test: regexCssModules,
  347. use: [
  348. require.resolve("../../../loaders/next-flight-css-dev-loader"),
  349. ...(0, _loaders).getCssModuleLoader(ctx, lazyPostCSSInitializer),
  350. ]
  351. }),
  352. ]
  353. }));
  354. } else {
  355. fns.push((0, _helpers).loader({
  356. oneOf: [
  357. markRemovable({
  358. // A global CSS import always has side effects. Webpack will tree
  359. // shake the CSS without this option if the issuer claims to have
  360. // no side-effects.
  361. // See https://github.com/webpack/webpack/issues/6571
  362. sideEffects: true,
  363. test: regexCssGlobal,
  364. // We only allow Global CSS to be imported anywhere in the
  365. // application if it comes from node_modules. This is a best-effort
  366. // heuristic that makes a safety trade-off for better
  367. // interoperability with npm packages that require CSS. Without
  368. // this ability, the component's CSS would have to be included for
  369. // the entire app instead of specific page where it's required.
  370. include: {
  371. and: [
  372. /node_modules/
  373. ]
  374. },
  375. // Global CSS is only supported in the user's application, not in
  376. // node_modules.
  377. issuer: ctx.experimental.craCompat ? undefined : {
  378. and: [
  379. ctx.rootDirectory
  380. ],
  381. not: [
  382. /node_modules/
  383. ]
  384. },
  385. use: (0, _loaders).getGlobalCssLoader(ctx, lazyPostCSSInitializer)
  386. }),
  387. ]
  388. }));
  389. if (ctx.customAppFile) {
  390. fns.push((0, _helpers).loader({
  391. oneOf: [
  392. markRemovable({
  393. // A global CSS import always has side effects. Webpack will tree
  394. // shake the CSS without this option if the issuer claims to have
  395. // no side-effects.
  396. // See https://github.com/webpack/webpack/issues/6571
  397. sideEffects: true,
  398. test: regexCssGlobal,
  399. issuer: {
  400. and: [
  401. ctx.customAppFile
  402. ]
  403. },
  404. use: (0, _loaders).getGlobalCssLoader(ctx, lazyPostCSSInitializer)
  405. }),
  406. ]
  407. }));
  408. fns.push((0, _helpers).loader({
  409. oneOf: [
  410. markRemovable({
  411. // A global Sass import always has side effects. Webpack will tree
  412. // shake the Sass without this option if the issuer claims to have
  413. // no side-effects.
  414. // See https://github.com/webpack/webpack/issues/6571
  415. sideEffects: true,
  416. test: regexSassGlobal,
  417. issuer: {
  418. and: [
  419. ctx.customAppFile
  420. ]
  421. },
  422. use: (0, _loaders).getGlobalCssLoader(ctx, lazyPostCSSInitializer, sassPreprocessors)
  423. }),
  424. ]
  425. }));
  426. }
  427. }
  428. }
  429. // Throw an error for Global CSS used inside of `node_modules`
  430. if (!ctx.experimental.craCompat) {
  431. fns.push((0, _helpers).loader({
  432. oneOf: [
  433. markRemovable({
  434. test: [
  435. regexCssGlobal,
  436. regexSassGlobal
  437. ],
  438. issuer: {
  439. and: [
  440. /node_modules/
  441. ]
  442. },
  443. use: {
  444. loader: "error-loader",
  445. options: {
  446. reason: (0, _messages).getGlobalModuleImportError()
  447. }
  448. }
  449. }),
  450. ]
  451. }));
  452. }
  453. // Throw an error for Global CSS used outside of our custom <App> file
  454. fns.push((0, _helpers).loader({
  455. oneOf: [
  456. markRemovable({
  457. test: [
  458. regexCssGlobal,
  459. regexSassGlobal
  460. ],
  461. issuer: ctx.experimental.appDir ? {
  462. // If it's inside the app dir, but not importing from a layout file,
  463. // throw an error.
  464. and: [
  465. ctx.rootDirectory
  466. ],
  467. not: [
  468. /layout\.(js|mjs|jsx|ts|tsx)$/
  469. ]
  470. } : undefined,
  471. use: {
  472. loader: "error-loader",
  473. options: {
  474. reason: (0, _messages).getGlobalImportError()
  475. }
  476. }
  477. }),
  478. ]
  479. }));
  480. if (ctx.isClient) {
  481. // Automatically transform references to files (i.e. url()) into URLs
  482. // e.g. url(./logo.svg)
  483. fns.push((0, _helpers).loader({
  484. oneOf: [
  485. markRemovable({
  486. // This should only be applied to CSS files
  487. issuer: regexLikeCss,
  488. // Exclude extensions that webpack handles by default
  489. exclude: [
  490. /\.(js|mjs|jsx|ts|tsx)$/,
  491. /\.html$/,
  492. /\.json$/,
  493. /\.webpack\[[^\]]+\]$/,
  494. ],
  495. // `asset/resource` always emits a URL reference, where `asset`
  496. // might inline the asset as a data URI
  497. type: "asset/resource"
  498. }),
  499. ]
  500. }));
  501. }
  502. // Enable full mini-css-extract-plugin hmr for prod mode pages or app dir
  503. if (ctx.isClient && (ctx.isProduction || ctx.experimental.appDir)) {
  504. // Extract CSS as CSS file(s) in the client-side production bundle.
  505. const MiniCssExtractPlugin = require("../../../plugins/mini-css-extract-plugin").default;
  506. fns.push((0, _helpers).plugin(// @ts-ignore webpack 5 compat
  507. new MiniCssExtractPlugin({
  508. filename: ctx.isProduction ? "static/css/[contenthash].css" : "static/css/[name].css",
  509. chunkFilename: ctx.isProduction ? "static/css/[contenthash].css" : "static/css/[name].css",
  510. // Next.js guarantees that CSS order "doesn't matter", due to imposed
  511. // restrictions:
  512. // 1. Global CSS can only be defined in a single entrypoint (_app)
  513. // 2. CSS Modules generate scoped class names by default and cannot
  514. // include Global CSS (:global() selector).
  515. //
  516. // While not a perfect guarantee (e.g. liberal use of `:global()`
  517. // selector), this assumption is required to code-split CSS.
  518. //
  519. // If this warning were to trigger, it'd be unactionable by the user,
  520. // but likely not valid -- so we disable it.
  521. ignoreOrder: true
  522. })));
  523. }
  524. const fn = (0, _utils).pipe(...fns);
  525. return fn(config);
  526. });
  527. exports.css = css;
  528. //# sourceMappingURL=index.js.map