wip: more consistent compiler-sfc usage + inline mode for ssr

This commit is contained in:
Evan You
2020-11-20 14:22:51 -05:00
parent 58227e88e9
commit 8ac2241b22
18 changed files with 213 additions and 93 deletions

View File

@@ -201,6 +201,40 @@ return (_ctx, _cache) => {
}"
`;
exports[`SFC compile <script setup> inlineTemplate mode ssr codegen 1`] = `
"import { useCssVars as _useCssVars, unref as _unref } from 'vue'
import { ssrRenderAttrs as _ssrRenderAttrs, ssrInterpolate as _ssrInterpolate } from \\"@vue/server-renderer\\"
import { ref } from 'vue'
export default {
expose: [],
__ssrInlineRender: true,
setup(__props) {
_useCssVars(_ctx => ({
\\"xxxxxxxx-count\\": (count.value)
}))
const count = ref(0)
return (_ctx, _push, _parent, _attrs) => {
const _cssVars = { style: {
\\"xxxxxxxx-count\\": (count.value)
}}
_push(\`<!--[--><div\${
_ssrRenderAttrs(_cssVars)
}>\${
_ssrInterpolate(count.value)
}</div><div\${
_ssrRenderAttrs(_cssVars)
}>static</div><!--]-->\`)
}
}
}"
`;
exports[`SFC compile <script setup> inlineTemplate mode template assignment expression codegen 1`] = `
"import { createVNode as _createVNode, isRef as _isRef, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"

View File

@@ -1,4 +1,4 @@
import { BindingTypes } from '@vue/compiler-dom/src'
import { BindingTypes } from '@vue/compiler-dom'
import { compileSFCScript as compile, assertCode } from './utils'
describe('SFC compile <script setup>', () => {
@@ -297,6 +297,34 @@ const bar = 1
expect(content).toMatch(`{ lett: lett } = val`)
assertCode(content)
})
test('ssr codegen', () => {
const { content } = compile(
`
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<div>{{ count }}</div>
<div>static</div>
</template>
<style>
div { color: v-bind(count) }
</style>
`,
{
inlineTemplate: true,
templateOptions: {
ssr: true
}
}
)
expect(content).toMatch(`\n __ssrInlineRender: true,\n`)
expect(content).toMatch(`return (_ctx, _push`)
expect(content).toMatch(`ssrInterpolate`)
assertCode(content)
})
})
describe('with TypeScript', () => {

View File

@@ -16,7 +16,7 @@ export function compileScoped(
const res = compileStyle({
source,
filename: 'test.css',
id: 'test',
id: 'data-v-test',
scoped: true,
...options
})
@@ -32,61 +32,61 @@ export function compileScoped(
describe('SFC scoped CSS', () => {
test('simple selectors', () => {
expect(compileScoped(`h1 { color: red; }`)).toMatch(
`h1[test] { color: red;`
`h1[data-v-test] { color: red;`
)
expect(compileScoped(`.foo { color: red; }`)).toMatch(
`.foo[test] { color: red;`
`.foo[data-v-test] { color: red;`
)
})
test('descendent selector', () => {
expect(compileScoped(`h1 .foo { color: red; }`)).toMatch(
`h1 .foo[test] { color: red;`
`h1 .foo[data-v-test] { color: red;`
)
})
test('multiple selectors', () => {
expect(compileScoped(`h1 .foo, .bar, .baz { color: red; }`)).toMatch(
`h1 .foo[test], .bar[test], .baz[test] { color: red;`
`h1 .foo[data-v-test], .bar[data-v-test], .baz[data-v-test] { color: red;`
)
})
test('pseudo class', () => {
expect(compileScoped(`.foo:after { color: red; }`)).toMatch(
`.foo[test]:after { color: red;`
`.foo[data-v-test]:after { color: red;`
)
})
test('pseudo element', () => {
expect(compileScoped(`::selection { display: none; }`)).toMatch(
'[test]::selection {'
'[data-v-test]::selection {'
)
})
test('spaces before pseudo element', () => {
const code = compileScoped(`.abc, ::selection { color: red; }`)
expect(code).toMatch('.abc[test],')
expect(code).toMatch('[test]::selection {')
expect(code).toMatch('.abc[data-v-test],')
expect(code).toMatch('[data-v-test]::selection {')
})
test('::v-deep', () => {
expect(compileScoped(`:deep(.foo) { color: red; }`)).toMatchInlineSnapshot(`
"[test] .foo { color: red;
"[data-v-test] .foo { color: red;
}"
`)
expect(compileScoped(`::v-deep(.foo) { color: red; }`))
.toMatchInlineSnapshot(`
"[test] .foo { color: red;
"[data-v-test] .foo { color: red;
}"
`)
expect(compileScoped(`::v-deep(.foo .bar) { color: red; }`))
.toMatchInlineSnapshot(`
"[test] .foo .bar { color: red;
"[data-v-test] .foo .bar { color: red;
}"
`)
expect(compileScoped(`.baz .qux ::v-deep(.foo .bar) { color: red; }`))
.toMatchInlineSnapshot(`
".baz .qux[test] .foo .bar { color: red;
".baz .qux[data-v-test] .foo .bar { color: red;
}"
`)
})
@@ -94,22 +94,22 @@ describe('SFC scoped CSS', () => {
test('::v-slotted', () => {
expect(compileScoped(`:slotted(.foo) { color: red; }`))
.toMatchInlineSnapshot(`
".foo[test-s] { color: red;
".foo[data-v-test-s] { color: red;
}"
`)
expect(compileScoped(`::v-slotted(.foo) { color: red; }`))
.toMatchInlineSnapshot(`
".foo[test-s] { color: red;
".foo[data-v-test-s] { color: red;
}"
`)
expect(compileScoped(`::v-slotted(.foo .bar) { color: red; }`))
.toMatchInlineSnapshot(`
".foo .bar[test-s] { color: red;
".foo .bar[data-v-test-s] { color: red;
}"
`)
expect(compileScoped(`.baz .qux ::v-slotted(.foo .bar) { color: red; }`))
.toMatchInlineSnapshot(`
".baz .qux .foo .bar[test-s] { color: red;
".baz .qux .foo .bar[data-v-test-s] { color: red;
}"
`)
})
@@ -142,7 +142,7 @@ describe('SFC scoped CSS', () => {
expect(compileScoped(`@media print { .foo { color: red }}`))
.toMatchInlineSnapshot(`
"@media print {
.foo[test] { color: red
.foo[data-v-test] { color: red
}}"
`)
})
@@ -151,7 +151,7 @@ describe('SFC scoped CSS', () => {
expect(compileScoped(`@supports(display: grid) { .foo { display: grid }}`))
.toMatchInlineSnapshot(`
"@supports(display: grid) {
.foo[test] { display: grid
.foo[data-v-test] { display: grid
}}"
`)
})
@@ -222,7 +222,7 @@ describe('SFC scoped CSS', () => {
// vue-loader/#1370
test('spaces after selector', () => {
expect(compileScoped(`.foo , .bar { color: red; }`)).toMatchInlineSnapshot(`
".foo[test], .bar[test] { color: red;
".foo[data-v-test], .bar[data-v-test] { color: red;
}"
`)
})
@@ -231,12 +231,12 @@ describe('SFC scoped CSS', () => {
test('::v-deep as combinator', () => {
expect(compileScoped(`::v-deep .foo { color: red; }`))
.toMatchInlineSnapshot(`
"[test] .foo { color: red;
"[data-v-test] .foo { color: red;
}"
`)
expect(compileScoped(`.bar ::v-deep .foo { color: red; }`))
.toMatchInlineSnapshot(`
".bar[test] .foo { color: red;
".bar[data-v-test] .foo { color: red;
}"
`)
expect(
@@ -247,7 +247,7 @@ describe('SFC scoped CSS', () => {
test('>>> (deprecated syntax)', () => {
const code = compileScoped(`>>> .foo { color: red; }`)
expect(code).toMatchInlineSnapshot(`
"[test] .foo { color: red;
"[data-v-test] .foo { color: red;
}"
`)
expect(
@@ -258,7 +258,7 @@ describe('SFC scoped CSS', () => {
test('/deep/ (deprecated syntax)', () => {
const code = compileScoped(`/deep/ .foo { color: red; }`)
expect(code).toMatchInlineSnapshot(`
"[test] .foo { color: red;
"[data-v-test] .foo { color: red;
}"
`)
expect(

View File

@@ -1,10 +1,20 @@
import { compileTemplate } from '../src/compileTemplate'
import {
compileTemplate,
SFCTemplateCompileOptions
} from '../src/compileTemplate'
import { parse, SFCTemplateBlock } from '../src/parse'
function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
return compileTemplate({
...opts,
id: ''
})
}
test('should work', () => {
const source = `<div><p>{{ render }}</p></div>`
const result = compileTemplate({ filename: 'example.vue', source })
const result = compile({ filename: 'example.vue', source })
expect(result.errors.length).toBe(0)
expect(result.source).toBe(source)
@@ -25,7 +35,7 @@ body
{ filename: 'example.vue', sourceMap: true }
).descriptor.template as SFCTemplateBlock
const result = compileTemplate({
const result = compile({
filename: 'example.vue',
source: template.content,
preprocessLang: template.lang
@@ -40,7 +50,7 @@ test('warn missing preprocessor', () => {
sourceMap: true
}).descriptor.template as SFCTemplateBlock
const result = compileTemplate({
const result = compile({
filename: 'example.vue',
source: template.content,
preprocessLang: template.lang
@@ -52,7 +62,7 @@ test('warn missing preprocessor', () => {
test('transform asset url options', () => {
const input = { source: `<foo bar="~baz"/>`, filename: 'example.vue' }
// Object option
const { code: code1 } = compileTemplate({
const { code: code1 } = compile({
...input,
transformAssetUrls: {
tags: { foo: ['bar'] }
@@ -61,7 +71,7 @@ test('transform asset url options', () => {
expect(code1).toMatch(`import _imports_0 from 'baz'\n`)
// legacy object option (direct tags config)
const { code: code2 } = compileTemplate({
const { code: code2 } = compile({
...input,
transformAssetUrls: {
foo: ['bar']
@@ -70,7 +80,7 @@ test('transform asset url options', () => {
expect(code2).toMatch(`import _imports_0 from 'baz'\n`)
// false option
const { code: code3 } = compileTemplate({
const { code: code3 } = compile({
...input,
transformAssetUrls: false
})
@@ -87,7 +97,7 @@ test('source map', () => {
{ filename: 'example.vue', sourceMap: true }
).descriptor.template as SFCTemplateBlock
const result = compileTemplate({
const result = compile({
filename: 'example.vue',
source: template.content
})
@@ -96,7 +106,7 @@ test('source map', () => {
})
test('template errors', () => {
const result = compileTemplate({
const result = compile({
filename: 'example.vue',
source: `<div :foo
:bar="a[" v-model="baz"/>`
@@ -114,7 +124,7 @@ test('preprocessor errors', () => {
{ filename: 'example.vue', sourceMap: true }
).descriptor.template as SFCTemplateBlock
const result = compileTemplate({
const result = compile({
filename: 'example.vue',
source: template.content,
preprocessLang: template.lang