})"
`;
+
+exports[`SFC genDefaultAs > <script setup> only 1`] = `
+"const a = 1
+
+const _sfc_ = {
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+
+return { a }
+}
+
+}"
+`;
+
+exports[`SFC genDefaultAs > <script setup> only w/ ts 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+const a = 1
+
+const _sfc_ = /*#__PURE__*/_defineComponent({
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+
+return { a }
+}
+
+})"
+`;
+
+exports[`SFC genDefaultAs > <script> + <script setup> 1`] = `
+"const __default__ = {}
+
+const _sfc_ = /*#__PURE__*/Object.assign(__default__, {
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+ const a = 1
+
+return { a }
+}
+
+})"
+`;
+
+exports[`SFC genDefaultAs > <script> + <script setup> 2`] = `
+"const __default__ = {}
+
+const _sfc_ = /*#__PURE__*/Object.assign(__default__, {
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+ const a = 1
+
+return { a }
+}
+
+})"
+`;
+
+exports[`SFC genDefaultAs > <script> + <script setup> w/ ts 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+ const __default__ = {}
+
+const _sfc_ = /*#__PURE__*/_defineComponent({
+ ...__default__,
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+ const a = 1
+
+return { a }
+}
+
+})"
+`;
+
+exports[`SFC genDefaultAs > normal <script> only 1`] = `
+"
+ const _sfc_ = {}
+ "
+`;
+
+exports[`SFC genDefaultAs > normal <script> w/ cssVars 1`] = `
+"
+ const _sfc_ = {}
+
+import { useCssVars as _useCssVars } from 'vue'
+const __injectCSSVars__ = () => {
+_useCssVars(_ctx => ({
+ \\"xxxxxxxx-x\\": (_ctx.x)
+}))}
+const __setup__ = _sfc_.setup
+_sfc_.setup = __setup__
+ ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
+ : __injectCSSVars__
+"
+`;
})
})
})
+
+describe('SFC genDefaultAs', () => {
+ test('normal <script> only', () => {
+ const { content } = compile(
+ `<script>
+ export default {}
+ </script>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).toMatch(`const _sfc_ = {}`)
+ assertCode(content)
+ })
+
+ test('normal <script> w/ cssVars', () => {
+ const { content } = compile(
+ `<script>
+ export default {}
+ </script>
+ <style>
+ .foo { color: v-bind(x) }
+ </style>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).not.toMatch('__default__')
+ expect(content).toMatch(`const _sfc_ = {}`)
+ assertCode(content)
+ })
+
+ test('<script> + <script setup>', () => {
+ const { content } = compile(
+ `<script>
+ export default {}
+ </script>
+ <script setup>
+ const a = 1
+ </script>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).toMatch(
+ `const _sfc_ = /*#__PURE__*/Object.assign(__default__`
+ )
+ assertCode(content)
+ })
+
+ test('<script> + <script setup>', () => {
+ const { content } = compile(
+ `<script>
+ export default {}
+ </script>
+ <script setup>
+ const a = 1
+ </script>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).toMatch(
+ `const _sfc_ = /*#__PURE__*/Object.assign(__default__`
+ )
+ assertCode(content)
+ })
+
+ test('<script setup> only', () => {
+ const { content } = compile(
+ `<script setup>
+ const a = 1
+ </script>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).toMatch(`const _sfc_ = {\n setup`)
+ assertCode(content)
+ })
+
+ test('<script setup> only w/ ts', () => {
+ const { content } = compile(
+ `<script setup lang="ts">
+ const a = 1
+ </script>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).toMatch(`const _sfc_ = /*#__PURE__*/_defineComponent(`)
+ assertCode(content)
+ })
+
+ test('<script> + <script setup> w/ ts', () => {
+ const { content } = compile(
+ `<script lang="ts">
+ export default {}
+ </script>
+ <script setup lang="ts">
+ const a = 1
+ </script>`,
+ {
+ genDefaultAs: '_sfc_'
+ }
+ )
+ expect(content).not.toMatch('export default')
+ expect(content).toMatch(
+ `const _sfc_ = /*#__PURE__*/_defineComponent({\n ...__default__`
+ )
+ assertCode(content)
+ })
+})
const WITH_DEFAULTS = 'withDefaults'
const DEFINE_OPTIONS = 'defineOptions'
-// constants
-const DEFAULT_VAR = `__default__`
-
const isBuiltInDir = makeMap(
`once,memo,if,for,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
)
* from being hot-reloaded separately from component state.
*/
inlineTemplate?: boolean
+ /**
+ * Generate the final component as a variable instead of default export.
+ * This is useful in e.g. @vitejs/plugin-vue where the script needs to be
+ * placed inside the main module.
+ */
+ genDefaultAs?: string
/**
* Options for template compilation when inlining. Note these are options that
* would normally be passed to `compiler-sfc`'s own `compileTemplate()`, not
const cssVars = sfc.cssVars
const scriptLang = script && script.lang
const scriptSetupLang = scriptSetup && scriptSetup.lang
+ const genDefaultAs = options.genDefaultAs
+ ? `const ${options.genDefaultAs} =`
+ : `export default`
+ const normalScriptDefaultVar = `__default__`
const isJS =
scriptLang === 'js' ||
scriptLang === 'jsx' ||
// do not process non js/ts script blocks
return script
}
+ // normal <script> only
try {
let content = script.content
let map = script.map
}) as unknown as RawSourceMap
}
}
- if (cssVars.length) {
+ if (cssVars.length || options.genDefaultAs) {
+ const defaultVar = options.genDefaultAs || normalScriptDefaultVar
const s = new MagicString(content)
- rewriteDefaultAST(scriptAst.body, s, DEFAULT_VAR)
+ rewriteDefaultAST(scriptAst.body, s, defaultVar)
content = s.toString()
- content += genNormalScriptCssVarsCode(
- cssVars,
- bindings,
- scopeId,
- isProd
- )
- content += `\nexport default ${DEFAULT_VAR}`
+ if (cssVars.length) {
+ content += genNormalScriptCssVarsCode(
+ cssVars,
+ bindings,
+ scopeId,
+ isProd,
+ defaultVar
+ )
+ }
+ if (!options.genDefaultAs) {
+ content += `\nexport default ${defaultVar}`
+ }
}
return {
...script,
// export default { ... } --> const __default__ = { ... }
const start = node.start! + scriptStartOffset!
const end = node.declaration.start! + scriptStartOffset!
- s.overwrite(start, end, `const ${DEFAULT_VAR} = `)
+ s.overwrite(start, end, `const ${normalScriptDefaultVar} = `)
} else if (node.type === 'ExportNamedDeclaration') {
const defaultSpecifier = node.specifiers.find(
s => s.exported.type === 'Identifier' && s.exported.name === 'default'
// rewrite to `import { x as __default__ } from './x'` and
// add to top
s.prepend(
- `import { ${defaultSpecifier.local.name} as ${DEFAULT_VAR} } from '${node.source.value}'\n`
+ `import { ${defaultSpecifier.local.name} as ${normalScriptDefaultVar} } from '${node.source.value}'\n`
)
} else {
// export { x as default }
// rewrite to `const __default__ = x` and move to end
s.appendLeft(
scriptEndOffset!,
- `\nconst ${DEFAULT_VAR} = ${defaultSpecifier.local.name}\n`
+ `\nconst ${normalScriptDefaultVar} = ${defaultSpecifier.local.name}\n`
)
}
}
// user's TS setting should compile it down to proper targets
// export default defineComponent({ ...__default__, ... })
const def =
- (defaultExport ? `\n ...${DEFAULT_VAR},` : ``) +
+ (defaultExport ? `\n ...${normalScriptDefaultVar},` : ``) +
(definedOptions ? `\n ...${definedOptions},` : '')
s.prependLeft(
startOffset,
- `\nexport default /*#__PURE__*/${helper(
+ `\n${genDefaultAs} /*#__PURE__*/${helper(
`defineComponent`
)}({${def}${runtimeOptions}\n ${
hasAwait ? `async ` : ``
// export default Object.assign(__default__, { ... })
s.prependLeft(
startOffset,
- `\nexport default /*#__PURE__*/Object.assign(${
- defaultExport ? `${DEFAULT_VAR}, ` : ''
+ `\n${genDefaultAs} /*#__PURE__*/Object.assign(${
+ defaultExport ? `${normalScriptDefaultVar}, ` : ''
}${definedOptions ? `${definedOptions}, ` : ''}{${runtimeOptions}\n ` +
`${hasAwait ? `async ` : ``}setup(${args}) {\n${exposeCall}`
)
} else {
s.prependLeft(
startOffset,
- `\nexport default {${runtimeOptions}\n ` +
+ `\n${genDefaultAs} {${runtimeOptions}\n ` +
`${hasAwait ? `async ` : ``}setup(${args}) {\n${exposeCall}`
)
s.appendRight(endOffset, `}`)
return {
...scriptSetup,
- s,
bindings: bindingMetadata,
imports: userImports,
content: s.toString(),