11import curry from 'lodash.curry'
22import MiniCssExtractPlugin from 'mini-css-extract-plugin'
33import path from 'path'
4- import { Configuration } from 'webpack'
4+ import webpack , { Configuration } from 'webpack'
55import { loader } from '../../helpers'
66import { ConfigurationContext , ConfigurationFn , pipe } from '../../utils'
7- import { getGlobalImportError } from './messages'
7+ import { getCssModuleLocalIdent } from './getCssModuleLocalIdent'
8+ import { getGlobalImportError , getModuleImportError } from './messages'
89import { getPostCssPlugins } from './plugins'
9- import webpack from 'webpack'
1010
11- function getStyleLoader ( {
11+ function getClientStyleLoader ( {
1212 isDevelopment,
1313} : {
1414 isDevelopment : boolean
@@ -73,14 +73,93 @@ export const css = curry(async function css(
7373
7474 const fns : ConfigurationFn [ ] = [ ]
7575
76+ const postCssPlugins = await getPostCssPlugins ( ctx . rootDirectory )
77+ // CSS Modules support must be enabled on the server and client so the class
78+ // names are availble for SSR or Prerendering.
79+ fns . push (
80+ loader ( {
81+ oneOf : [
82+ {
83+ // CSS Modules should never have side effects. This setting will
84+ // allow unused CSS to be removed from the production build.
85+ // We ensure this by disallowing `:global()` CSS at the top-level
86+ // via the `pure` mode in `css-loader`.
87+ sideEffects : false ,
88+ // CSS Modules are activated via this specific extension.
89+ test : / \. m o d u l e \. c s s $ / ,
90+ // CSS Modules are only supported in the user's application. We're
91+ // not yet allowing CSS imports _within_ `node_modules`.
92+ issuer : {
93+ include : [ ctx . rootDirectory ] ,
94+ exclude : / n o d e _ m o d u l e s / ,
95+ } ,
96+
97+ use : ( [
98+ // Add appropriate development more or production mode style
99+ // loader
100+ ctx . isClient &&
101+ getClientStyleLoader ( { isDevelopment : ctx . isDevelopment } ) ,
102+
103+ // Resolve CSS `@import`s and `url()`s
104+ {
105+ loader : require . resolve ( 'css-loader' ) ,
106+ options : {
107+ importLoaders : 1 ,
108+ sourceMap : true ,
109+ onlyLocals : ctx . isServer ,
110+ modules : {
111+ // Disallow global style exports so we can code-split CSS and
112+ // not worry about loading order.
113+ mode : 'pure' ,
114+ // Generate a friendly production-ready name so it's
115+ // reasonably understandable. The same name is used for
116+ // development.
117+ // TODO: Consider making production reduce this to a single
118+ // character?
119+ getLocalIdent : getCssModuleLocalIdent ,
120+ } ,
121+ } ,
122+ } ,
123+
124+ // Compile CSS
125+ {
126+ loader : require . resolve ( 'postcss-loader' ) ,
127+ options : {
128+ ident : 'postcss' ,
129+ plugins : postCssPlugins ,
130+ sourceMap : true ,
131+ } ,
132+ } ,
133+ ] as webpack . RuleSetUseItem [ ] ) . filter ( Boolean ) ,
134+ } ,
135+ ] ,
136+ } )
137+ )
138+
139+ // Throw an error for CSS Modules used outside their supported scope
140+ fns . push (
141+ loader ( {
142+ oneOf : [
143+ {
144+ test : / \. m o d u l e \. c s s $ / ,
145+ use : {
146+ loader : 'error-loader' ,
147+ options : {
148+ reason : getModuleImportError ( ) ,
149+ } ,
150+ } ,
151+ } ,
152+ ] ,
153+ } )
154+ )
155+
76156 if ( ctx . isServer ) {
77157 fns . push (
78158 loader ( {
79159 oneOf : [ { test : / \. c s s $ / , use : require . resolve ( 'ignore-loader' ) } ] ,
80160 } )
81161 )
82162 } else if ( ctx . customAppFile ) {
83- const postCssPlugins = await getPostCssPlugins ( ctx . rootDirectory )
84163 fns . push (
85164 loader ( {
86165 oneOf : [
@@ -96,7 +175,7 @@ export const css = curry(async function css(
96175 use : [
97176 // Add appropriate development more or production mode style
98177 // loader
99- getStyleLoader ( { isDevelopment : ctx . isDevelopment } ) ,
178+ getClientStyleLoader ( { isDevelopment : ctx . isDevelopment } ) ,
100179
101180 // Resolve CSS `@import`s and `url()`s
102181 {
0 commit comments