Skip to content

Commit a2c767e

Browse files
committed
fix: minify embedded CSS with extract: false
close vuejs#2214
1 parent 8dfa290 commit a2c767e

File tree

4 files changed

+61
-47
lines changed

4 files changed

+61
-47
lines changed

packages/@vue/cli-service/__tests__/css.spec.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ test('default loaders', () => {
5454
LANGS.forEach(lang => {
5555
const loader = lang === 'css' ? [] : LOADERS[lang]
5656
expect(findLoaders(config, lang)).toEqual(['vue-style', 'css', 'postcss'].concat(loader))
57+
expect(findOptions(config, lang, 'postcss').plugins).toBeFalsy()
5758
// assert css-loader options
5859
expect(findOptions(config, lang, 'css')).toEqual({
5960
sourceMap: false,
@@ -69,6 +70,7 @@ test('production defaults', () => {
6970
LANGS.forEach(lang => {
7071
const loader = lang === 'css' ? [] : LOADERS[lang]
7172
expect(findLoaders(config, lang)).toEqual([extractLoaderPath, 'css', 'postcss'].concat(loader))
73+
expect(findOptions(config, lang, 'postcss').plugins).toBeFalsy()
7274
expect(findOptions(config, lang, 'css')).toEqual({
7375
sourceMap: false,
7476
importLoaders: 2
@@ -109,7 +111,30 @@ test('css.extract', () => {
109111
}
110112
}, 'production')
111113
LANGS.forEach(lang => {
112-
expect(findLoaders(config, lang)).not.toContain(extractLoaderPath)
114+
const loader = lang === 'css' ? [] : LOADERS[lang]
115+
// when extract is false in production, even without postcss config,
116+
// an instance of postcss-loader is injected for inline minification.
117+
expect(findLoaders(config, lang)).toEqual(['vue-style', 'css', 'postcss'].concat(loader))
118+
expect(findOptions(config, lang, 'css').importLoaders).toBe(2)
119+
expect(findOptions(config, lang, 'postcss').plugins).toBeTruthy()
120+
})
121+
122+
const config2 = genConfig({
123+
postcss: {},
124+
vue: {
125+
css: {
126+
extract: false
127+
}
128+
}
129+
}, 'production')
130+
LANGS.forEach(lang => {
131+
const loader = lang === 'css' ? [] : LOADERS[lang]
132+
// if postcss config is present, two postcss-loaders will be used becasue it
133+
// does not support mixing config files with loader options.
134+
expect(findLoaders(config2, lang)).toEqual(['vue-style', 'css', 'postcss', 'postcss'].concat(loader))
135+
expect(findOptions(config2, lang, 'css').importLoaders).toBe(3)
136+
// minification loader should be injected before the user-facing postcss-loader
137+
expect(findOptions(config2, lang, 'postcss').plugins).toBeTruthy()
113138
})
114139
})
115140

packages/@vue/cli-service/lib/config/css.js

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ module.exports = (api, options) => {
5151
'.postcssrc.json'
5252
]))
5353

54+
// if building for production but not extracting CSS, we need to minimize
55+
// the embbeded inline CSS as they will not be going through the optimizing
56+
// plugin.
57+
const needInlineMinification = isProd && !shouldExtract
58+
59+
const cssnanoOptions = {
60+
safe: true,
61+
autoprefixer: { disable: true },
62+
mergeLonghand: false
63+
}
64+
if (options.productionSourceMap && sourceMap) {
65+
cssnanoOptions.map = { inline: false }
66+
}
67+
5468
function createCSSRule (lang, test, loader, options) {
5569
const baseRule = webpackConfig.module.rule(lang).test(test)
5670

@@ -92,7 +106,8 @@ module.exports = (api, options) => {
92106
sourceMap,
93107
importLoaders: (
94108
1 + // stylePostLoader injected by vue-loader
95-
hasPostCSSConfig
109+
(hasPostCSSConfig ? 1 : 0) +
110+
(needInlineMinification ? 1 : 0)
96111
)
97112
}, loaderOptions.css)
98113

@@ -111,6 +126,15 @@ module.exports = (api, options) => {
111126
.loader('css-loader')
112127
.options(cssLoaderOptions)
113128

129+
if (needInlineMinification) {
130+
rule
131+
.use('cssnano')
132+
.loader('postcss-loader')
133+
.options({
134+
plugins: [require('cssnano')(cssnanoOptions)]
135+
})
136+
}
137+
114138
if (hasPostCSSConfig) {
115139
rule
116140
.use('postcss-loader')
@@ -143,24 +167,16 @@ module.exports = (api, options) => {
143167
webpackConfig
144168
.plugin('extract-css')
145169
.use(require('mini-css-extract-plugin'), [extractOptions])
146-
}
147170

148-
if (isProd) {
149-
// optimize CSS (dedupe)
150-
const cssProcessorOptions = {
151-
safe: true,
152-
autoprefixer: { disable: true },
153-
mergeLonghand: false
154-
}
155-
if (options.productionSourceMap && sourceMap) {
156-
cssProcessorOptions.map = { inline: false }
171+
// minify extracted CSS
172+
if (isProd) {
173+
webpackConfig
174+
.plugin('optimize-css')
175+
.use(require('@intervolga/optimize-cssnano-plugin'), [{
176+
sourceMap: options.productionSourceMap && sourceMap,
177+
cssnanoOptions
178+
}])
157179
}
158-
webpackConfig
159-
.plugin('optimize-css')
160-
.use(require('@intervolga/optimize-cssnano-plugin'), [{
161-
sourceMap: options.productionSourceMap && sourceMap,
162-
cssnanoOptions: cssProcessorOptions
163-
}])
164180
}
165181
})
166182
}

packages/@vue/cli-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"cliui": "^4.1.0",
3737
"copy-webpack-plugin": "^4.5.2",
3838
"css-loader": "^1.0.0",
39+
"cssnano": "^4.0.0",
3940
"debug": "^3.1.0",
4041
"escape-string-regexp": "^1.0.5",
4142
"file-loader": "^1.1.11",

yarn.lock

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7082,7 +7082,7 @@ jest-util@^23.4.0:
70827082
slash "^1.0.0"
70837083
source-map "^0.6.0"
70847084

7085-
jest-validate@^23.0.0, jest-validate@^23.4.0:
7085+
jest-validate@^23.4.0:
70867086
version "23.4.0"
70877087
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.4.0.tgz#d96eede01ef03ac909c009e9c8e455197d48c201"
70887088
dependencies:
@@ -7606,34 +7606,6 @@ linkify-it@^2.0.0:
76067606
dependencies:
76077607
uc.micro "^1.0.1"
76087608

7609-
lint-staged@^7.2.0:
7610-
version "7.2.0"
7611-
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-7.2.0.tgz#bdf4bb7f2f37fe689acfaec9999db288a5b26888"
7612-
dependencies:
7613-
app-root-path "^2.0.1"
7614-
chalk "^2.3.1"
7615-
commander "^2.14.1"
7616-
cosmiconfig "^5.0.2"
7617-
debug "^3.1.0"
7618-
dedent "^0.7.0"
7619-
execa "^0.9.0"
7620-
find-parent-dir "^0.3.0"
7621-
is-glob "^4.0.0"
7622-
is-windows "^1.0.2"
7623-
jest-validate "^23.0.0"
7624-
listr "^0.14.1"
7625-
lodash "^4.17.5"
7626-
log-symbols "^2.2.0"
7627-
micromatch "^3.1.8"
7628-
npm-which "^3.0.1"
7629-
p-map "^1.1.1"
7630-
path-is-inside "^1.0.2"
7631-
pify "^3.0.0"
7632-
please-upgrade-node "^3.0.2"
7633-
staged-git-files "1.1.1"
7634-
string-argv "^0.0.2"
7635-
stringify-object "^3.2.2"
7636-
76377609
lint-staged@^7.2.2:
76387610
version "7.2.2"
76397611
resolved "http://registry.npm.taobao.org/lint-staged/download/lint-staged-7.2.2.tgz#0983d55d497f19f36d11ff2c8242b2f56cc2dd05"

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