Skip to content

Commit f67f99a

Browse files
Timerijjk
authored andcommitted
Extract CSS Loaders into Separate Files (vercel#10210)
1 parent 6988a2e commit f67f99a

File tree

6 files changed

+160
-124
lines changed

6 files changed

+160
-124
lines changed

packages/next/build/webpack/config/blocks/css/index.ts

Lines changed: 4 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import curry from 'lodash.curry'
22
import path from 'path'
3-
import webpack, { Configuration } from 'webpack'
3+
import { Configuration } from 'webpack'
44
import MiniCssExtractPlugin from '../../../plugins/mini-css-extract-plugin'
55
import { loader, plugin } from '../../helpers'
66
import { ConfigurationContext, ConfigurationFn, pipe } from '../../utils'
7-
import { getCssModuleLocalIdent } from './getCssModuleLocalIdent'
7+
import { getCssModuleLoader, getGlobalCssLoader } from './loaders'
88
import {
99
getCustomDocumentError,
1010
getGlobalImportError,
@@ -18,62 +18,6 @@ const regexCssAll = /\.css$/
1818
const regexCssGlobal = /(?<!\.module)\.css$/
1919
const regexCssModules = /\.module\.css$/
2020

21-
function getClientStyleLoader({
22-
isDevelopment,
23-
assetPrefix,
24-
}: {
25-
isDevelopment: boolean
26-
assetPrefix: string
27-
}): webpack.RuleSetUseItem {
28-
return isDevelopment
29-
? {
30-
loader: require.resolve('style-loader'),
31-
options: {
32-
// By default, style-loader injects CSS into the bottom
33-
// of <head>. This causes ordering problems between dev
34-
// and prod. To fix this, we render a <noscript> tag as
35-
// an anchor for the styles to be placed before. These
36-
// styles will be applied _before_ <style jsx global>.
37-
insert: function(element: Node) {
38-
// These elements should always exist. If they do not,
39-
// this code should fail.
40-
var anchorElement = document.querySelector(
41-
'#__next_css__DO_NOT_USE__'
42-
)!
43-
var parentNode = anchorElement.parentNode! // Normally <head>
44-
45-
// Each style tag should be placed right before our
46-
// anchor. By inserting before and not after, we do not
47-
// need to track the last inserted element.
48-
parentNode.insertBefore(element, anchorElement)
49-
50-
// Remember: this is development only code.
51-
//
52-
// After styles are injected, we need to remove the
53-
// <style> tags that set `body { display: none; }`.
54-
//
55-
// We use `requestAnimationFrame` as a way to defer
56-
// this operation since there may be multiple style
57-
// tags.
58-
;(self.requestAnimationFrame || setTimeout)(function() {
59-
for (
60-
var x = document.querySelectorAll('[data-next-hide-fouc]'),
61-
i = x.length;
62-
i--;
63-
64-
) {
65-
x[i].parentNode!.removeChild(x[i])
66-
}
67-
})
68-
},
69-
},
70-
}
71-
: {
72-
loader: MiniCssExtractPlugin.loader,
73-
options: { publicPath: `${assetPrefix}/_next/` },
74-
}
75-
}
76-
7721
export const css = curry(async function css(
7822
enabled: boolean,
7923
ctx: ConfigurationContext,
@@ -145,47 +89,7 @@ export const css = curry(async function css(
14589
include: [ctx.rootDirectory],
14690
exclude: /node_modules/,
14791
},
148-
149-
use: ([
150-
// Add appropriate development more or production mode style
151-
// loader
152-
ctx.isClient &&
153-
getClientStyleLoader({
154-
isDevelopment: ctx.isDevelopment,
155-
assetPrefix: ctx.assetPrefix,
156-
}),
157-
158-
// Resolve CSS `@import`s and `url()`s
159-
{
160-
loader: require.resolve('css-loader'),
161-
options: {
162-
importLoaders: 1,
163-
sourceMap: true,
164-
onlyLocals: ctx.isServer,
165-
modules: {
166-
// Disallow global style exports so we can code-split CSS and
167-
// not worry about loading order.
168-
mode: 'pure',
169-
// Generate a friendly production-ready name so it's
170-
// reasonably understandable. The same name is used for
171-
// development.
172-
// TODO: Consider making production reduce this to a single
173-
// character?
174-
getLocalIdent: getCssModuleLocalIdent,
175-
},
176-
},
177-
},
178-
179-
// Compile CSS
180-
{
181-
loader: require.resolve('postcss-loader'),
182-
options: {
183-
ident: '__nextjs_postcss',
184-
plugins: postCssPlugins,
185-
sourceMap: true,
186-
},
187-
},
188-
] as webpack.RuleSetUseItem[]).filter(Boolean),
92+
use: getCssModuleLoader(ctx, postCssPlugins),
18993
},
19094
],
19195
})
@@ -228,31 +132,7 @@ export const css = curry(async function css(
228132
sideEffects: true,
229133
test: regexCssGlobal,
230134
issuer: { include: ctx.customAppFile },
231-
232-
use: [
233-
// Add appropriate development more or production mode style
234-
// loader
235-
getClientStyleLoader({
236-
isDevelopment: ctx.isDevelopment,
237-
assetPrefix: ctx.assetPrefix,
238-
}),
239-
240-
// Resolve CSS `@import`s and `url()`s
241-
{
242-
loader: require.resolve('css-loader'),
243-
options: { importLoaders: 1, sourceMap: true },
244-
},
245-
246-
// Compile CSS
247-
{
248-
loader: require.resolve('postcss-loader'),
249-
options: {
250-
ident: '__nextjs_postcss',
251-
plugins: postCssPlugins,
252-
sourceMap: true,
253-
},
254-
},
255-
],
135+
use: getGlobalCssLoader(ctx, postCssPlugins),
256136
},
257137
],
258138
})
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import webpack from 'webpack'
2+
import MiniCssExtractPlugin from '../../../../plugins/mini-css-extract-plugin'
3+
4+
export function getClientStyleLoader({
5+
isDevelopment,
6+
assetPrefix,
7+
}: {
8+
isDevelopment: boolean
9+
assetPrefix: string
10+
}): webpack.RuleSetUseItem {
11+
return isDevelopment
12+
? {
13+
loader: require.resolve('style-loader'),
14+
options: {
15+
// By default, style-loader injects CSS into the bottom
16+
// of <head>. This causes ordering problems between dev
17+
// and prod. To fix this, we render a <noscript> tag as
18+
// an anchor for the styles to be placed before. These
19+
// styles will be applied _before_ <style jsx global>.
20+
insert: function(element: Node) {
21+
// These elements should always exist. If they do not,
22+
// this code should fail.
23+
var anchorElement = document.querySelector(
24+
'#__next_css__DO_NOT_USE__'
25+
)!
26+
var parentNode = anchorElement.parentNode! // Normally <head>
27+
28+
// Each style tag should be placed right before our
29+
// anchor. By inserting before and not after, we do not
30+
// need to track the last inserted element.
31+
parentNode.insertBefore(element, anchorElement)
32+
33+
// Remember: this is development only code.
34+
//
35+
// After styles are injected, we need to remove the
36+
// <style> tags that set `body { display: none; }`.
37+
//
38+
// We use `requestAnimationFrame` as a way to defer
39+
// this operation since there may be multiple style
40+
// tags.
41+
;(self.requestAnimationFrame || setTimeout)(function() {
42+
for (
43+
var x = document.querySelectorAll('[data-next-hide-fouc]'),
44+
i = x.length;
45+
i--;
46+
47+
) {
48+
x[i].parentNode!.removeChild(x[i])
49+
}
50+
})
51+
},
52+
},
53+
}
54+
: {
55+
loader: MiniCssExtractPlugin.loader,
56+
options: { publicPath: `${assetPrefix}/_next/` },
57+
}
58+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import postcss from 'postcss'
2+
import webpack from 'webpack'
3+
import { ConfigurationContext } from '../../../utils'
4+
import { getClientStyleLoader } from './client'
5+
6+
export function getGlobalCssLoader(
7+
ctx: ConfigurationContext,
8+
postCssPlugins: postcss.AcceptedPlugin[]
9+
): webpack.RuleSetUseItem[] {
10+
const loaders: webpack.RuleSetUseItem[] = []
11+
12+
if (ctx.isClient) {
13+
// Add appropriate development more or production mode style
14+
// loader
15+
loaders.push(
16+
getClientStyleLoader({
17+
isDevelopment: ctx.isDevelopment,
18+
assetPrefix: ctx.assetPrefix,
19+
})
20+
)
21+
}
22+
23+
// Resolve CSS `@import`s and `url()`s
24+
loaders.push({
25+
loader: require.resolve('css-loader'),
26+
options: { importLoaders: 1, sourceMap: true },
27+
})
28+
29+
// Compile CSS
30+
loaders.push({
31+
loader: require.resolve('postcss-loader'),
32+
options: {
33+
ident: '__nextjs_postcss',
34+
plugins: postCssPlugins,
35+
sourceMap: true,
36+
},
37+
})
38+
39+
return loaders
40+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './global'
2+
export * from './modules'
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import postcss from 'postcss'
2+
import webpack from 'webpack'
3+
import { ConfigurationContext } from '../../../utils'
4+
import { getClientStyleLoader } from './client'
5+
import { getCssModuleLocalIdent } from './getCssModuleLocalIdent'
6+
7+
export function getCssModuleLoader(
8+
ctx: ConfigurationContext,
9+
postCssPlugins: postcss.AcceptedPlugin[]
10+
): webpack.RuleSetUseItem[] {
11+
const loaders: webpack.RuleSetUseItem[] = []
12+
13+
if (ctx.isClient) {
14+
// Add appropriate development more or production mode style
15+
// loader
16+
loaders.push(
17+
getClientStyleLoader({
18+
isDevelopment: ctx.isDevelopment,
19+
assetPrefix: ctx.assetPrefix,
20+
})
21+
)
22+
}
23+
24+
// Resolve CSS `@import`s and `url()`s
25+
loaders.push({
26+
loader: require.resolve('css-loader'),
27+
options: {
28+
importLoaders: 1,
29+
sourceMap: true,
30+
onlyLocals: ctx.isServer,
31+
modules: {
32+
// Disallow global style exports so we can code-split CSS and
33+
// not worry about loading order.
34+
mode: 'pure',
35+
// Generate a friendly production-ready name so it's
36+
// reasonably understandable. The same name is used for
37+
// development.
38+
// TODO: Consider making production reduce this to a single
39+
// character?
40+
getLocalIdent: getCssModuleLocalIdent,
41+
},
42+
},
43+
})
44+
45+
// Compile CSS
46+
loaders.push({
47+
loader: require.resolve('postcss-loader'),
48+
options: {
49+
ident: '__nextjs_postcss',
50+
plugins: postCssPlugins,
51+
sourceMap: true,
52+
},
53+
})
54+
55+
return loaders
56+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy