From bc6433acf7b1de876dc095e6f112f047aa5598ae Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Mon, 9 Sep 2019 17:23:21 +0800 Subject: [PATCH 1/4] feat: support sass-loader v8 (cherry picked from commit af17a9b49fc31ff07f180e26edd4940a1404e516) --- docs/guide/css.md | 5 ++- docs/zh/guide/css.md | 5 ++- .../@vue/cli-service/__tests__/css.spec.js | 45 ++++++++++++++----- packages/@vue/cli-service/generator/index.js | 12 ++--- packages/@vue/cli-service/lib/config/css.js | 44 ++++++++++++++---- packages/@vue/cli-service/package.json | 6 +-- 6 files changed, 85 insertions(+), 32 deletions(-) diff --git a/docs/guide/css.md b/docs/guide/css.md index db819bce8a..b354442d2c 100644 --- a/docs/guide/css.md +++ b/docs/guide/css.md @@ -128,8 +128,9 @@ module.exports = { // pass options to sass-loader // @/ is an alias to src/ // so this assumes you have a file named `src/variables.sass` + // Note: this option is named as "data" in sass-loader v7 sass: { - data: `@import "~@/variables.sass"` + prependData: `@import "~@/variables.sass"` }, // by default the `sass` option will apply to both syntaxes // because `scss` syntax is also processed by sass-loader underlyingly @@ -137,7 +138,7 @@ module.exports = { // `scss` syntax requires an semicolon at the end of a statement, while `sass` syntax requires none // in that case, we can target the `scss` syntax separately using the `scss` option scss: { - data: `@import "~@/variables.scss";` + prependData: `@import "~@/variables.scss";` }, // pass Less.js Options to less-loader less:{ diff --git a/docs/zh/guide/css.md b/docs/zh/guide/css.md index aeb0aeba20..a7cb4c4e0d 100644 --- a/docs/zh/guide/css.md +++ b/docs/zh/guide/css.md @@ -129,7 +129,8 @@ module.exports = { sass: { // @/ 是 src/ 的别名 // 所以这里假设你有 `src/variables.sass` 这个文件 - data: `@import "~@/variables.sass"` + // 注意:在 sass-loader v7 中,这个选项名是 "data" + prependData: `@import "~@/variables.sass"` }, // 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效 // 因为 `scss` 语法在内部也是由 sass-loader 处理的 @@ -137,7 +138,7 @@ module.exports = { // `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号 // 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置 scss: { - data: `@import "~@/variables.scss";` + prependData: `@import "~@/variables.scss";` }, // 给 less-loader 传递 Less.js 相关选项 less:{ diff --git a/packages/@vue/cli-service/__tests__/css.spec.js b/packages/@vue/cli-service/__tests__/css.spec.js index b51aa7408c..4615cce735 100644 --- a/packages/@vue/cli-service/__tests__/css.spec.js +++ b/packages/@vue/cli-service/__tests__/css.spec.js @@ -62,7 +62,12 @@ test('default loaders', () => { }) }) // sass indented syntax - expect(findOptions(config, 'sass', 'sass')).toMatchObject({ indentedSyntax: true, sourceMap: false }) + expect(findOptions(config, 'sass', 'sass')).toMatchObject({ + sassOptions: { + indentedSyntax: true + }, + sourceMap: false + }) }) test('production defaults', () => { @@ -180,21 +185,30 @@ test('css-loader options', () => { }) test('css.loaderOptions', () => { - const data = '$env: production;' + const prependData = '$env: production;' const config = genConfig({ vue: { css: { loaderOptions: { sass: { - data + prependData } } } } }) - expect(findOptions(config, 'scss', 'sass')).toMatchObject({ data, sourceMap: false }) - expect(findOptions(config, 'sass', 'sass')).toMatchObject({ data, indentedSyntax: true, sourceMap: false }) + expect(findOptions(config, 'scss', 'sass')).toMatchObject({ + prependData, + sourceMap: false + }) + expect(findOptions(config, 'sass', 'sass')).toMatchObject({ + prependData, + sassOptions: { + indentedSyntax: true + }, + sourceMap: false + }) }) test('scss loaderOptions', () => { @@ -206,24 +220,33 @@ test('scss loaderOptions', () => { css: { loaderOptions: { sass: { - sassData + prependData: sassData }, scss: { - scssData + prependData: scssData } } } } }) - expect(findOptions(config, 'scss', 'sass')).toMatchObject({ scssData, sourceMap: false }) - expect(findOptions(config, 'sass', 'sass')).toMatchObject({ sassData, indentedSyntax: true, sourceMap: false }) + expect(findOptions(config, 'scss', 'sass')).toMatchObject({ + prependData: scssData, + sourceMap: false + }) + expect(findOptions(config, 'sass', 'sass')).toMatchObject({ + prependData: sassData, + sassOptions: { + indentedSyntax: true + }, + sourceMap: false + }) }) test('should use dart sass implementation whenever possible', () => { const config = genConfig() - expect(findOptions(config, 'scss', 'sass')).toMatchObject({ fiber: require('fibers'), implementation: require('sass') }) - expect(findOptions(config, 'sass', 'sass')).toMatchObject({ fiber: require('fibers'), implementation: require('sass') }) + expect(findOptions(config, 'scss', 'sass')).toMatchObject({ implementation: require('sass') }) + expect(findOptions(config, 'sass', 'sass')).toMatchObject({ implementation: require('sass') }) }) test('skip postcss-loader if no postcss config found', () => { diff --git a/packages/@vue/cli-service/generator/index.js b/packages/@vue/cli-service/generator/index.js index 0ef373f501..4e38c386e7 100644 --- a/packages/@vue/cli-service/generator/index.js +++ b/packages/@vue/cli-service/generator/index.js @@ -37,16 +37,16 @@ module.exports = (api, options) => { const deps = { // TODO: remove 'sass' option in v4 or rename 'dart-sass' to 'sass' sass: { - 'node-sass': '^4.9.0', - 'sass-loader': '^7.1.0' + 'node-sass': '^4.12.0', + 'sass-loader': '^8.0.0' }, 'node-sass': { - 'node-sass': '^4.9.0', - 'sass-loader': '^7.1.0' + 'node-sass': '^4.12.0', + 'sass-loader': '^8.0.0' }, 'dart-sass': { - sass: '^1.18.0', - 'sass-loader': '^7.1.0' + sass: '^1.19.0', + 'sass-loader': '^8.0.0' }, less: { 'less': '^3.0.4', diff --git a/packages/@vue/cli-service/lib/config/css.js b/packages/@vue/cli-service/lib/config/css.js index 4506de43fc..ef8b8d4748 100644 --- a/packages/@vue/cli-service/lib/config/css.js +++ b/packages/@vue/cli-service/lib/config/css.js @@ -1,5 +1,7 @@ const fs = require('fs') const path = require('path') +const semver = require('semver') +const { warn } = require('@vue/cli-shared-utils') const findExisting = (context, files) => { for (const file of files) { @@ -15,10 +17,21 @@ module.exports = (api, options) => { const shadowMode = !!process.env.VUE_CLI_CSS_SHADOW_MODE const isProd = process.env.NODE_ENV === 'production' + let sassLoaderVersion + try { + sassLoaderVersion = semver.major(require('sass-loader/package.json').version) + } catch (e) {} + if (sassLoaderVersion < 8) { + warn('sass-loader v8 is out, please consider upgrading your sass-loader version.') + } + const defaultSassLoaderOptions = {} try { defaultSassLoaderOptions.implementation = require('sass') - defaultSassLoaderOptions.fiber = require('fibers') + // since sass-loader 8, fibers will be automatically detected and used + if (sassLoaderVersion < 8) { + defaultSassLoaderOptions.fiber = require('fibers') + } } catch (e) {} const { @@ -169,13 +182,28 @@ module.exports = (api, options) => { defaultSassLoaderOptions, loaderOptions.scss || loaderOptions.sass )) - createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( - defaultSassLoaderOptions, - { - indentedSyntax: true - }, - loaderOptions.sass - )) + if (sassLoaderVersion < 8) { + createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( + defaultSassLoaderOptions, + { + indentedSyntax: true + }, + loaderOptions.sass + )) + } else { + createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( + defaultSassLoaderOptions, + loaderOptions.sass, + { + sassOptions: Object.assign( + (loaderOptions.sass && loaderOptions.sass.sassOptions) || {}, + { + indentedSyntax: true + } + ) + } + )) + } createCSSRule('less', /\.less$/, 'less-loader', loaderOptions.less) createCSSRule('stylus', /\.styl(us)?$/, 'stylus-loader', Object.assign({ preferPathResolver: 'webpack' diff --git a/packages/@vue/cli-service/package.json b/packages/@vue/cli-service/package.json index 3abe7fabe9..d6866249ba 100644 --- a/packages/@vue/cli-service/package.json +++ b/packages/@vue/cli-service/package.json @@ -84,9 +84,9 @@ "vue-template-compiler": "^2.0.0" }, "devDependencies": { - "fibers": "^3.1.1", - "sass": "^1.18.0", - "sass-loader": "^7.1.0", + "fibers": ">= 3.1.1 <5.0.0", + "sass": "^1.19.0", + "sass-loader": "^8.0.0", "vue": "^2.6.10", "vue-router": "^3.0.3", "vue-template-compiler": "^2.6.10", From c0baf059602fa4d828f635a9fa04031925d90abf Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Mon, 30 Sep 2019 14:02:48 +0800 Subject: [PATCH 2/4] fix: fix sassOptions merging for scss syntax in sass-loader v8 (#4631) fixes #4630 (cherry picked from commit ebdb142a4b61f9b94279a5f4e7e654500f75fbcf) --- packages/@vue/cli-service/__tests__/css.spec.js | 14 +++++++++++--- packages/@vue/cli-service/lib/config/css.js | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/@vue/cli-service/__tests__/css.spec.js b/packages/@vue/cli-service/__tests__/css.spec.js index 4615cce735..4b52d6cf9a 100644 --- a/packages/@vue/cli-service/__tests__/css.spec.js +++ b/packages/@vue/cli-service/__tests__/css.spec.js @@ -191,7 +191,10 @@ test('css.loaderOptions', () => { css: { loaderOptions: { sass: { - prependData + prependData, + sassOptions: { + includePaths: ['./src/styles'] + } } } } @@ -200,12 +203,17 @@ test('css.loaderOptions', () => { expect(findOptions(config, 'scss', 'sass')).toMatchObject({ prependData, - sourceMap: false + sourceMap: false, + sassOptions: { + includePaths: ['./src/styles'] + } }) + expect(findOptions(config, 'scss', 'sass').sassOptions).not.toHaveProperty('indentedSyntax') expect(findOptions(config, 'sass', 'sass')).toMatchObject({ prependData, sassOptions: { - indentedSyntax: true + indentedSyntax: true, + includePaths: ['./src/styles'] }, sourceMap: false }) diff --git a/packages/@vue/cli-service/lib/config/css.js b/packages/@vue/cli-service/lib/config/css.js index ef8b8d4748..def03a06e0 100644 --- a/packages/@vue/cli-service/lib/config/css.js +++ b/packages/@vue/cli-service/lib/config/css.js @@ -196,7 +196,8 @@ module.exports = (api, options) => { loaderOptions.sass, { sassOptions: Object.assign( - (loaderOptions.sass && loaderOptions.sass.sassOptions) || {}, + {}, + loaderOptions.sass && loaderOptions.sass.sassOptions, { indentedSyntax: true } From 2c61e34697aa04298d86ed79f249b86f9e3b9b99 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Tue, 1 Oct 2019 23:30:15 +0800 Subject: [PATCH 3/4] fix: avoid accidentally overriding sass config with scss configs (#4637) (cherry picked from commit e63bf6122bb979e2dac258074c13e55b3471caa2) --- packages/@vue/cli-service/__tests__/css.spec.js | 6 +++++- packages/@vue/cli-service/lib/config/css.js | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/@vue/cli-service/__tests__/css.spec.js b/packages/@vue/cli-service/__tests__/css.spec.js index 4b52d6cf9a..5d8d337f66 100644 --- a/packages/@vue/cli-service/__tests__/css.spec.js +++ b/packages/@vue/cli-service/__tests__/css.spec.js @@ -231,7 +231,8 @@ test('scss loaderOptions', () => { prependData: sassData }, scss: { - prependData: scssData + prependData: scssData, + webpackImporter: false } } } @@ -249,6 +250,9 @@ test('scss loaderOptions', () => { }, sourceMap: false }) + + // should not merge scss options into default sass config + expect(findOptions(config, 'sass', 'sass')).not.toHaveProperty('webpackImporter') }) test('should use dart sass implementation whenever possible', () => { diff --git a/packages/@vue/cli-service/lib/config/css.js b/packages/@vue/cli-service/lib/config/css.js index def03a06e0..dc70147193 100644 --- a/packages/@vue/cli-service/lib/config/css.js +++ b/packages/@vue/cli-service/lib/config/css.js @@ -179,11 +179,13 @@ module.exports = (api, options) => { createCSSRule('css', /\.css$/) createCSSRule('postcss', /\.p(ost)?css$/) createCSSRule('scss', /\.scss$/, 'sass-loader', Object.assign( + {}, defaultSassLoaderOptions, loaderOptions.scss || loaderOptions.sass )) if (sassLoaderVersion < 8) { createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( + {}, defaultSassLoaderOptions, { indentedSyntax: true @@ -192,6 +194,7 @@ module.exports = (api, options) => { )) } else { createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( + {}, defaultSassLoaderOptions, loaderOptions.sass, { From 98840df8b78d37d73c3b8df967b4a9ce5a6e3ea3 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Wed, 9 Oct 2019 11:06:36 +0800 Subject: [PATCH 4/4] chore: don't warn user for sass-loader version here --- packages/@vue/cli-service/lib/config/css.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/@vue/cli-service/lib/config/css.js b/packages/@vue/cli-service/lib/config/css.js index dc70147193..e77dd2f238 100644 --- a/packages/@vue/cli-service/lib/config/css.js +++ b/packages/@vue/cli-service/lib/config/css.js @@ -1,7 +1,6 @@ const fs = require('fs') const path = require('path') const semver = require('semver') -const { warn } = require('@vue/cli-shared-utils') const findExisting = (context, files) => { for (const file of files) { @@ -21,9 +20,6 @@ module.exports = (api, options) => { try { sassLoaderVersion = semver.major(require('sass-loader/package.json').version) } catch (e) {} - if (sassLoaderVersion < 8) { - warn('sass-loader v8 is out, please consider upgrading your sass-loader version.') - } const defaultSassLoaderOptions = {} try {