From d18ab9e2754609268804348dabb1ee2681e5a85c Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 21 Sep 2021 15:01:18 -0400 Subject: [PATCH] feat(plugin-vue): support optional @vue/compiler-sfc peer dep --- package.json | 4 +-- packages/plugin-vue/README.md | 4 +-- packages/plugin-vue/package.json | 8 +++--- packages/plugin-vue/src/compiler.ts | 25 +++++++++++++++++ packages/plugin-vue/src/index.ts | 27 ++++--------------- packages/plugin-vue/src/main.ts | 5 ++-- packages/plugin-vue/src/script.ts | 5 ++-- packages/plugin-vue/src/style.ts | 5 ++-- packages/plugin-vue/src/template.ts | 6 ++--- .../plugin-vue/src/utils/descriptorCache.ts | 5 ++-- 10 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 packages/plugin-vue/src/compiler.ts diff --git a/package.json b/package.json index 1034bc80..423735d7 100644 --- a/package.json +++ b/package.json @@ -60,9 +60,9 @@ "yorkie": "^2.0.0" }, "peerDependencies": { + "less": ">=4.0.0", "sass": ">=1.0.0", - "stylus": ">=0.54.0", - "less": ">=4.0.0" + "stylus": ">=0.54.0" }, "peerDependenciesMeta": { "sass": { diff --git a/packages/plugin-vue/README.md b/packages/plugin-vue/README.md index 9dcfefd8..b29039da 100644 --- a/packages/plugin-vue/README.md +++ b/packages/plugin-vue/README.md @@ -1,6 +1,6 @@ # @vitejs/plugin-vue [![npm](https://img.shields.io/npm/v/@vitejs/plugin-vue.svg)](https://npmjs.com/package/@vitejs/plugin-vue) -Note: requires `@vue/compiler-sfc` as peer dependency. This is largely a port of `rollup-plugin-vue` with some vite-specific tweaks. +> Note: as of `vue` 3.2.13+ and `@vitejs/plugin-vue` 1.9.0+, `@vue/compiler-sfc` is no longer required as a peer dependency. ```js // vite.config.js @@ -46,7 +46,7 @@ export interface Options { */ refTransform?: boolean | string | RegExp | (string | RegExp)[] - // options to pass on to @vue/compiler-sfc + // options to pass on to vue/compiler-sfc script?: Partial template?: Partial style?: Partial diff --git a/packages/plugin-vue/package.json b/packages/plugin-vue/package.json index 9d41e701..cbf09826 100644 --- a/packages/plugin-vue/package.json +++ b/packages/plugin-vue/package.json @@ -11,7 +11,7 @@ "scripts": { "dev": "tsc -p . -w --incremental", "build": "rimraf dist && run-s build-bundle build-types", - "build-bundle": "esbuild src/index.ts --bundle --platform=node --target=node12 --external:@vue/compiler-sfc --external:vite --outfile=dist/index.js", + "build-bundle": "esbuild src/index.ts --bundle --platform=node --target=node12 --external:@vue/compiler-sfc --external:vue/compiler-sfc --external:vite --outfile=dist/index.js", "build-types": "tsc -p . --emitDeclarationOnly --outDir temp && api-extractor run && rimraf temp", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --commit-path . --lerna-package plugin-vue", "release": "node ../../scripts/release.js" @@ -29,17 +29,17 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-vue#readme", "peerDependencies": { - "@vue/compiler-sfc": "^3.2.6", "vite": "^2.5.10" }, "devDependencies": { "@rollup/pluginutils": "^4.1.1", "@types/hash-sum": "^1.0.0", - "@vue/compiler-sfc": "^3.2.12", "debug": "^4.3.2", "hash-sum": "^2.0.0", "rollup": "^2.38.5", "slash": "^3.0.0", - "source-map": "^0.6.1" + "source-map": "^0.6.1", + "vue": "^3.2.13", + "@vue/compiler-sfc": "^3.2.13" } } diff --git a/packages/plugin-vue/src/compiler.ts b/packages/plugin-vue/src/compiler.ts new file mode 100644 index 00000000..e7ece1df --- /dev/null +++ b/packages/plugin-vue/src/compiler.ts @@ -0,0 +1,25 @@ +// extend the descriptor so we can store the scopeId on it +declare module '@vue/compiler-sfc' { + interface SFCDescriptor { + id: string + } +} + +import * as _compiler from '@vue/compiler-sfc' + +export let compiler: typeof _compiler + +try { + // Vue 3.2.13+ ships the SFC compiler directly under the `vue` package + // making it no longer necessary to have @vue/compiler-sfc separately installed. + compiler = require('vue/compiler-sfc') +} catch (e) { + try { + compiler = require('@vue/compiler-sfc') + } catch (e) { + throw new Error( + `@vitejs/plugin-vue requires vue (>=3.2.13) or @vue/compiler-sfc ` + + `to be present in the dependency tree.` + ) + } +} diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts index f42fad71..f326a4da 100644 --- a/packages/plugin-vue/src/index.ts +++ b/packages/plugin-vue/src/index.ts @@ -1,12 +1,3 @@ -try { - require.resolve('@vue/compiler-sfc') -} catch (e) { - throw new Error( - '@vitejs/plugin-vue requires @vue/compiler-sfc to be present in the dependency ' + - 'tree.' - ) -} - import fs from 'fs' import { Plugin, ViteDevServer } from 'vite' import { createFilter } from '@rollup/pluginutils' @@ -14,10 +5,9 @@ import { SFCBlock, SFCScriptCompileOptions, SFCStyleCompileOptions, - SFCTemplateCompileOptions, - shouldTransformRef, - transformRef + SFCTemplateCompileOptions } from '@vue/compiler-sfc' +import { compiler } from './compiler' import { parseVueRequest } from './utils/query' import { getDescriptor } from './utils/descriptorCache' import { getResolvedScript } from './script' @@ -27,13 +17,6 @@ import { transformTemplateAsModule } from './template' import { transformStyle } from './style' import { EXPORT_HELPER_ID, helperCode } from './helper' -// extend the descriptor so we can store the scopeId on it -declare module '@vue/compiler-sfc' { - interface SFCDescriptor { - id: string - } -} - export { parseVueRequest, VueQuery } from './utils/query' export interface Options { @@ -108,7 +91,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { : createFilter(refTransform) // compat for older verisons - const canUseRefTransform = typeof shouldTransformRef === 'function' + const canUseRefTransform = typeof compiler.shouldTransformRef === 'function' let options: ResolvedOptions = { isProduction: process.env.NODE_ENV === 'production', @@ -209,8 +192,8 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { if (!query.vue && refTransformFilter(filename)) { if (!canUseRefTransform) { this.warn('refTransform requires @vue/compiler-sfc@^3.2.5.') - } else if (shouldTransformRef(code)) { - return transformRef(code, { + } else if (compiler.shouldTransformRef(code)) { + return compiler.transformRef(code, { filename, sourceMap: true }) diff --git a/packages/plugin-vue/src/main.ts b/packages/plugin-vue/src/main.ts index 9a6e6431..8e4a2af6 100644 --- a/packages/plugin-vue/src/main.ts +++ b/packages/plugin-vue/src/main.ts @@ -1,6 +1,7 @@ import qs from 'querystring' import path from 'path' -import { rewriteDefault, SFCBlock, SFCDescriptor } from '@vue/compiler-sfc' +import { SFCBlock, SFCDescriptor } from '@vue/compiler-sfc' +import { compiler } from './compiler' import { ResolvedOptions } from '.' import { createDescriptor, @@ -271,7 +272,7 @@ async function genScriptCode( // If the script is js/ts and has no external src, it can be directly placed // in the main module. if ((!script.lang || script.lang === 'ts') && !script.src) { - scriptCode = rewriteDefault(script.content, '_sfc_main') + scriptCode = compiler.rewriteDefault(script.content, '_sfc_main') map = script.map } else { if (script.src) { diff --git a/packages/plugin-vue/src/script.ts b/packages/plugin-vue/src/script.ts index cba63b5c..f851327f 100644 --- a/packages/plugin-vue/src/script.ts +++ b/packages/plugin-vue/src/script.ts @@ -1,6 +1,7 @@ -import { compileScript, SFCDescriptor, SFCScriptBlock } from '@vue/compiler-sfc' +import { SFCDescriptor, SFCScriptBlock } from '@vue/compiler-sfc' import { ResolvedOptions } from '.' import { resolveTemplateCompilerOptions } from './template' +import { compiler } from './compiler' // ssr and non ssr builds would output different script content const clientCache = new WeakMap() @@ -38,7 +39,7 @@ export function resolveScript( let resolved: SFCScriptBlock | null = null - resolved = compileScript(descriptor, { + resolved = compiler.compileScript(descriptor, { ...options.script, id: descriptor.id, isProd: options.isProduction, diff --git a/packages/plugin-vue/src/style.ts b/packages/plugin-vue/src/style.ts index 961c9b38..fd71cd9d 100644 --- a/packages/plugin-vue/src/style.ts +++ b/packages/plugin-vue/src/style.ts @@ -1,6 +1,7 @@ -import { compileStyleAsync, SFCDescriptor } from '@vue/compiler-sfc' +import { SFCDescriptor } from '@vue/compiler-sfc' import { TransformPluginContext } from 'rollup' import { ResolvedOptions } from '.' +import { compiler } from './compiler' // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function transformStyle( @@ -13,7 +14,7 @@ export async function transformStyle( const block = descriptor.styles[index] // vite already handles pre-processors and CSS module so this is only // applying SFC-specific transforms like scoped mode and CSS vars rewrite (v-bind(var)) - const result = await compileStyleAsync({ + const result = await compiler.compileStyleAsync({ ...options.style, filename: descriptor.filename, id: `data-v-${descriptor.id}`, diff --git a/packages/plugin-vue/src/template.ts b/packages/plugin-vue/src/template.ts index b3a8e1e5..a29874d0 100644 --- a/packages/plugin-vue/src/template.ts +++ b/packages/plugin-vue/src/template.ts @@ -1,16 +1,16 @@ import path from 'path' import slash from 'slash' import { - compileTemplate, SFCDescriptor, SFCTemplateCompileOptions, SFCTemplateCompileResults, CompilerOptions -} from '@vue/compiler-sfc' +} from 'vue/compiler-sfc' import { PluginContext, TransformPluginContext } from 'rollup' import { ResolvedOptions } from '.' import { getResolvedScript } from './script' import { createRollupError } from './utils/error' +import { compiler } from './compiler' // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function transformTemplateAsModule( @@ -70,7 +70,7 @@ export function compile( ssr: boolean ) { const filename = descriptor.filename - const result = compileTemplate({ + const result = compiler.compileTemplate({ ...resolveTemplateCompilerOptions(descriptor, options, ssr)!, source: code }) diff --git a/packages/plugin-vue/src/utils/descriptorCache.ts b/packages/plugin-vue/src/utils/descriptorCache.ts index c0e860d8..dde91e21 100644 --- a/packages/plugin-vue/src/utils/descriptorCache.ts +++ b/packages/plugin-vue/src/utils/descriptorCache.ts @@ -2,8 +2,9 @@ import fs from 'fs' import path from 'path' import slash from 'slash' import hash from 'hash-sum' -import { CompilerError, parse, SFCDescriptor } from '@vue/compiler-sfc' +import { CompilerError, SFCDescriptor } from '@vue/compiler-sfc' import { ResolvedOptions } from '..' +import { compiler } from '../compiler' // node_modules/@vue/compiler-sfc/dist/compiler-sfc.d.ts SFCParseResult should be exported so it can be re-used export interface SFCParseResult { @@ -19,7 +20,7 @@ export function createDescriptor( source: string, { root, isProduction, sourceMap }: ResolvedOptions ): SFCParseResult { - const { descriptor, errors } = parse(source, { + const { descriptor, errors } = compiler.parse(source, { filename, sourceMap })