Skip to content

Commit e56ef61

Browse files
committed
built-in support for CSS extraction with extractCSS option
1 parent 5346db2 commit e56ef61

File tree

3 files changed

+60
-21
lines changed

3 files changed

+60
-21
lines changed

lib/loader.js

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var genId = require('./utils/gen-id')
55
var querystring = require('querystring')
66
var loaderUtils = require('loader-utils')
77
var normalize = require('./utils/normalize')
8-
var hasLoader = require('./utils/has-loader')
8+
var tryRequire = require('./utils/try-require')
99

1010
// internal lib loaders
1111
var selectorPath = normalize.lib('selector')
@@ -19,8 +19,8 @@ var styleLoaderPath = normalize.dep('vue-style-loader')
1919
var hotReloadAPIPath = normalize.dep('vue-hot-reload-api')
2020

2121
// check whether default js loader exists
22-
var hasBabel = hasLoader('babel')
23-
var hasBuble = hasLoader('buble')
22+
var hasBabel = !!tryRequire('babel-loader')
23+
var hasBuble = !!tryRequire('buble-loader')
2424

2525
var rewriterInjectRE = /\b(css(?:-loader)?(?:\?[^!]+)?)(?:!|$)/
2626

@@ -83,7 +83,9 @@ module.exports = function (content) {
8383

8484
var defaultLoaders = {
8585
html: templateCompilerPath + templateCompilerOptions,
86-
css: styleLoaderPath + '!' + 'css-loader' + cssLoaderOptions,
86+
css: options.extractCSS
87+
? getCSSExtractLoader()
88+
: styleLoaderPath + '!' + 'css-loader' + cssLoaderOptions,
8789
js: hasBuble ? ('buble-loader' + bubleOptions) : hasBabel ? 'babel-loader' : ''
8890
}
8991

@@ -190,19 +192,29 @@ module.exports = function (content) {
190192

191193
function getRawLoaderString (type, part, index, scoped) {
192194
var lang = part.lang || defaultLang[type]
193-
var loader = loaders[lang]
194195

195196
var styleCompiler = ''
196197
if (type === 'styles') {
198+
// style compiler that needs to be applied for all styles
197199
styleCompiler = styleCompilerPath + '?' + JSON.stringify({
198200
// a marker for vue-style-loader to know that this is an import from a vue file
199201
vue: true,
200202
id: moduleId,
201203
scoped: !!scoped,
202204
hasInlineConfig: !!query.postcss
203205
}) + '!'
206+
// normalize scss/sass
207+
if (lang === 'sass') {
208+
lang = 'sass?indentedSyntax'
209+
} else if (lang === 'scss') {
210+
lang = 'sass'
211+
}
204212
}
205213

214+
var loader = options.extractCSS
215+
? loaders[lang] || getCSSExtractLoader(lang)
216+
: loaders[lang]
217+
206218
var injectString = (type === 'script' && query.inject)
207219
? 'inject-loader!'
208220
: ''
@@ -252,7 +264,7 @@ module.exports = function (content) {
252264

253265
// sass => sass-loader
254266
// sass-loader => sass-loader
255-
// sass?indentedsyntax!css => sass-loader?indentedSyntax!css-loader
267+
// sass?indentedSyntax!css => sass-loader?indentedSyntax!css-loader
256268
function ensureLoader (lang) {
257269
return lang.split('!').map(function (loader) {
258270
return loader.replace(/^([\w-]+)(\?.*)?/, function (_, name, query) {
@@ -275,6 +287,32 @@ module.exports = function (content) {
275287
}
276288
}
277289

290+
function getCSSExtractLoader (lang) {
291+
var extract
292+
var op = options.extractCSS
293+
// extractCSS option is an instance of ExtractTextPlugin
294+
if (typeof op.extract === 'function') {
295+
extract = op.extract
296+
} else {
297+
var plugin = tryRequire('extract-text-webpack-plugin')
298+
if (!plugin) {
299+
throw new Error(
300+
'[vue-loader] extractCSS: true requires extract-text-webpack-plugin ' +
301+
'as a peer dependency.'
302+
)
303+
} else {
304+
extract = plugin.extract
305+
}
306+
}
307+
var langLoader = lang
308+
? ensureBang(ensureLoader(lang))
309+
: ''
310+
return extract({
311+
use: 'css-loader' + cssLoaderOptions + '!' + langLoader,
312+
fallback: 'vue-style-loader'
313+
})
314+
}
315+
278316
var output = ''
279317
var parts = parse(content, fileName, this.sourceMap)
280318
var hasScoped = parts.styles.some(function (s) { return s.scoped })

lib/utils/has-loader.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

lib/utils/try-require.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var fs = require('fs')
2+
var path = require('path')
3+
var cwd = process.cwd()
4+
5+
// attempts to first require a dep using projects cwd (when vue-loader is linked)
6+
// then try a normal require.
7+
module.exports = function tryRequire (dep) {
8+
var cwdPath = path.resolve(cwd, 'node_modules', dep)
9+
if (fs.existsSync(cwdPath)) {
10+
return require(cwdPath)
11+
} else {
12+
try {
13+
return require(dep)
14+
} catch (e) {}
15+
}
16+
}

0 commit comments

Comments
 (0)