From e111c601759e74cb13d6900d6da99ad1a6d4a786 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 29 May 2020 19:04:42 -0400 Subject: [PATCH] refactor: apply postcss-import in compileCss + remove precprocessor @import tests --- playground/App.vue | 6 +- playground/css-@import/TestCssAtImport.vue | 19 +++++ playground/css-@import/imported.css | 3 + .../css-@import/testCssAtImportFromScript.css | 1 + .../css-@import/testCssAtImportFromStyle.css | 3 + .../css-@import/testCssImportBoundary.css | 3 - .../testCssImportBoundary.module.scss | 5 -- .../css-@import/testCssImportBoundary.scss | 1 - .../css-@import/testCssImportBoundary.vue | 31 -------- src/node/build/buildPluginCss.ts | 11 +-- src/node/server/serverPluginCss.ts | 16 +--- src/node/server/serverPluginVue.ts | 24 +----- src/node/utils/cssUtils.ts | 73 ++++++++++--------- test/test.js | 56 ++++++-------- 14 files changed, 96 insertions(+), 156 deletions(-) create mode 100644 playground/css-@import/TestCssAtImport.vue create mode 100644 playground/css-@import/imported.css create mode 100644 playground/css-@import/testCssAtImportFromScript.css create mode 100644 playground/css-@import/testCssAtImportFromStyle.css delete mode 100644 playground/css-@import/testCssImportBoundary.css delete mode 100644 playground/css-@import/testCssImportBoundary.module.scss delete mode 100644 playground/css-@import/testCssImportBoundary.scss delete mode 100644 playground/css-@import/testCssImportBoundary.vue diff --git a/playground/App.vue b/playground/App.vue index dc94b218c16425..81b380ce05cb46 100644 --- a/playground/App.vue +++ b/playground/App.vue @@ -14,7 +14,7 @@ - + @@ -43,7 +43,7 @@ import TestJsx from './TestJsx.vue' import TestAlias from './TestAlias.vue' import TestTransform from './TestTransform.vue' import TestRewriteOptimized from "./rewrite-optimized/TestRewriteOptimized.vue"; -import TestCssImportBoundary from './css-@import/testCssImportBoundary.vue' +import TestCssAtImport from './css-@import/TestCssAtImport.vue' export default { data: () => ({ @@ -58,7 +58,7 @@ export default { TestScopedCss, TestCssModules, TestPreprocessors, - TestCssImportBoundary, + TestCssAtImport, TestSrcImport, TestAssets, TestJsonImport, diff --git a/playground/css-@import/TestCssAtImport.vue b/playground/css-@import/TestCssAtImport.vue new file mode 100644 index 00000000000000..2d0057863a9ed0 --- /dev/null +++ b/playground/css-@import/TestCssAtImport.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/playground/css-@import/imported.css b/playground/css-@import/imported.css new file mode 100644 index 00000000000000..954e5708f09d0c --- /dev/null +++ b/playground/css-@import/imported.css @@ -0,0 +1,3 @@ +.script-at-import { + color: green; +} diff --git a/playground/css-@import/testCssAtImportFromScript.css b/playground/css-@import/testCssAtImportFromScript.css new file mode 100644 index 00000000000000..83dcc223c86630 --- /dev/null +++ b/playground/css-@import/testCssAtImportFromScript.css @@ -0,0 +1 @@ +@import './imported.css' diff --git a/playground/css-@import/testCssAtImportFromStyle.css b/playground/css-@import/testCssAtImportFromStyle.css new file mode 100644 index 00000000000000..1557d3b3c0d5a5 --- /dev/null +++ b/playground/css-@import/testCssAtImportFromStyle.css @@ -0,0 +1,3 @@ +.sfc-style-at-import { + color: red; +} diff --git a/playground/css-@import/testCssImportBoundary.css b/playground/css-@import/testCssImportBoundary.css deleted file mode 100644 index e6f9b665e56de3..00000000000000 --- a/playground/css-@import/testCssImportBoundary.css +++ /dev/null @@ -1,3 +0,0 @@ -.style-at-import { - color: red; -} diff --git a/playground/css-@import/testCssImportBoundary.module.scss b/playground/css-@import/testCssImportBoundary.module.scss deleted file mode 100644 index 000f9bd40b78bf..00000000000000 --- a/playground/css-@import/testCssImportBoundary.module.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import "./testCssImportBoundary.scss"; - -.style-import-module-w-at-import { - color: $scssImport; -} diff --git a/playground/css-@import/testCssImportBoundary.scss b/playground/css-@import/testCssImportBoundary.scss deleted file mode 100644 index 528826ee516454..00000000000000 --- a/playground/css-@import/testCssImportBoundary.scss +++ /dev/null @@ -1 +0,0 @@ -$scssImport: red diff --git a/playground/css-@import/testCssImportBoundary.vue b/playground/css-@import/testCssImportBoundary.vue deleted file mode 100644 index fb696122116192..00000000000000 --- a/playground/css-@import/testCssImportBoundary.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - diff --git a/src/node/build/buildPluginCss.ts b/src/node/build/buildPluginCss.ts index b0d8721c51571c..319674f4eb0177 100644 --- a/src/node/build/buildPluginCss.ts +++ b/src/node/build/buildPluginCss.ts @@ -7,8 +7,7 @@ import { urlRE, compileCss, cssPreprocessLangRE, - rewriteCssUrls, - parseCssImport + rewriteCssUrls } from '../utils/cssUtils' import { SFCStyleCompileResults } from '@vue/compiler-sfc' @@ -32,16 +31,10 @@ export const createBuildCssPlugin = ( name: 'vite:css', async transform(css: string, id: string) { if (id.endsWith('.css') || cssPreprocessLangRE.test(id)) { - const res = await parseCssImport(css, id) - if (typeof res === 'string') { - css = res - } else { - css = res.css - } const result = await compileCss(root, id, { id: '', source: css, - filename: path.basename(id), + filename: id, scoped: false, modules: id.endsWith('.module.css'), preprocessLang: id.replace(cssPreprocessLangRE, '$2') as any diff --git a/src/node/server/serverPluginCss.ts b/src/node/server/serverPluginCss.ts index 82dec8c8842960..da5356ab3c0b1d 100644 --- a/src/node/server/serverPluginCss.ts +++ b/src/node/server/serverPluginCss.ts @@ -10,8 +10,6 @@ import { cssImportMap, cssPreprocessLangRE, getCssImportBoundaries, - parseCssImport, - recordCssImportPlain, rewriteCssUrls } from '../utils/cssUtils' import qs from 'querystring' @@ -78,7 +76,7 @@ export const cssPlugin: ServerPlugin = ({ root, app, watcher, resolver }) => { return } // handle HMR for module.css - // it cannot process with normal css, the class which in module.css maybe removed + // it cannot be handled as normal css because the js exports may change if (filePath.endsWith('.module.css')) { moduleCssUpdate(filePath) return @@ -130,17 +128,7 @@ export const cssPlugin: ServerPlugin = ({ root, app, watcher, resolver }) => { } async function processCss(root: string, ctx: Context) { - let css = (await readBody(ctx.body))! - // should parser import before compile - const res = await parseCssImport(css, resolver.requestToFile(ctx.path)) - - if (typeof res === 'string') { - css = res - } else { - css = res.css - recordCssImportPlain(res.messages) - } - + const css = (await readBody(ctx.body))! const result = await compileCss(root, ctx.path, { id: '', source: css, diff --git a/src/node/server/serverPluginVue.ts b/src/node/server/serverPluginVue.ts index 8486b3cbb3daab..6ba6e0f2d2d51a 100644 --- a/src/node/server/serverPluginVue.ts +++ b/src/node/server/serverPluginVue.ts @@ -29,13 +29,7 @@ import { Context } from 'koa' import { transform } from '../esbuildService' import { InternalResolver } from '../resolver' import { seenUrls } from './serverPluginServeStatic' -import { - codegenCss, - compileCss, - parseCssImport, - recordCssImportPlain, - rewriteCssUrls -} from '../utils/cssUtils' +import { codegenCss, compileCss, rewriteCssUrls } from '../utils/cssUtils' import { parse } from '../utils/babelParse' import MagicString from 'magic-string' import { resolveImport } from './serverPluginModuleRewrite' @@ -520,21 +514,9 @@ async function compileSFCStyle( const start = Date.now() const { generateCodeFrame } = resolveCompiler(root) - - let css = style.content - // should parser css import before compile - const res = await parseCssImport(css, `${filePath}?type=style&index=${index}`) - - if (typeof res === 'string') { - css = res - } else { - css = res.css - recordCssImportPlain(res.messages) - } - const result = (await compileCss(root, publicPath, { - source: css, - filename: filePath, + source: style.content, + filename: filePath + `?type=style&index=${index}`, id: ``, // will be computed in compileCss scoped: style.scoped != null, modules: style.module != null, diff --git a/src/node/utils/cssUtils.ts b/src/node/utils/cssUtils.ts index fd19eee60823a4..abd066257b8eff 100644 --- a/src/node/utils/cssUtils.ts +++ b/src/node/utils/cssUtils.ts @@ -10,8 +10,7 @@ import { SFCStyleCompileResults } from '@vue/compiler-sfc' import { hmrClientPublicPath } from '../server/serverPluginHmr' -import postcss, { Result, ResultMessage } from 'postcss' -import cssImport from 'postcss-import' + export const urlRE = /(url\(\s*['"]?)([^"')]+)(["']?\s*\))/ export const cssPreprocessLangRE = /(.+).(less|sass|scss|styl|stylus)$/ @@ -55,15 +54,24 @@ export async function compileCss( }: SFCAsyncStyleCompileOptions ): Promise { const id = hash_sum(publicPath) - const postcssConfig = await loadPostcssConfig(root) + let postcssConfig = await loadPostcssConfig(root) const { compileStyleAsync } = resolveCompiler(root) - if (publicPath.endsWith('.css') && !modules && !postcssConfig) { + if ( + publicPath.endsWith('.css') && + !modules && + !postcssConfig && + !source.includes('@import') + ) { // no need to invoke compile for plain css if no postcss config is present return source } - return await compileStyleAsync({ + const postcssOptions = postcssConfig && postcssConfig.options + const postcssPlugins = postcssConfig ? postcssConfig.plugins : [] + postcssPlugins.push(require('postcss-import')()) + + const res = await compileStyleAsync({ source, filename, id: `data-v-${id}`, @@ -72,18 +80,32 @@ export async function compileCss( modulesOptions: { generateScopedName: `[local]_${id}` }, + preprocessLang: preprocessLang, preprocessCustomRequire: (id: string) => require(resolveFrom(root, id)), - ...(postcssConfig - ? { - postcssOptions: postcssConfig.options, - postcssPlugins: postcssConfig.plugins - } - : {}), preprocessOptions: { includePaths: ['node_modules'] - } + }, + + postcssOptions, + postcssPlugins }) + + // record css import dependencies + if (res.rawResult) { + res.rawResult.messages.forEach((msg) => { + let { type, file, parent } = msg + if (type === 'dependency') { + if (cssImportMap.has(file)) { + cssImportMap.get(file)!.add(parent) + } else { + cssImportMap.set(file, new Set([parent])) + } + } + }) + } + + return res } export function codegenCss( @@ -133,34 +155,13 @@ export const cssImportMap = new Map< Set >() -export async function parseCssImport( - css: string, - filePath: string -): Promise { - if (!css.includes('@import')) { - return css - } - return await postcss().use(cssImport()).process(css, { from: filePath }) -} - -export function recordCssImportPlain(messages: ResultMessage[]) { - messages.forEach((msg) => { - let { type, file, parent } = msg - if (type === 'dependency') { - if (cssImportMap.has(file)) { - cssImportMap.get(file)!.add(parent) - } else { - cssImportMap.set(file, new Set([parent])) - } - } - }) -} - export function getCssImportBoundaries( filePath: string, boundaries = new Set() ) { - if (!cssImportMap.has(filePath)) return boundaries + if (!cssImportMap.has(filePath)) { + return boundaries + } const importers = cssImportMap.get(filePath)! for (const importer of importers) { boundaries.add(importer) diff --git a/test/test.js b/test/test.js index 8b17556b3164a8..7f5f335199730a 100644 --- a/test/test.js +++ b/test/test.js @@ -184,39 +184,6 @@ describe('vite', () => { }) } - test('SFC normal css w/ @import', async () => { - const el = await page.$('.style-at-import') - expect(await getComputedColor(el)).toBe('rgb(255, 0, 0)') - if (!isBuild) { - await updateFile('css-@import/testCssImportBoundary.css', (content) => - content.replace('red', 'rgb(0, 0, 0)') - ) - await expectByPolling(() => getComputedColor(el), 'rgb(0, 0, 0)') - } - }) - - test('SFC preprocessor w/ @import', async () => { - const el = await page.$('.style-at-import-scss') - expect(await getComputedColor(el)).toBe('rgb(255, 0, 0)') - if (!isBuild) { - await updateFile('css-@import/testCssImportBoundary.scss', (content) => - content.replace('red', 'rgb(0, 0, 0)') - ) - await expectByPolling(() => getComputedColor(el), 'rgb(0, 0, 0)') - } - }) - - // test('SFC