2022-09-27 20:10:05 +02:00
|
|
|
import path from 'path'
|
2020-03-29 01:43:59 +01:00
|
|
|
import curry from 'next/dist/compiled/lodash.curry'
|
2021-10-07 01:46:46 +02:00
|
|
|
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
2020-01-13 13:48:24 +01:00
|
|
|
import { loader, plugin } from '../../helpers'
|
2019-12-09 21:08:15 +01:00
|
|
|
import { ConfigurationContext, ConfigurationFn, pipe } from '../../utils'
|
2020-01-22 16:50:27 +01:00
|
|
|
import { getCssModuleLoader, getGlobalCssLoader } from './loaders'
|
2022-09-22 07:12:59 +02:00
|
|
|
import { getFontLoader } from './loaders/font-loader'
|
2019-12-27 19:35:37 +01:00
|
|
|
import {
|
2020-01-14 20:53:42 +01:00
|
|
|
getCustomDocumentError,
|
2019-12-27 19:35:37 +01:00
|
|
|
getGlobalImportError,
|
|
|
|
getGlobalModuleImportError,
|
|
|
|
getLocalModuleImportError,
|
|
|
|
} from './messages'
|
2019-12-09 21:08:15 +01:00
|
|
|
import { getPostCssPlugins } from './plugins'
|
2022-11-10 01:28:48 +01:00
|
|
|
import { nonNullable } from '../../../../../lib/non-nullable'
|
|
|
|
import { WEBPACK_LAYERS } from '../../../../../lib/constants'
|
2019-12-09 21:08:15 +01:00
|
|
|
|
2020-01-22 21:26:51 +01:00
|
|
|
// RegExps for all Style Sheet variants
|
2021-09-06 10:59:23 +02:00
|
|
|
export const regexLikeCss = /\.(css|scss|sass)$/
|
2020-01-22 21:26:51 +01:00
|
|
|
|
|
|
|
// RegExps for Style Sheets
|
2020-01-22 15:50:30 +01:00
|
|
|
const regexCssGlobal = /(?<!\.module)\.css$/
|
|
|
|
const regexCssModules = /\.module\.css$/
|
|
|
|
|
2020-01-22 21:26:51 +01:00
|
|
|
// RegExps for Syntactically Awesome Style Sheets
|
|
|
|
const regexSassGlobal = /(?<!\.module)\.(scss|sass)$/
|
|
|
|
const regexSassModules = /\.module\.(scss|sass)$/
|
|
|
|
|
2021-11-29 15:19:39 +01:00
|
|
|
/**
|
|
|
|
* Mark a rule as removable if built-in CSS support is disabled
|
|
|
|
*
|
|
|
|
* @param {webpack.RuleSetRule} r the rule to mark
|
|
|
|
*
|
|
|
|
* @returns {webpack.RuleSetRule} the marked rule
|
|
|
|
*/
|
|
|
|
function markRemovable(r: webpack.RuleSetRule): webpack.RuleSetRule {
|
|
|
|
Object.defineProperty(r, Symbol.for('__next_css_remove'), {
|
|
|
|
enumerable: false,
|
|
|
|
value: true,
|
|
|
|
})
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2021-11-25 18:41:20 +01:00
|
|
|
let postcssInstancePromise: Promise<any>
|
|
|
|
export async function lazyPostCSS(
|
|
|
|
rootDirectory: string,
|
|
|
|
supportedBrowsers: string[] | undefined,
|
|
|
|
disablePostcssPresetEnv: boolean | undefined
|
|
|
|
) {
|
|
|
|
if (!postcssInstancePromise) {
|
|
|
|
postcssInstancePromise = (async () => {
|
|
|
|
const postcss = require('postcss')
|
|
|
|
// @ts-ignore backwards compat
|
|
|
|
postcss.plugin = function postcssPlugin(name, initializer) {
|
|
|
|
function creator(...args: any) {
|
|
|
|
let transformer = initializer(...args)
|
|
|
|
transformer.postcssPlugin = name
|
|
|
|
// transformer.postcssVersion = new Processor().version
|
|
|
|
return transformer
|
|
|
|
}
|
|
|
|
|
|
|
|
let cache: any
|
|
|
|
Object.defineProperty(creator, 'postcss', {
|
|
|
|
get() {
|
|
|
|
if (!cache) cache = creator()
|
|
|
|
return cache
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
creator.process = function (
|
|
|
|
css: any,
|
|
|
|
processOpts: any,
|
|
|
|
pluginOpts: any
|
|
|
|
) {
|
|
|
|
return postcss([creator(pluginOpts)]).process(css, processOpts)
|
|
|
|
}
|
|
|
|
|
|
|
|
return creator
|
|
|
|
}
|
|
|
|
|
|
|
|
// @ts-ignore backwards compat
|
|
|
|
postcss.vendor = {
|
|
|
|
/**
|
|
|
|
* Returns the vendor prefix extracted from an input string.
|
|
|
|
*
|
|
|
|
* @param {string} prop String with or without vendor prefix.
|
|
|
|
*
|
|
|
|
* @return {string} vendor prefix or empty string
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* postcss.vendor.prefix('-moz-tab-size') //=> '-moz-'
|
|
|
|
* postcss.vendor.prefix('tab-size') //=> ''
|
|
|
|
*/
|
|
|
|
prefix: function prefix(prop: any) {
|
|
|
|
const match = prop.match(/^(-\w+-)/)
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
return match[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
return ''
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the input string stripped of its vendor prefix.
|
|
|
|
*
|
|
|
|
* @param {string} prop String with or without vendor prefix.
|
|
|
|
*
|
|
|
|
* @return {string} String name without vendor prefixes.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* postcss.vendor.unprefixed('-moz-tab-size') //=> 'tab-size'
|
|
|
|
*/
|
|
|
|
unprefixed: function unprefixed(prop: any) {
|
|
|
|
return prop.replace(/^-\w+-/, '')
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
const postCssPlugins = await getPostCssPlugins(
|
|
|
|
rootDirectory,
|
|
|
|
supportedBrowsers,
|
|
|
|
disablePostcssPresetEnv
|
|
|
|
)
|
|
|
|
|
|
|
|
return {
|
|
|
|
postcss,
|
|
|
|
postcssWithPlugins: postcss(postCssPlugins),
|
|
|
|
}
|
|
|
|
})()
|
|
|
|
}
|
|
|
|
|
|
|
|
return postcssInstancePromise
|
|
|
|
}
|
|
|
|
|
2019-12-09 21:08:15 +01:00
|
|
|
export const css = curry(async function css(
|
|
|
|
ctx: ConfigurationContext,
|
2021-01-14 02:59:08 +01:00
|
|
|
config: webpack.Configuration
|
2019-12-09 21:08:15 +01:00
|
|
|
) {
|
2020-09-11 14:36:48 +02:00
|
|
|
const {
|
|
|
|
prependData: sassPrependData,
|
|
|
|
additionalData: sassAdditionalData,
|
|
|
|
...sassOptions
|
|
|
|
} = ctx.sassOptions
|
2020-05-23 15:37:48 +02:00
|
|
|
|
2022-01-02 23:16:17 +01:00
|
|
|
const lazyPostCSSInitializer = () =>
|
2021-11-25 18:41:20 +01:00
|
|
|
lazyPostCSS(
|
|
|
|
ctx.rootDirectory,
|
|
|
|
ctx.supportedBrowsers,
|
|
|
|
ctx.experimental.disablePostcssPresetEnv
|
|
|
|
)
|
|
|
|
|
2020-01-22 21:26:51 +01:00
|
|
|
const sassPreprocessors: webpack.RuleSetUseItem[] = [
|
|
|
|
// First, process files with `sass-loader`: this inlines content, and
|
|
|
|
// compiles away the proprietary syntax.
|
|
|
|
{
|
2021-01-14 02:59:08 +01:00
|
|
|
loader: require.resolve('next/dist/compiled/sass-loader'),
|
2020-01-22 21:26:51 +01:00
|
|
|
options: {
|
|
|
|
// Source maps are required so that `resolve-url-loader` can locate
|
|
|
|
// files original to their source directory.
|
|
|
|
sourceMap: true,
|
2020-05-23 15:37:48 +02:00
|
|
|
sassOptions,
|
2020-09-11 14:36:48 +02:00
|
|
|
additionalData: sassPrependData || sassAdditionalData,
|
2020-01-22 21:26:51 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
// Then, `sass-loader` will have passed-through CSS imports as-is instead
|
|
|
|
// of inlining them. Because they were inlined, the paths are no longer
|
|
|
|
// correct.
|
|
|
|
// To fix this, we use `resolve-url-loader` to rewrite the CSS
|
|
|
|
// imports to real file paths.
|
|
|
|
{
|
2022-01-02 23:16:17 +01:00
|
|
|
loader: require.resolve('../../../loaders/resolve-url-loader/index'),
|
2020-01-22 21:26:51 +01:00
|
|
|
options: {
|
2022-01-02 23:16:17 +01:00
|
|
|
postcss: lazyPostCSSInitializer,
|
2020-01-22 21:26:51 +01:00
|
|
|
// Source maps are not required here, but we may as well emit
|
|
|
|
// them.
|
|
|
|
sourceMap: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
2021-11-29 15:19:39 +01:00
|
|
|
const fns: ConfigurationFn[] = []
|
2019-12-09 21:08:15 +01:00
|
|
|
|
2022-09-22 07:12:59 +02:00
|
|
|
// Resolve the configured font loaders, the resolved files are noop files that next-font-loader will match
|
|
|
|
let fontLoaders: [string, string][] | undefined = ctx.experimental.fontLoaders
|
2022-10-07 11:15:57 +02:00
|
|
|
? ctx.experimental.fontLoaders.map(({ loader: fontLoader, options }) => [
|
|
|
|
path.join(require.resolve(fontLoader), '../target.css'),
|
|
|
|
options,
|
|
|
|
])
|
2022-09-22 07:12:59 +02:00
|
|
|
: undefined
|
|
|
|
|
|
|
|
// Font loaders cannot be imported in _document.
|
|
|
|
fontLoaders?.forEach(([fontLoaderPath, fontLoaderOptions]) => {
|
|
|
|
// Matches the resolved font loaders noop files to run next-font-loader
|
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
markRemovable({
|
|
|
|
sideEffects: false,
|
|
|
|
test: fontLoaderPath,
|
|
|
|
use: getFontLoader(ctx, lazyPostCSSInitializer, fontLoaderOptions),
|
|
|
|
}),
|
2022-10-07 11:15:57 +02:00
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
2022-09-22 07:12:59 +02:00
|
|
|
})
|
|
|
|
|
2022-09-27 20:10:05 +02:00
|
|
|
// CSS cannot be imported in _document. This comes before everything because
|
|
|
|
// global CSS nor CSS modules work in said file.
|
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
markRemovable({
|
|
|
|
test: regexLikeCss,
|
|
|
|
// Use a loose regex so we don't have to crawl the file system to
|
|
|
|
// find the real file name (if present).
|
|
|
|
issuer: /pages[\\/]_document\./,
|
|
|
|
use: {
|
|
|
|
loader: 'error-loader',
|
|
|
|
options: {
|
|
|
|
reason: getCustomDocumentError(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
2022-11-10 01:28:48 +01:00
|
|
|
const shouldIncludeExternalCSSImports =
|
|
|
|
!!ctx.experimental.craCompat || !!ctx.experimental.transpilePackages
|
2022-10-31 16:44:48 +01:00
|
|
|
|
2022-11-10 01:28:48 +01:00
|
|
|
// CSS modules & SASS modules support. They are allowed to be imported in anywhere.
|
|
|
|
fns.push(
|
|
|
|
// CSS Modules should never have side effects. This setting will
|
|
|
|
// allow unused CSS to be removed from the production build.
|
|
|
|
// We ensure this by disallowing `:global()` CSS at the top-level
|
|
|
|
// via the `pure` mode in `css-loader`.
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
// For app dir, it has to match one of the 2 layers and then apply a
|
|
|
|
// specific loader.
|
|
|
|
ctx.hasAppDir && !ctx.isProduction
|
|
|
|
? markRemovable({
|
|
|
|
sideEffects: false,
|
|
|
|
test: regexCssModules,
|
|
|
|
issuerLayer: {
|
|
|
|
or: [WEBPACK_LAYERS.server, WEBPACK_LAYERS.client],
|
2022-07-12 11:42:46 +02:00
|
|
|
},
|
2022-08-25 18:40:16 +02:00
|
|
|
use: [
|
|
|
|
require.resolve('../../../loaders/next-flight-css-dev-loader'),
|
2022-11-10 01:28:48 +01:00
|
|
|
...getCssModuleLoader(ctx, lazyPostCSSInitializer),
|
2022-08-25 18:40:16 +02:00
|
|
|
],
|
2022-11-10 01:28:48 +01:00
|
|
|
})
|
|
|
|
: null,
|
|
|
|
ctx.hasAppDir && !ctx.isServer
|
|
|
|
? markRemovable({
|
|
|
|
sideEffects: false,
|
|
|
|
test: regexCssModules,
|
2022-10-24 04:05:55 +02:00
|
|
|
use: [
|
|
|
|
require.resolve('../../../loaders/next-flight-css-dev-loader'),
|
2022-11-10 01:28:48 +01:00
|
|
|
...getCssModuleLoader(ctx, lazyPostCSSInitializer),
|
2022-10-24 04:05:55 +02:00
|
|
|
],
|
2022-11-10 01:28:48 +01:00
|
|
|
})
|
|
|
|
: null,
|
|
|
|
markRemovable({
|
|
|
|
sideEffects: false,
|
|
|
|
test: regexCssModules,
|
|
|
|
use: getCssModuleLoader(ctx, lazyPostCSSInitializer),
|
|
|
|
}),
|
|
|
|
].filter(nonNullable),
|
|
|
|
}),
|
|
|
|
// Opt-in support for Sass (using .scss or .sass extensions).
|
|
|
|
// Sass Modules should never have side effects. This setting will
|
|
|
|
// allow unused Sass to be removed from the production build.
|
|
|
|
// We ensure this by disallowing `:global()` Sass at the top-level
|
|
|
|
// via the `pure` mode in `css-loader`.
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
// For app dir, we match both server and client layers.
|
|
|
|
ctx.hasAppDir && !ctx.isProduction
|
|
|
|
? markRemovable({
|
2022-08-25 18:40:16 +02:00
|
|
|
sideEffects: false,
|
2022-11-10 01:28:48 +01:00
|
|
|
test: regexSassModules,
|
|
|
|
issuerLayer: {
|
|
|
|
or: [WEBPACK_LAYERS.server, WEBPACK_LAYERS.client],
|
|
|
|
},
|
2022-08-25 18:40:16 +02:00
|
|
|
use: [
|
|
|
|
require.resolve('../../../loaders/next-flight-css-dev-loader'),
|
2022-11-10 01:28:48 +01:00
|
|
|
...getCssModuleLoader(
|
|
|
|
ctx,
|
|
|
|
lazyPostCSSInitializer,
|
|
|
|
sassPreprocessors
|
|
|
|
),
|
2022-08-25 18:40:16 +02:00
|
|
|
],
|
2022-11-10 01:28:48 +01:00
|
|
|
})
|
|
|
|
: null,
|
|
|
|
ctx.hasAppDir && !ctx.isServer
|
|
|
|
? markRemovable({
|
2022-10-24 04:05:55 +02:00
|
|
|
sideEffects: false,
|
|
|
|
test: regexSassModules,
|
|
|
|
use: [
|
|
|
|
require.resolve('../../../loaders/next-flight-css-dev-loader'),
|
|
|
|
...getCssModuleLoader(
|
|
|
|
ctx,
|
|
|
|
lazyPostCSSInitializer,
|
|
|
|
sassPreprocessors
|
|
|
|
),
|
|
|
|
],
|
2022-11-10 01:28:48 +01:00
|
|
|
})
|
|
|
|
: null,
|
|
|
|
markRemovable({
|
|
|
|
sideEffects: false,
|
|
|
|
test: regexSassModules,
|
|
|
|
use: getCssModuleLoader(
|
|
|
|
ctx,
|
|
|
|
lazyPostCSSInitializer,
|
|
|
|
sassPreprocessors
|
|
|
|
),
|
|
|
|
}),
|
|
|
|
].filter(nonNullable),
|
|
|
|
}),
|
|
|
|
// Throw an error for CSS Modules used outside their supported scope
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
markRemovable({
|
|
|
|
test: [regexCssModules, regexSassModules],
|
|
|
|
use: {
|
|
|
|
loader: 'error-loader',
|
|
|
|
options: {
|
|
|
|
reason: getLocalModuleImportError(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
// Global CSS and SASS support.
|
|
|
|
if (ctx.isServer) {
|
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
ctx.hasAppDir && !ctx.isProduction
|
|
|
|
? markRemovable({
|
|
|
|
sideEffects: true,
|
|
|
|
test: [regexCssGlobal, regexSassGlobal],
|
|
|
|
issuerLayer: {
|
|
|
|
or: [WEBPACK_LAYERS.server, WEBPACK_LAYERS.client],
|
|
|
|
},
|
|
|
|
use: require.resolve(
|
|
|
|
'../../../loaders/next-flight-css-dev-loader'
|
|
|
|
),
|
|
|
|
})
|
|
|
|
: null,
|
|
|
|
markRemovable({
|
|
|
|
// CSS imports have side effects, even on the server side.
|
|
|
|
sideEffects: true,
|
|
|
|
test: [regexCssGlobal, regexSassGlobal],
|
|
|
|
use: require.resolve('next/dist/compiled/ignore-loader'),
|
|
|
|
}),
|
|
|
|
].filter(nonNullable),
|
|
|
|
})
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
// They are allowed to be loaded when any of the following is true:
|
|
|
|
// - hasAppDir: If the issuerLayer is RSC
|
|
|
|
// - If the CSS file is located in `node_modules`
|
|
|
|
// - If the CSS file is located in another package in a monorepo (outside of the current rootDir)
|
|
|
|
// - If the issuer is pages/_app (matched later)
|
|
|
|
const allowedExternalCSSImports = {
|
|
|
|
and: [
|
|
|
|
{
|
|
|
|
or: [
|
|
|
|
/node_modules/,
|
|
|
|
{
|
|
|
|
not: [ctx.rootDirectory],
|
|
|
|
},
|
2022-07-06 01:07:13 +02:00
|
|
|
],
|
2022-11-10 01:28:48 +01:00
|
|
|
},
|
|
|
|
],
|
|
|
|
}
|
2022-08-25 18:40:16 +02:00
|
|
|
|
2022-11-10 01:28:48 +01:00
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
ctx.hasAppDir
|
|
|
|
? markRemovable({
|
|
|
|
sideEffects: true,
|
|
|
|
test: regexCssGlobal,
|
|
|
|
use: [
|
|
|
|
require.resolve(
|
|
|
|
'../../../loaders/next-flight-css-dev-loader'
|
|
|
|
),
|
|
|
|
...getGlobalCssLoader(ctx, lazyPostCSSInitializer),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
: null,
|
|
|
|
ctx.hasAppDir
|
|
|
|
? markRemovable({
|
|
|
|
sideEffects: true,
|
|
|
|
test: regexSassGlobal,
|
|
|
|
use: [
|
|
|
|
require.resolve(
|
|
|
|
'../../../loaders/next-flight-css-dev-loader'
|
|
|
|
),
|
|
|
|
...getGlobalCssLoader(
|
|
|
|
ctx,
|
|
|
|
lazyPostCSSInitializer,
|
|
|
|
sassPreprocessors
|
|
|
|
),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
: null,
|
|
|
|
!ctx.hasAppDir
|
|
|
|
? markRemovable({
|
2022-08-25 18:40:16 +02:00
|
|
|
sideEffects: true,
|
|
|
|
test: regexCssGlobal,
|
2022-11-10 01:28:48 +01:00
|
|
|
include: allowedExternalCSSImports,
|
|
|
|
issuer: shouldIncludeExternalCSSImports
|
|
|
|
? undefined
|
|
|
|
: {
|
|
|
|
and: [ctx.rootDirectory],
|
|
|
|
not: [/node_modules/],
|
|
|
|
},
|
2022-08-25 18:40:16 +02:00
|
|
|
use: getGlobalCssLoader(ctx, lazyPostCSSInitializer),
|
2022-11-10 01:28:48 +01:00
|
|
|
})
|
|
|
|
: null,
|
|
|
|
!ctx.hasAppDir
|
|
|
|
? markRemovable({
|
2022-08-25 18:40:16 +02:00
|
|
|
sideEffects: true,
|
|
|
|
test: regexSassGlobal,
|
2022-11-10 01:28:48 +01:00
|
|
|
include: allowedExternalCSSImports,
|
|
|
|
issuer: shouldIncludeExternalCSSImports
|
|
|
|
? undefined
|
|
|
|
: {
|
|
|
|
and: [ctx.rootDirectory],
|
|
|
|
not: [/node_modules/],
|
|
|
|
},
|
2022-08-25 18:40:16 +02:00
|
|
|
use: getGlobalCssLoader(
|
|
|
|
ctx,
|
|
|
|
lazyPostCSSInitializer,
|
|
|
|
sassPreprocessors
|
|
|
|
),
|
2022-11-10 01:28:48 +01:00
|
|
|
})
|
|
|
|
: null,
|
|
|
|
].filter(nonNullable),
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
if (ctx.customAppFile) {
|
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
markRemovable({
|
|
|
|
sideEffects: true,
|
|
|
|
test: regexCssGlobal,
|
|
|
|
issuer: { and: [ctx.customAppFile] },
|
|
|
|
use: getGlobalCssLoader(ctx, lazyPostCSSInitializer),
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
}),
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
|
|
|
markRemovable({
|
|
|
|
sideEffects: true,
|
|
|
|
test: regexSassGlobal,
|
|
|
|
issuer: { and: [ctx.customAppFile] },
|
|
|
|
use: getGlobalCssLoader(
|
|
|
|
ctx,
|
|
|
|
lazyPostCSSInitializer,
|
|
|
|
sassPreprocessors
|
|
|
|
),
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
2022-07-06 01:07:13 +02:00
|
|
|
}
|
2019-12-09 21:08:15 +01:00
|
|
|
}
|
|
|
|
|
2019-12-27 19:35:37 +01:00
|
|
|
// Throw an error for Global CSS used inside of `node_modules`
|
2022-11-10 01:28:48 +01:00
|
|
|
if (!shouldIncludeExternalCSSImports) {
|
2021-06-09 16:51:56 +02:00
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
2021-11-29 15:19:39 +01:00
|
|
|
markRemovable({
|
2021-06-09 16:51:56 +02:00
|
|
|
test: [regexCssGlobal, regexSassGlobal],
|
|
|
|
issuer: { and: [/node_modules/] },
|
|
|
|
use: {
|
|
|
|
loader: 'error-loader',
|
|
|
|
options: {
|
|
|
|
reason: getGlobalModuleImportError(),
|
|
|
|
},
|
2019-12-27 19:35:37 +01:00
|
|
|
},
|
2021-11-29 15:19:39 +01:00
|
|
|
}),
|
2021-06-09 16:51:56 +02:00
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2019-12-27 19:35:37 +01:00
|
|
|
|
2019-12-09 21:08:15 +01:00
|
|
|
// Throw an error for Global CSS used outside of our custom <App> file
|
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
2021-11-29 15:19:39 +01:00
|
|
|
markRemovable({
|
2020-09-10 19:45:30 +02:00
|
|
|
test: [regexCssGlobal, regexSassGlobal],
|
2022-10-05 00:16:44 +02:00
|
|
|
issuer: ctx.hasAppDir
|
2022-07-06 01:07:13 +02:00
|
|
|
? {
|
|
|
|
// If it's inside the app dir, but not importing from a layout file,
|
|
|
|
// throw an error.
|
2022-07-18 17:27:48 +02:00
|
|
|
and: [ctx.rootDirectory],
|
2022-09-18 02:00:16 +02:00
|
|
|
not: [/layout\.(js|mjs|jsx|ts|tsx)$/],
|
2022-07-06 01:07:13 +02:00
|
|
|
}
|
|
|
|
: undefined,
|
2019-12-09 21:08:15 +01:00
|
|
|
use: {
|
|
|
|
loader: 'error-loader',
|
|
|
|
options: {
|
2021-08-19 10:12:12 +02:00
|
|
|
reason: getGlobalImportError(),
|
2019-12-09 21:08:15 +01:00
|
|
|
},
|
|
|
|
},
|
2021-11-29 15:19:39 +01:00
|
|
|
}),
|
2019-12-09 21:08:15 +01:00
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
2019-12-26 23:17:37 +01:00
|
|
|
if (ctx.isClient) {
|
|
|
|
// Automatically transform references to files (i.e. url()) into URLs
|
|
|
|
// e.g. url(./logo.svg)
|
|
|
|
fns.push(
|
|
|
|
loader({
|
|
|
|
oneOf: [
|
2021-11-29 15:19:39 +01:00
|
|
|
markRemovable({
|
2019-12-26 23:17:37 +01:00
|
|
|
// This should only be applied to CSS files
|
2020-06-17 17:00:29 +02:00
|
|
|
issuer: regexLikeCss,
|
2019-12-26 23:17:37 +01:00
|
|
|
// Exclude extensions that webpack handles by default
|
2021-05-12 18:04:01 +02:00
|
|
|
exclude: [
|
|
|
|
/\.(js|mjs|jsx|ts|tsx)$/,
|
|
|
|
/\.html$/,
|
|
|
|
/\.json$/,
|
|
|
|
/\.webpack\[[^\]]+\]$/,
|
|
|
|
],
|
2021-10-25 01:54:16 +02:00
|
|
|
// `asset/resource` always emits a URL reference, where `asset`
|
|
|
|
// might inline the asset as a data URI
|
|
|
|
type: 'asset/resource',
|
2021-11-29 15:19:39 +01:00
|
|
|
}),
|
2019-12-26 23:17:37 +01:00
|
|
|
],
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2019-12-09 21:08:15 +01:00
|
|
|
|
2022-07-21 14:38:04 +02:00
|
|
|
// Enable full mini-css-extract-plugin hmr for prod mode pages or app dir
|
2022-10-05 00:16:44 +02:00
|
|
|
if (ctx.isClient && (ctx.isProduction || ctx.hasAppDir)) {
|
2020-01-13 13:48:24 +01:00
|
|
|
// Extract CSS as CSS file(s) in the client-side production bundle.
|
2022-06-03 20:47:16 +02:00
|
|
|
const MiniCssExtractPlugin =
|
|
|
|
require('../../../plugins/mini-css-extract-plugin').default
|
2020-01-13 13:48:24 +01:00
|
|
|
fns.push(
|
|
|
|
plugin(
|
2020-07-15 19:56:27 +02:00
|
|
|
// @ts-ignore webpack 5 compat
|
2020-01-13 13:48:24 +01:00
|
|
|
new MiniCssExtractPlugin({
|
2022-07-21 14:38:04 +02:00
|
|
|
filename: ctx.isProduction
|
|
|
|
? 'static/css/[contenthash].css'
|
|
|
|
: 'static/css/[name].css',
|
|
|
|
chunkFilename: ctx.isProduction
|
|
|
|
? 'static/css/[contenthash].css'
|
|
|
|
: 'static/css/[name].css',
|
2020-01-22 15:50:30 +01:00
|
|
|
// Next.js guarantees that CSS order "doesn't matter", due to imposed
|
2020-01-13 13:48:24 +01:00
|
|
|
// restrictions:
|
|
|
|
// 1. Global CSS can only be defined in a single entrypoint (_app)
|
|
|
|
// 2. CSS Modules generate scoped class names by default and cannot
|
|
|
|
// include Global CSS (:global() selector).
|
|
|
|
//
|
2020-01-22 15:50:30 +01:00
|
|
|
// While not a perfect guarantee (e.g. liberal use of `:global()`
|
|
|
|
// selector), this assumption is required to code-split CSS.
|
|
|
|
//
|
2020-01-13 13:48:24 +01:00
|
|
|
// If this warning were to trigger, it'd be unactionable by the user,
|
2020-09-10 19:45:30 +02:00
|
|
|
// but likely not valid -- so we disable it.
|
2020-01-13 13:48:24 +01:00
|
|
|
ignoreOrder: true,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-12-09 21:08:15 +01:00
|
|
|
const fn = pipe(...fns)
|
|
|
|
return fn(config)
|
|
|
|
})
|