Lazy-load postcss (#31762)
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: Tobias Koppers <tobias.koppers@googlemail.com>
This commit is contained in:
parent
a4159321b2
commit
92b397f2b7
12 changed files with 307 additions and 303 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -13,6 +13,7 @@ test/node_modules
|
|||
# logs & pids
|
||||
*.log
|
||||
pids
|
||||
*.cpuprofile
|
||||
|
||||
# coverage
|
||||
.nyc_output
|
||||
|
@ -41,4 +42,4 @@ test-timings.json
|
|||
.now
|
||||
|
||||
# Cache
|
||||
*.tsbuildinfo
|
||||
*.tsbuildinfo
|
||||
|
|
|
@ -33,7 +33,6 @@ import { NextConfigComplete } from '../server/config-shared'
|
|||
import { finalizeEntrypoint } from './entries'
|
||||
import * as Log from './output/log'
|
||||
import { build as buildConfiguration } from './webpack/config'
|
||||
import { __overrideCssConfiguration } from './webpack/config/blocks/css/overrideCssConfiguration'
|
||||
import MiddlewarePlugin from './webpack/plugins/middleware-plugin'
|
||||
import BuildManifestPlugin from './webpack/plugins/build-manifest-plugin'
|
||||
import { JsConfigPathsPlugin } from './webpack/plugins/jsconfig-paths-plugin'
|
||||
|
@ -1890,8 +1889,6 @@ export default async function getBaseWebpackConfig(
|
|||
(e) => (e as any).__next_css_remove !== true
|
||||
)
|
||||
}
|
||||
} else if (!config.future.strictPostcssConfiguration) {
|
||||
await __overrideCssConfiguration(dir, supportedBrowsers, webpackConfig)
|
||||
}
|
||||
|
||||
// Inject missing React Refresh loaders so that development mode is fast:
|
||||
|
|
|
@ -11,69 +11,6 @@ import {
|
|||
getLocalModuleImportError,
|
||||
} from './messages'
|
||||
import { getPostCssPlugins } from './plugins'
|
||||
import postcss from '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+-/, '')
|
||||
},
|
||||
}
|
||||
|
||||
// RegExps for all Style Sheet variants
|
||||
export const regexLikeCss = /\.(css|scss|sass)$/
|
||||
|
@ -86,6 +23,99 @@ const regexCssModules = /\.module\.css$/
|
|||
const regexSassGlobal = /(?<!\.module)\.(scss|sass)$/
|
||||
const regexSassModules = /\.module\.(scss|sass)$/
|
||||
|
||||
let postcssInstancePromise: Promise<any>
|
||||
export async function lazyPostCSS(
|
||||
rootDirectory: string,
|
||||
supportedBrowsers: string[] | undefined,
|
||||
strictPostcssConfiguration: boolean | 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,
|
||||
strictPostcssConfiguration,
|
||||
disablePostcssPresetEnv
|
||||
)
|
||||
|
||||
return {
|
||||
postcss,
|
||||
postcssWithPlugins: postcss(postCssPlugins),
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
return postcssInstancePromise
|
||||
}
|
||||
|
||||
export const css = curry(async function css(
|
||||
ctx: ConfigurationContext,
|
||||
config: webpack.Configuration
|
||||
|
@ -96,6 +126,14 @@ export const css = curry(async function css(
|
|||
...sassOptions
|
||||
} = ctx.sassOptions
|
||||
|
||||
const lazyPostCSSInitalizer = () =>
|
||||
lazyPostCSS(
|
||||
ctx.rootDirectory,
|
||||
ctx.supportedBrowsers,
|
||||
ctx.future.strictPostcssConfiguration,
|
||||
ctx.experimental.disablePostcssPresetEnv
|
||||
)
|
||||
|
||||
const sassPreprocessors: webpack.RuleSetUseItem[] = [
|
||||
// First, process files with `sass-loader`: this inlines content, and
|
||||
// compiles away the proprietary syntax.
|
||||
|
@ -137,12 +175,6 @@ export const css = curry(async function css(
|
|||
}),
|
||||
]
|
||||
|
||||
const postCssPlugins = await getPostCssPlugins(
|
||||
ctx.rootDirectory,
|
||||
ctx.supportedBrowsers,
|
||||
!ctx.future.strictPostcssConfiguration
|
||||
)
|
||||
|
||||
// CSS cannot be imported in _document. This comes before everything because
|
||||
// global CSS nor CSS modules work in said file.
|
||||
fns.push(
|
||||
|
@ -183,7 +215,7 @@ export const css = curry(async function css(
|
|||
and: [ctx.rootDirectory],
|
||||
not: [/node_modules/],
|
||||
},
|
||||
use: getCssModuleLoader(ctx, postCssPlugins),
|
||||
use: getCssModuleLoader(ctx, lazyPostCSSInitalizer),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
@ -206,7 +238,11 @@ export const css = curry(async function css(
|
|||
and: [ctx.rootDirectory],
|
||||
not: [/node_modules/],
|
||||
},
|
||||
use: getCssModuleLoader(ctx, postCssPlugins, sassPreprocessors),
|
||||
use: getCssModuleLoader(
|
||||
ctx,
|
||||
lazyPostCSSInitalizer,
|
||||
sassPreprocessors
|
||||
),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
@ -266,7 +302,7 @@ export const css = curry(async function css(
|
|||
and: [ctx.rootDirectory],
|
||||
not: [/node_modules/],
|
||||
},
|
||||
use: getGlobalCssLoader(ctx, postCssPlugins),
|
||||
use: getGlobalCssLoader(ctx, lazyPostCSSInitalizer),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
@ -284,7 +320,7 @@ export const css = curry(async function css(
|
|||
sideEffects: true,
|
||||
test: regexCssGlobal,
|
||||
issuer: { and: [ctx.customAppFile] },
|
||||
use: getGlobalCssLoader(ctx, postCssPlugins),
|
||||
use: getGlobalCssLoader(ctx, lazyPostCSSInitalizer),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
@ -300,7 +336,11 @@ export const css = curry(async function css(
|
|||
sideEffects: true,
|
||||
test: regexSassGlobal,
|
||||
issuer: { and: [ctx.customAppFile] },
|
||||
use: getGlobalCssLoader(ctx, postCssPlugins, sassPreprocessors),
|
||||
use: getGlobalCssLoader(
|
||||
ctx,
|
||||
lazyPostCSSInitalizer,
|
||||
sassPreprocessors
|
||||
),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import { AcceptedPlugin } from 'postcss'
|
||||
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import { ConfigurationContext } from '../../../utils'
|
||||
import { getClientStyleLoader } from './client'
|
||||
import { cssFileResolve } from './file-resolve'
|
||||
import postcss from 'postcss'
|
||||
|
||||
export function getGlobalCssLoader(
|
||||
ctx: ConfigurationContext,
|
||||
postCssPlugins: AcceptedPlugin[],
|
||||
postcss: any,
|
||||
preProcessors: readonly webpack.RuleSetUseItem[] = []
|
||||
): webpack.RuleSetUseItem[] {
|
||||
const loaders: webpack.RuleSetUseItem[] = []
|
||||
|
@ -27,6 +25,7 @@ export function getGlobalCssLoader(
|
|||
loaders.push({
|
||||
loader: require.resolve('../../../../loaders/css-loader/src'),
|
||||
options: {
|
||||
postcss,
|
||||
importLoaders: 1 + preProcessors.length,
|
||||
// Next.js controls CSS Modules eligibility:
|
||||
modules: false,
|
||||
|
@ -41,7 +40,7 @@ export function getGlobalCssLoader(
|
|||
loaders.push({
|
||||
loader: require.resolve('../../../../loaders/postcss-loader/src'),
|
||||
options: {
|
||||
postcss: postcss(postCssPlugins),
|
||||
postcss,
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import { AcceptedPlugin } from 'postcss'
|
||||
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import { ConfigurationContext } from '../../../utils'
|
||||
import { getClientStyleLoader } from './client'
|
||||
import { cssFileResolve } from './file-resolve'
|
||||
import { getCssModuleLocalIdent } from './getCssModuleLocalIdent'
|
||||
import postcss from 'postcss'
|
||||
|
||||
export function getCssModuleLoader(
|
||||
ctx: ConfigurationContext,
|
||||
postCssPlugins: AcceptedPlugin[],
|
||||
postcss: any,
|
||||
preProcessors: readonly webpack.RuleSetUseItem[] = []
|
||||
): webpack.RuleSetUseItem[] {
|
||||
const loaders: webpack.RuleSetUseItem[] = []
|
||||
|
@ -28,6 +26,7 @@ export function getCssModuleLoader(
|
|||
loaders.push({
|
||||
loader: require.resolve('../../../../loaders/css-loader/src'),
|
||||
options: {
|
||||
postcss,
|
||||
importLoaders: 1 + preProcessors.length,
|
||||
// Use CJS mode for backwards compatibility:
|
||||
esModule: false,
|
||||
|
@ -57,7 +56,7 @@ export function getCssModuleLoader(
|
|||
loaders.push({
|
||||
loader: require.resolve('../../../../loaders/postcss-loader/src'),
|
||||
options: {
|
||||
postcss: postcss(postCssPlugins),
|
||||
postcss,
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import { getPostCssPlugins } from './plugins'
|
||||
import postcss from 'postcss'
|
||||
|
||||
export async function __overrideCssConfiguration(
|
||||
rootDirectory: string,
|
||||
supportedBrowsers: string[] | undefined,
|
||||
config: webpack.Configuration
|
||||
) {
|
||||
const postCssPlugins = await getPostCssPlugins(
|
||||
rootDirectory,
|
||||
supportedBrowsers
|
||||
)
|
||||
|
||||
function patch(rule: webpack.RuleSetRule) {
|
||||
if (
|
||||
rule.options &&
|
||||
typeof rule.options === 'object' &&
|
||||
typeof rule.options.postcssOptions === 'object'
|
||||
) {
|
||||
rule.options.postcssOptions.plugins = postCssPlugins
|
||||
} else if (
|
||||
rule.options &&
|
||||
typeof rule.options === 'object' &&
|
||||
typeof rule.options.postcss !== 'undefined'
|
||||
) {
|
||||
rule.options.postcss = postcss(postCssPlugins)
|
||||
} else if (Array.isArray(rule.oneOf)) {
|
||||
rule.oneOf.forEach(patch)
|
||||
} else if (Array.isArray(rule.use)) {
|
||||
rule.use.forEach((u) => {
|
||||
if (typeof u === 'object') {
|
||||
patch(u)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
config.module?.rules?.forEach((entry) => {
|
||||
patch(entry)
|
||||
})
|
||||
}
|
|
@ -88,40 +88,46 @@ async function loadPlugin(
|
|||
}
|
||||
|
||||
function getDefaultPlugins(
|
||||
supportedBrowsers: string[] | undefined
|
||||
): CssPluginCollection {
|
||||
supportedBrowsers: string[] | undefined,
|
||||
disablePostcssPresetEnv: boolean
|
||||
): any[] {
|
||||
return [
|
||||
require.resolve('next/dist/compiled/postcss-flexbugs-fixes'),
|
||||
[
|
||||
require.resolve('next/dist/compiled/postcss-preset-env'),
|
||||
{
|
||||
browsers: supportedBrowsers ?? ['defaults'],
|
||||
autoprefixer: {
|
||||
// Disable legacy flexbox support
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
// Enable CSS features that have shipped to the
|
||||
// web platform, i.e. in 2+ browsers unflagged.
|
||||
stage: 3,
|
||||
features: {
|
||||
'custom-properties': false,
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
disablePostcssPresetEnv
|
||||
? false
|
||||
: [
|
||||
require.resolve('next/dist/compiled/postcss-preset-env'),
|
||||
{
|
||||
browsers: supportedBrowsers ?? ['defaults'],
|
||||
autoprefixer: {
|
||||
// Disable legacy flexbox support
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
// Enable CSS features that have shipped to the
|
||||
// web platform, i.e. in 2+ browsers unflagged.
|
||||
stage: 3,
|
||||
features: {
|
||||
'custom-properties': false,
|
||||
},
|
||||
},
|
||||
],
|
||||
].filter(Boolean)
|
||||
}
|
||||
|
||||
export async function getPostCssPlugins(
|
||||
dir: string,
|
||||
supportedBrowsers: string[] | undefined,
|
||||
defaults: boolean = false
|
||||
defaults: boolean = false,
|
||||
disablePostcssPresetEnv: boolean = false
|
||||
): Promise<import('postcss').AcceptedPlugin[]> {
|
||||
let config = defaults
|
||||
? null
|
||||
: await findConfig<{ plugins: CssPluginCollection }>(dir, 'postcss')
|
||||
|
||||
if (config == null) {
|
||||
config = { plugins: getDefaultPlugins(supportedBrowsers) }
|
||||
config = {
|
||||
plugins: getDefaultPlugins(supportedBrowsers, disablePostcssPresetEnv),
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof config === 'function') {
|
||||
|
|
|
@ -2,28 +2,135 @@
|
|||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
import postcss from 'postcss'
|
||||
|
||||
import CssSyntaxError from './CssSyntaxError'
|
||||
import Warning from '../../postcss-loader/src/Warning'
|
||||
import { icssParser, importParser, urlParser } from './plugins'
|
||||
import {
|
||||
normalizeOptions,
|
||||
shouldUseModulesPlugins,
|
||||
shouldUseImportPlugin,
|
||||
shouldUseURLPlugin,
|
||||
shouldUseIcssPlugin,
|
||||
getPreRequester,
|
||||
getExportCode,
|
||||
getFilter,
|
||||
getImportCode,
|
||||
getModuleCode,
|
||||
getModulesPlugins,
|
||||
normalizeSourceMap,
|
||||
sort,
|
||||
} from './utils'
|
||||
// import { icssParser, importParser, urlParser } from './plugins'
|
||||
import { stringifyRequest } from '../../../stringify-request'
|
||||
|
||||
const moduleRegExp = /\.module\.\w+$/i
|
||||
|
||||
function getModulesOptions(rawOptions, loaderContext) {
|
||||
const { resourcePath } = loaderContext
|
||||
|
||||
if (typeof rawOptions.modules === 'undefined') {
|
||||
const isModules = moduleRegExp.test(resourcePath)
|
||||
|
||||
if (!isModules) {
|
||||
return false
|
||||
}
|
||||
} else if (
|
||||
typeof rawOptions.modules === 'boolean' &&
|
||||
rawOptions.modules === false
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
let modulesOptions = {
|
||||
compileType: rawOptions.icss ? 'icss' : 'module',
|
||||
auto: true,
|
||||
mode: 'local',
|
||||
exportGlobals: false,
|
||||
localIdentName: '[hash:base64]',
|
||||
localIdentContext: loaderContext.rootContext,
|
||||
localIdentHashPrefix: '',
|
||||
// eslint-disable-next-line no-undefined
|
||||
localIdentRegExp: undefined,
|
||||
namedExport: false,
|
||||
exportLocalsConvention: 'asIs',
|
||||
exportOnlyLocals: false,
|
||||
}
|
||||
|
||||
if (
|
||||
typeof rawOptions.modules === 'boolean' ||
|
||||
typeof rawOptions.modules === 'string'
|
||||
) {
|
||||
modulesOptions.mode =
|
||||
typeof rawOptions.modules === 'string' ? rawOptions.modules : 'local'
|
||||
} else {
|
||||
if (rawOptions.modules) {
|
||||
if (typeof rawOptions.modules.auto === 'boolean') {
|
||||
const isModules =
|
||||
rawOptions.modules.auto && moduleRegExp.test(resourcePath)
|
||||
|
||||
if (!isModules) {
|
||||
return false
|
||||
}
|
||||
} else if (rawOptions.modules.auto instanceof RegExp) {
|
||||
const isModules = rawOptions.modules.auto.test(resourcePath)
|
||||
|
||||
if (!isModules) {
|
||||
return false
|
||||
}
|
||||
} else if (typeof rawOptions.modules.auto === 'function') {
|
||||
const isModule = rawOptions.modules.auto(resourcePath)
|
||||
|
||||
if (!isModule) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
rawOptions.modules.namedExport === true &&
|
||||
typeof rawOptions.modules.exportLocalsConvention === 'undefined'
|
||||
) {
|
||||
modulesOptions.exportLocalsConvention = 'camelCaseOnly'
|
||||
}
|
||||
}
|
||||
|
||||
modulesOptions = { ...modulesOptions, ...(rawOptions.modules || {}) }
|
||||
}
|
||||
|
||||
if (typeof modulesOptions.mode === 'function') {
|
||||
modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath)
|
||||
}
|
||||
|
||||
if (modulesOptions.namedExport === true) {
|
||||
if (rawOptions.esModule === false) {
|
||||
throw new Error(
|
||||
'The "modules.namedExport" option requires the "esModules" option to be enabled'
|
||||
)
|
||||
}
|
||||
|
||||
if (modulesOptions.exportLocalsConvention !== 'camelCaseOnly') {
|
||||
throw new Error(
|
||||
'The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly"'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return modulesOptions
|
||||
}
|
||||
|
||||
function normalizeOptions(rawOptions, loaderContext) {
|
||||
if (rawOptions.icss) {
|
||||
loaderContext.emitWarning(
|
||||
new Error(
|
||||
'The "icss" option is deprecated, use "modules.compileType: "icss"" instead'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const modulesOptions = getModulesOptions(rawOptions, loaderContext)
|
||||
|
||||
return {
|
||||
url: typeof rawOptions.url === 'undefined' ? true : rawOptions.url,
|
||||
import: typeof rawOptions.import === 'undefined' ? true : rawOptions.import,
|
||||
modules: modulesOptions,
|
||||
// TODO remove in the next major release
|
||||
icss: typeof rawOptions.icss === 'undefined' ? false : rawOptions.icss,
|
||||
sourceMap:
|
||||
typeof rawOptions.sourceMap === 'boolean'
|
||||
? rawOptions.sourceMap
|
||||
: loaderContext.sourceMap,
|
||||
importLoaders:
|
||||
typeof rawOptions.importLoaders === 'string'
|
||||
? parseInt(rawOptions.importLoaders, 10)
|
||||
: rawOptions.importLoaders,
|
||||
esModule:
|
||||
typeof rawOptions.esModule === 'undefined' ? true : rawOptions.esModule,
|
||||
}
|
||||
}
|
||||
|
||||
export default async function loader(content, map, meta) {
|
||||
const rawOptions = this.getOptions()
|
||||
|
||||
|
@ -42,6 +149,25 @@ export default async function loader(content, map, meta) {
|
|||
throw error
|
||||
}
|
||||
|
||||
const { postcss } = await rawOptions.postcss()
|
||||
|
||||
const {
|
||||
shouldUseModulesPlugins,
|
||||
shouldUseImportPlugin,
|
||||
shouldUseURLPlugin,
|
||||
shouldUseIcssPlugin,
|
||||
getPreRequester,
|
||||
getExportCode,
|
||||
getFilter,
|
||||
getImportCode,
|
||||
getModuleCode,
|
||||
getModulesPlugins,
|
||||
normalizeSourceMap,
|
||||
sort,
|
||||
} = require('./utils')
|
||||
|
||||
const { icssParser, importParser, urlParser } = require('./plugins')
|
||||
|
||||
const replacements = []
|
||||
const exports = []
|
||||
|
||||
|
|
|
@ -81,130 +81,6 @@ function getFilter(filter, resourcePath) {
|
|||
}
|
||||
}
|
||||
|
||||
const moduleRegExp = /\.module\.\w+$/i
|
||||
|
||||
function getModulesOptions(rawOptions, loaderContext) {
|
||||
const { resourcePath } = loaderContext
|
||||
|
||||
if (typeof rawOptions.modules === 'undefined') {
|
||||
const isModules = moduleRegExp.test(resourcePath)
|
||||
|
||||
if (!isModules) {
|
||||
return false
|
||||
}
|
||||
} else if (
|
||||
typeof rawOptions.modules === 'boolean' &&
|
||||
rawOptions.modules === false
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
let modulesOptions = {
|
||||
compileType: rawOptions.icss ? 'icss' : 'module',
|
||||
auto: true,
|
||||
mode: 'local',
|
||||
exportGlobals: false,
|
||||
localIdentName: '[hash:base64]',
|
||||
localIdentContext: loaderContext.rootContext,
|
||||
localIdentHashPrefix: '',
|
||||
// eslint-disable-next-line no-undefined
|
||||
localIdentRegExp: undefined,
|
||||
namedExport: false,
|
||||
exportLocalsConvention: 'asIs',
|
||||
exportOnlyLocals: false,
|
||||
}
|
||||
|
||||
if (
|
||||
typeof rawOptions.modules === 'boolean' ||
|
||||
typeof rawOptions.modules === 'string'
|
||||
) {
|
||||
modulesOptions.mode =
|
||||
typeof rawOptions.modules === 'string' ? rawOptions.modules : 'local'
|
||||
} else {
|
||||
if (rawOptions.modules) {
|
||||
if (typeof rawOptions.modules.auto === 'boolean') {
|
||||
const isModules =
|
||||
rawOptions.modules.auto && moduleRegExp.test(resourcePath)
|
||||
|
||||
if (!isModules) {
|
||||
return false
|
||||
}
|
||||
} else if (rawOptions.modules.auto instanceof RegExp) {
|
||||
const isModules = rawOptions.modules.auto.test(resourcePath)
|
||||
|
||||
if (!isModules) {
|
||||
return false
|
||||
}
|
||||
} else if (typeof rawOptions.modules.auto === 'function') {
|
||||
const isModule = rawOptions.modules.auto(resourcePath)
|
||||
|
||||
if (!isModule) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
rawOptions.modules.namedExport === true &&
|
||||
typeof rawOptions.modules.exportLocalsConvention === 'undefined'
|
||||
) {
|
||||
modulesOptions.exportLocalsConvention = 'camelCaseOnly'
|
||||
}
|
||||
}
|
||||
|
||||
modulesOptions = { ...modulesOptions, ...(rawOptions.modules || {}) }
|
||||
}
|
||||
|
||||
if (typeof modulesOptions.mode === 'function') {
|
||||
modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath)
|
||||
}
|
||||
|
||||
if (modulesOptions.namedExport === true) {
|
||||
if (rawOptions.esModule === false) {
|
||||
throw new Error(
|
||||
'The "modules.namedExport" option requires the "esModules" option to be enabled'
|
||||
)
|
||||
}
|
||||
|
||||
if (modulesOptions.exportLocalsConvention !== 'camelCaseOnly') {
|
||||
throw new Error(
|
||||
'The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly"'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return modulesOptions
|
||||
}
|
||||
|
||||
function normalizeOptions(rawOptions, loaderContext) {
|
||||
if (rawOptions.icss) {
|
||||
loaderContext.emitWarning(
|
||||
new Error(
|
||||
'The "icss" option is deprecated, use "modules.compileType: "icss"" instead'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const modulesOptions = getModulesOptions(rawOptions, loaderContext)
|
||||
|
||||
return {
|
||||
url: typeof rawOptions.url === 'undefined' ? true : rawOptions.url,
|
||||
import: typeof rawOptions.import === 'undefined' ? true : rawOptions.import,
|
||||
modules: modulesOptions,
|
||||
// TODO remove in the next major release
|
||||
icss: typeof rawOptions.icss === 'undefined' ? false : rawOptions.icss,
|
||||
sourceMap:
|
||||
typeof rawOptions.sourceMap === 'boolean'
|
||||
? rawOptions.sourceMap
|
||||
: loaderContext.sourceMap,
|
||||
importLoaders:
|
||||
typeof rawOptions.importLoaders === 'string'
|
||||
? parseInt(rawOptions.importLoaders, 10)
|
||||
: rawOptions.importLoaders,
|
||||
esModule:
|
||||
typeof rawOptions.esModule === 'undefined' ? true : rawOptions.esModule,
|
||||
}
|
||||
}
|
||||
|
||||
function shouldUseImportPlugin(options) {
|
||||
if (options.modules.exportOnlyLocals) {
|
||||
return false
|
||||
|
@ -632,7 +508,6 @@ function isDataUrl(url) {
|
|||
|
||||
export {
|
||||
isDataUrl,
|
||||
normalizeOptions,
|
||||
shouldUseModulesPlugins,
|
||||
shouldUseImportPlugin,
|
||||
shouldUseURLPlugin,
|
||||
|
@ -640,7 +515,6 @@ export {
|
|||
normalizeUrl,
|
||||
requestify,
|
||||
getFilter,
|
||||
getModulesOptions,
|
||||
getModulesPlugins,
|
||||
normalizeSourceMap,
|
||||
getPreRequester,
|
||||
|
|
|
@ -56,13 +56,16 @@ export default async function loader(content, sourceMap, meta) {
|
|||
loaderSpan.setAttribute('astUsed', 'true')
|
||||
}
|
||||
|
||||
// Initializes postcss with plugins
|
||||
const { postcssWithPlugins } = await options.postcss()
|
||||
|
||||
let result
|
||||
|
||||
try {
|
||||
result = await loaderSpan
|
||||
.traceChild('postcss-process')
|
||||
.traceAsyncFn(() =>
|
||||
options.postcss.process(root || content, processOptions)
|
||||
postcssWithPlugins.process(root || content, processOptions)
|
||||
)
|
||||
} catch (error) {
|
||||
if (error.file) {
|
||||
|
|
|
@ -126,6 +126,7 @@ export type NextConfig = { [key: string]: any } & {
|
|||
crossOrigin?: false | 'anonymous' | 'use-credentials'
|
||||
swcMinify?: boolean
|
||||
experimental?: {
|
||||
disablePostcssPresetEnv?: boolean
|
||||
removeConsole?:
|
||||
| boolean
|
||||
| {
|
||||
|
|
|
@ -208,7 +208,7 @@ describe('Bad CSS Customization Array (1)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -228,7 +228,7 @@ describe('Bad CSS Customization Array (2)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/To disable 'postcss-trolling', pass false, otherwise, pass true or a configuration object./
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -245,7 +245,7 @@ describe('Bad CSS Customization Array (3)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin must be provided as a string. Instead, we got: '5'/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -260,7 +260,7 @@ describe('Bad CSS Customization Array (4)', () => {
|
|||
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||
|
||||
expect(stderr).toMatch(/An unknown PostCSS plugin was provided \(5\)/)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -277,7 +277,7 @@ describe('Bad CSS Customization Array (5)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/Your custom PostCSS configuration must export a `plugins` key./
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -294,7 +294,7 @@ describe('Bad CSS Customization Array (6)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/Your custom PostCSS configuration must export a `plugins` key./
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -311,7 +311,7 @@ describe('Bad CSS Customization Array (7)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -328,7 +328,7 @@ describe('Bad CSS Customization Array (8)', () => {
|
|||
expect(stderr).toMatch(
|
||||
/A PostCSS Plugin was passed as a function using require\(\), but it must be provided as a string/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -345,6 +345,6 @@ describe('Bad CSS Customization Function', () => {
|
|||
expect(stderr).toMatch(
|
||||
/Your custom PostCSS configuration may not export a function/
|
||||
)
|
||||
expect(stderr).toMatch(/Build error occurred/)
|
||||
expect(stderr).toMatch(/Build failed because of webpack errors/)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue