@@ -8,13 +8,13 @@ const plugin = require("./plugin");
88const getImportPrefix = require ( "./getImportPrefix" ) ;
99const SyntaxError = require ( "./SyntaxError" ) ;
1010
11- module . exports = function ( content , map ) {
11+ module . exports = function ( content , map , meta ) {
1212 const options = loaderUtils . getOptions ( this ) || { } ;
1313
1414 // Todo validate options
1515
1616 const cb = this . async ( ) ;
17- const sourceMap = options . sourceMap ;
17+ const sourceMap = options . sourceMap || false ;
1818
1919 if ( sourceMap && map ) {
2020 if ( typeof map === "string" ) {
@@ -30,85 +30,95 @@ module.exports = function(content, map) {
3030 map = null ;
3131 }
3232
33- // We need a prefix to avoid path rewriting of PostCSS
34- const from =
35- "/css-loader!" +
36- loaderUtils
37- . getRemainingRequest ( this )
38- . split ( "!" )
39- . pop ( ) ;
40- const to = loaderUtils
41- . getCurrentRequest ( this )
42- . split ( "!" )
43- . pop ( ) ;
33+ // Reuse CSS AST (PostCSS AST e.g 'postcss-loader') to avoid reparsing
34+ if ( meta ) {
35+ const { ast } = meta ;
36+
37+ if ( ast && ast . type === "postcss" ) {
38+ content = ast . root ;
39+ }
40+ }
4441
45- postcss ( [
42+ const plugins = [
4643 plugin ( {
4744 url : options . url !== false ,
4845 import : options . import !== false
4946 } )
50- ] )
51- . process ( content , {
52- from,
53- to,
54- map : sourceMap
55- ? {
56- prev : map ,
57- sourcesContent : true ,
58- inline : false ,
59- annotation : false
60- }
61- : null
62- } )
47+ ] ;
48+
49+ const postcssOptions = {
50+ // We need a prefix to avoid path rewriting of PostCSS
51+ from :
52+ "/css-loader!" +
53+ loaderUtils
54+ . getRemainingRequest ( this )
55+ . split ( "!" )
56+ . pop ( ) ,
57+ to : loaderUtils
58+ . getCurrentRequest ( this )
59+ . split ( "!" )
60+ . pop ( ) ,
61+ map : sourceMap
62+ ? {
63+ prev : map ,
64+ sourcesContent : true ,
65+ inline : false ,
66+ annotation : false
67+ }
68+ : null
69+ } ;
70+
71+ postcss ( plugins )
72+ . process ( content , postcssOptions )
6373 . then ( result => {
64- var cssAsString = JSON . stringify ( result . css ) ;
74+ let cssAsString = JSON . stringify ( result . css ) ;
75+ let imports = "" ;
76+ let exports = "" ;
77+ let urlEscapeHelperCode = "" ;
6578
6679 if ( options . import !== false ) {
67- var alreadyImported = { } ;
68- var importJs = result . messages
80+ const alreadyImported = { } ;
81+ imports = result . messages
6982 . filter ( message => message . type === "at-rule-import" )
70- . filter ( imp => {
71- if ( ! imp . mediaQuery ) {
72- if ( alreadyImported [ imp . url ] ) {
83+ . filter ( message => {
84+ if ( ! message . mediaQuery ) {
85+ if ( alreadyImported [ message . url ] ) {
7386 return false ;
7487 }
7588
76- alreadyImported [ imp . url ] = true ;
89+ alreadyImported [ message . url ] = true ;
7790 }
7891
7992 return true ;
8093 } )
81- . map ( imp => {
82- if ( ! loaderUtils . isUrlRequest ( imp . url ) ) {
94+ . map ( message => {
95+ if ( ! loaderUtils . isUrlRequest ( message . url ) ) {
8396 return (
8497 "exports.push([module.id, " +
85- JSON . stringify ( "@import url(" + imp . url + ");" ) +
98+ JSON . stringify ( "@import url(" + message . url + ");" ) +
8699 ", " +
87- JSON . stringify ( imp . mediaQuery ) +
100+ JSON . stringify ( message . mediaQuery ) +
88101 "]);"
89102 ) ;
90103 }
91104
92105 // for importing CSS
93106 var importUrlPrefix = getImportPrefix ( this , options ) ;
94- var importUrl = importUrlPrefix + imp . url ;
107+ var importUrl = importUrlPrefix + message . url ;
95108
96109 return (
97110 "exports.i(require(" +
98111 loaderUtils . stringifyRequest ( this , importUrl ) +
99112 "), " +
100- JSON . stringify ( imp . mediaQuery ) +
113+ JSON . stringify ( message . mediaQuery ) +
101114 ");"
102115 ) ;
103116 } )
104117 . join ( "\n" ) ;
105118 }
106119
107- // Helper for ensuring valid CSS strings from requires
108- let urlEscapeHelper = "" ;
109-
110120 if ( options . url !== false ) {
111- urlEscapeHelper =
121+ urlEscapeHelperCode =
112122 "var runtimeEscape = require(" +
113123 loaderUtils . stringifyRequest (
114124 this ,
@@ -117,7 +127,7 @@ module.exports = function(content, map) {
117127 ");\n" ;
118128
119129 result . messages
120- . filter ( message => message . type === "css-loader-import -url" )
130+ . filter ( message => message . type === "function -url" )
121131 . forEach ( message => {
122132 const { placeholder, url } = message ;
123133 const splittedURL = url . split ( / ( \? ) ? # / ) ;
@@ -132,15 +142,6 @@ module.exports = function(content, map) {
132142 } ) ;
133143 }
134144
135- // Todo need save backward compatibility with old `style-loader`
136- var exportJs = "" ;
137-
138- if ( exportJs ) {
139- exportJs = "exports.locals = " + exportJs + ";" ;
140- }
141-
142- var moduleJs ;
143-
144145 if ( sourceMap && result . map ) {
145146 map = result . map . toJSON ( ) ;
146147
@@ -159,34 +160,34 @@ module.exports = function(content, map) {
159160 . pop ( )
160161 . replace ( / \\ / g, "/" ) ;
161162 map = JSON . stringify ( map ) ;
162-
163- moduleJs =
164- "exports.push([module.id, " + cssAsString + ', "", ' + map + "]);" ;
165- } else {
166- moduleJs = "exports.push([module.id, " + cssAsString + ', ""]);' ;
167163 }
168164
169- // embed runtime
165+ const runtimeCode = `module.exports = exports = require(${ loaderUtils . stringifyRequest (
166+ this ,
167+ require . resolve ( "./runtime.js" )
168+ ) } )(${ ! ! sourceMap } );\n`;
169+ const moduleCode = `// CSS Module\nexports.push([module.id, ${ cssAsString } , ""${
170+ map ? `,${ map } ` : ""
171+ } ]);\n`;
172+ const importsCode = imports ? `// CSS Imports\n${ imports } \n` : "" ;
173+ // Todo need save backward compatibility with old `style-loader` and exports.locals
174+ const exportsCode = exports ? `// CSS Exports\n${ exports } \n` : false ;
175+
170176 cb (
171177 null ,
172- urlEscapeHelper +
173- "exports = module.exports = require(" +
174- loaderUtils . stringifyRequest ( this , require . resolve ( "./runtime.js" ) ) +
175- ")(" +
176- sourceMap +
177- ");\n" +
178- "// imports\n" +
179- importJs +
180- "\n\n" +
181- "// module\n" +
182- moduleJs +
183- "\n\n" +
184- "// exports\n" +
185- exportJs
178+ [
179+ urlEscapeHelperCode ,
180+ runtimeCode ,
181+ importsCode ,
182+ moduleCode ,
183+ exportsCode
184+ ] . join ( "\n" )
186185 ) ;
187186 } )
188187 . catch ( err => {
189- // Todo if (err.file) this.addDependency(err.file)
188+ if ( err . file ) {
189+ this . addDependency ( err . file ) ;
190+ }
190191
191192 cb ( err . name === "CssSyntaxError" ? new SyntaxError ( err ) : err ) ;
192193 } ) ;
0 commit comments