@@ -77,7 +77,7 @@ module.exports = function (content) {
77
77
// disable all configuration loaders
78
78
'!!' +
79
79
// get loader string for pre-processors
80
- getLoaderString ( type , part , scoped ) +
80
+ getLoaderString ( type , part , index , scoped ) +
81
81
// select the corresponding part from the vue file
82
82
getSelectorString ( type , index || 0 ) +
83
83
// the url to the actual vuefile
@@ -94,17 +94,41 @@ module.exports = function (content) {
94
94
function getRequireForImportString ( type , impt , scoped ) {
95
95
return loaderUtils . stringifyRequest ( loaderContext ,
96
96
'!!' +
97
- getLoaderString ( type , impt , scoped ) +
97
+ getLoaderString ( type , impt , - 1 , scoped ) +
98
98
impt . src
99
99
)
100
100
}
101
101
102
- function getLoaderString ( type , part , scoped ) {
102
+ function addCssModulesToLoader ( loader , part , index ) {
103
+ if ( ! part . module ) return loader
104
+ return loader . replace ( / ( (?: ^ | ! ) c s s (?: - l o a d e r ) ? ) ( \? [ ^ ! ] * ) ? / , function ( m , $1 , $2 ) {
105
+ // $1: !css-loader
106
+ // $2: ?a=b
107
+ var option = loaderUtils . parseQuery ( $2 )
108
+ option . modules = true
109
+ option . importLoaders = true
110
+ option . localIdentName = '[hash:base64]'
111
+ if ( index !== - 1 ) {
112
+ // Note:
113
+ // Class name is generated according to its filename.
114
+ // Different <style> tags in the same .vue file may generate same names.
115
+ // Append `_[index]` to class name to avoid this.
116
+ option . localIdentName += '_' + index
117
+ }
118
+ return $1 + '?' + JSON . stringify ( option )
119
+ } )
120
+ }
121
+
122
+ function getLoaderString ( type , part , index , scoped ) {
103
123
var lang = part . lang || defaultLang [ type ]
104
124
var loader = loaders [ lang ]
105
125
var rewriter = type === 'styles' ? styleRewriter + ( scoped ? '&scoped=true!' : '!' ) : ''
106
126
var injectString = ( type === 'script' && query . inject ) ? 'inject!' : ''
107
127
if ( loader !== undefined ) {
128
+ // add css modules
129
+ if ( type === 'styles' ) {
130
+ loader = addCssModulesToLoader ( loader , part , index )
131
+ }
108
132
// inject rewriter before css/html loader for
109
133
// extractTextPlugin use cases
110
134
if ( rewriterInjectRE . test ( loader ) ) {
@@ -121,7 +145,8 @@ module.exports = function (content) {
121
145
case 'template' :
122
146
return defaultLoaders . html + '!' + templateLoaderPath + '?raw&engine=' + lang + '!'
123
147
case 'styles' :
124
- return defaultLoaders . css + '!' + rewriter + lang + '!'
148
+ loader = addCssModulesToLoader ( defaultLoaders . css , part , index )
149
+ return loader + '!' + rewriter + lang + '!'
125
150
case 'script' :
126
151
return injectString + lang + '!'
127
152
}
@@ -146,13 +171,31 @@ module.exports = function (content) {
146
171
var hasScoped = parts . styles . some ( function ( s ) { return s . scoped } )
147
172
var output = 'var __vue_exports__, __vue_options__\n'
148
173
174
+ // css modules
175
+ output += 'var __vue_styles__ = {}\n'
176
+ var cssModules = { }
177
+
149
178
// add requires for styles
150
179
if ( ! isServer && parts . styles . length ) {
151
180
output += '\n/* styles */\n'
152
181
parts . styles . forEach ( function ( style , i ) {
153
- output += style . src
182
+ /* !HACK! */
183
+ style . module = i === 0 ? 'style' : '$style'
184
+ var requireString = style . src
154
185
? getRequireForImport ( 'styles' , style , style . scoped )
155
186
: getRequire ( 'styles' , style , i , style . scoped )
187
+ // setCssModule
188
+ if ( style . module ) {
189
+ if ( style . module in cssModules ) {
190
+ loaderContext . emitError ( 'CSS module name "' + style . module + '" is not unique!' )
191
+ output += requireString
192
+ } else {
193
+ cssModules [ style . module ] = true
194
+ output += '__vue_styles__["' + style . module + '"] = ' + requireString + '\n'
195
+ }
196
+ } else {
197
+ output += requireString
198
+ }
156
199
} )
157
200
}
158
201
@@ -205,6 +248,16 @@ module.exports = function (content) {
205
248
exports += '__vue_options__._scopeId = "' + moduleId + '"\n'
206
249
}
207
250
251
+ if ( Object . keys ( cssModules ) . length ) {
252
+ // inject style modules as computed properties
253
+ exports +=
254
+ 'if (!__vue_options__.computed) __vue_options__.computed = {}\n' +
255
+ 'Object.keys(__vue_styles__).forEach(function (key) {\n' +
256
+ 'var module = __vue_styles__[key]\n' +
257
+ '__vue_options__.computed[key] = function () { return module }\n' +
258
+ '})\n'
259
+ }
260
+
208
261
if ( ! query . inject ) {
209
262
output += exports
210
263
// hot reload
0 commit comments