diff --git a/package.json b/package.json index 8573b6c839b208..dd7fd3958a93e8 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "@rollup/plugin-node-resolve": "^7.1.3", "@types/koa": "^2.11.3", "@vue/compiler-sfc": "^3.0.0-beta.9", - "@vue/shared": "^3.0.0-beta.9", "chalk": "^4.0.0", "chokidar": "^3.3.1", "cssnano": "^4.1.10", diff --git a/playground/main.js b/playground/main.js index c74fcb00aa01ee..168f67249e41a7 100644 --- a/playground/main.js +++ b/playground/main.js @@ -3,5 +3,3 @@ import App from './App.vue' import './testHmrManual' createApp(App).mount('#app') - -console.log('foooo') diff --git a/src/node/esbuildService.ts b/src/node/esbuildService.ts index fe77ba60e69669..a0bcc7d9320cbc 100644 --- a/src/node/esbuildService.ts +++ b/src/node/esbuildService.ts @@ -1,7 +1,7 @@ import path from 'path' import { startService, Service, TransformOptions, Message } from 'esbuild' import chalk from 'chalk' -import { generateCodeFrame } from '@vue/shared' +import { generateCodeFrame } from '@vue/compiler-sfc' const debug = require('debug')('vite:esbuild') diff --git a/src/node/server/serverPluginVue.ts b/src/node/server/serverPluginVue.ts index e28f2bd2384b37..35d305a582171b 100644 --- a/src/node/server/serverPluginVue.ts +++ b/src/node/server/serverPluginVue.ts @@ -1,10 +1,12 @@ +import chalk from 'chalk' import path from 'path' import { Plugin } from '.' import { SFCDescriptor, SFCTemplateBlock, SFCStyleBlock, - SFCStyleCompileResults + SFCStyleCompileResults, + generateCodeFrame } from '@vue/compiler-sfc' import { resolveCompiler } from '../utils/resolveVue' import hash_sum from 'hash-sum' @@ -124,10 +126,22 @@ export async function parseSFC( }) if (errors.length) { + console.error(chalk.red(`\n[vite] SFC parse error: `)) errors.forEach((e) => { - console.error(`[vite] SFC parse error: `, e) + console.error( + chalk.underline( + `${filename}:${e.loc!.start.line}:${e.loc!.start.column}` + ) + ) + console.error(chalk.yellow(e.message)) + console.error( + generateCodeFrame( + content as string, + e.loc!.start.offset, + e.loc!.end.offset + ) + ) }) - console.error(`source:\n`, content) } cached = cached || { styles: [] } @@ -210,11 +224,11 @@ async function compileSFCMain( function compileSFCTemplate( root: string, template: SFCTemplateBlock, - filePath: string, + filename: string, publicPath: string, scoped: boolean ): string { - let cached = vueCache.get(filePath) + let cached = vueCache.get(filename) if (cached && cached.template) { debug(`${publicPath} template cache hit`) return cached.template @@ -223,7 +237,7 @@ function compileSFCTemplate( const start = Date.now() const { code, map, errors } = resolveCompiler(root).compileTemplate({ source: template.content, - filename: filePath, + filename, inMap: template.map, transformAssetUrls: { base: path.posix.dirname(publicPath) @@ -237,16 +251,29 @@ function compileSFCTemplate( }) if (errors.length) { + console.error(chalk.red(`\n[vite] SFC template compilation error: `)) errors.forEach((e) => { - console.error(`[vite] SFC template compilation error: `, e) + if (typeof e === 'string') { + console.error(e) + } else { + console.error( + chalk.underline( + `${filename}:${e.loc!.start.line}:${e.loc!.start.column}` + ) + ) + console.error(chalk.yellow(e.message)) + const original = template.map!.sourcesContent![0] + console.error( + generateCodeFrame(original, e.loc!.start.offset, e.loc!.end.offset) + ) + } }) - console.error(`source:\n`, template.content) } const finalCode = code + genSourceMapString(map) cached = cached || { styles: [] } cached.template = finalCode - vueCache.set(filePath, cached) + vueCache.set(filename, cached) debug(`${publicPath} template compiled in ${Date.now() - start}ms.`) return finalCode @@ -256,10 +283,10 @@ async function compileSFCStyle( root: string, style: SFCStyleBlock, index: number, - filePath: string, + filename: string, publicPath: string ): Promise { - let cached = vueCache.get(filePath) + let cached = vueCache.get(filename) const cachedEntry = cached && cached.styles && cached.styles[index] if (cachedEntry) { debug(`${publicPath} style cache hit`) @@ -272,7 +299,7 @@ async function compileSFCStyle( const result = await resolveCompiler(root).compileStyleAsync({ source: style.content, - filename: filePath, + filename, id: `data-v-${id}`, scoped: style.scoped != null, modules: style.module != null, @@ -287,15 +314,45 @@ async function compileSFCStyle( }) if (result.errors.length) { - result.errors.forEach((e) => { - console.error(`[vite] SFC style compilation error: `, e) + console.error(chalk.red(`\n[vite] SFC style compilation error: `)) + result.errors.forEach((e: any) => { + if (typeof e === 'string') { + console.error(e) + } else { + const lineOffset = style.loc.start.line - 1 + if (e.line && e.column) { + console.log( + chalk.underline(`${filename}:${e.line + lineOffset}:${e.column}`) + ) + } else { + console.log(chalk.underline(filename)) + } + const filenameRE = new RegExp( + '.*' + + path.basename(filename).replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&') + + '(:\\d+:\\d+:\\s*)?' + ) + const cleanMsg = e.message.replace(filenameRE, '') + console.error(chalk.yellow(cleanMsg)) + if (e.line && e.column && cleanMsg.split(/\n/g).length === 1) { + const original = style.map!.sourcesContent![0] + const offset = + original + .split(/\r?\n/g) + .slice(0, e.line + lineOffset - 1) + .map((l) => l.length) + .reduce((total, l) => total + l + 1, 0) + + e.column - + 1 + console.error(generateCodeFrame(original, offset, offset + 1)) + } + } }) - console.error(`source:\n`, style.content) } cached = cached || { styles: [] } cached.styles[index] = result - vueCache.set(filePath, cached) + vueCache.set(filename, cached) debug(`${publicPath} style compiled in ${Date.now() - start}ms`) return result