Skip to content

Commit

Permalink
feat: support for experimental sfc features
Browse files Browse the repository at this point in the history
- new `<script setup>` vuejs/rfcs#227
- new `<style>` variable injection vuejs/rfcs#231

Requires a version of `@vue/compiler-sfc` that supports the above features.

Also should fix #1723
  • Loading branch information
yyx990803 committed Nov 21, 2020
1 parent fd33cad commit b85244b
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 23 deletions.
4 changes: 2 additions & 2 deletions example/ScriptSetup.vue
Expand Up @@ -17,9 +17,9 @@ function inc() {
count.value++
}
const hello = 'hi from script'
const hello = 'hi from scriptttt'
const color = ref('cyan')
const color = ref('red')
const changeColor = () => {
color.value = color.value === 'red' ? 'green' : 'red'
}
Expand Down
6 changes: 2 additions & 4 deletions src/index.ts
Expand Up @@ -29,7 +29,7 @@ import { genCSSModulesCode } from './cssModules'
import { formatError } from './formatError'

import VueLoaderPlugin from './plugin'
import { resolveScript } from './resolveScript'
import { canInlineTemplate, resolveScript } from './resolveScript'
import { setDescriptor } from './descriptorCache'

export { VueLoaderPlugin }
Expand Down Expand Up @@ -155,9 +155,7 @@ export default function loader(
let templateImport = ``
let templateRequest
const renderFnName = isServer ? `ssrRender` : `render`
const templateLang = descriptor.template && descriptor.template.lang
const useInlineTemplate =
descriptor.scriptSetup && isProduction && !isServer && !templateLang
const useInlineTemplate = canInlineTemplate(descriptor, isProduction)
if (descriptor.template && !useInlineTemplate) {
const src = descriptor.template.src || resourcePath
const idQuery = `&id=${id}`
Expand Down
28 changes: 19 additions & 9 deletions src/resolveScript.ts
Expand Up @@ -7,10 +7,20 @@ import {
} from '@vue/compiler-sfc'
import { VueLoaderOptions } from 'src'

// since we generate different output based on whether the template is inlined
// or not, we need to cache the results separately
const inlinedCache = new WeakMap<SFCDescriptor, SFCScriptBlock | null>()
const normalCache = new WeakMap<SFCDescriptor, SFCScriptBlock | null>()
const clientCache = new WeakMap<SFCDescriptor, SFCScriptBlock | null>()
const serverCache = new WeakMap<SFCDescriptor, SFCScriptBlock | null>()

/**
* inline template mode can only be enabled if:
* - is production (separate compilation needed for HMR during dev)
* - template has no pre-processor (separate loader chain required)
* - template is not using src
*/
export function canInlineTemplate(descriptor: SFCDescriptor, isProd: boolean) {
const templateLang = descriptor.template && descriptor.template.lang
const templateSrc = descriptor.template && descriptor.template.src
return isProd && !!descriptor.scriptSetup && !templateLang && !templateSrc
}

export function resolveScript(
descriptor: SFCDescriptor,
Expand All @@ -24,10 +34,9 @@ export function resolveScript(

const isProd = loaderContext.mode === 'production'
const isServer = loaderContext.target === 'node'
const templateLang = descriptor.template && descriptor.template.lang
const enableInline = isProd && !isServer && !templateLang
const enableInline = canInlineTemplate(descriptor, isProd)

const cacheToUse = enableInline ? inlinedCache : normalCache
const cacheToUse = isServer ? serverCache : clientCache
const cached = cacheToUse.get(descriptor)
if (cached) {
return cached
Expand All @@ -45,13 +54,14 @@ export function resolveScript(
if (compileScript) {
try {
resolved = compileScript(descriptor, {
// @ts-ignore TODO remove when vue is upgraded
scopeId,
// @ts-ignore
id: scopeId,
isProd,
inlineTemplate: enableInline,
babelParserPlugins: options.babelParserPlugins,
templateOptions: {
compiler,
ssr: isServer,
transformAssetUrls: options.transformAssetUrls || true,
},
})
Expand Down
16 changes: 8 additions & 8 deletions src/templateLoader.ts
Expand Up @@ -3,11 +3,7 @@ import * as qs from 'querystring'
import * as loaderUtils from 'loader-utils'
import { VueLoaderOptions } from './'
import { formatError } from './formatError'
import {
compileTemplate,
generateCssVars,
TemplateCompiler,
} from '@vue/compiler-sfc'
import { compileTemplate, TemplateCompiler } from '@vue/compiler-sfc'
import { getDescriptor } from './descriptorCache'
import { resolveScript } from './resolveScript'

Expand All @@ -25,7 +21,7 @@ const TemplateLoader: webpack.loader.Loader = function (source, inMap) {
{}) as VueLoaderOptions

const isServer = loaderContext.target === 'node'
const isProduction = loaderContext.mode === 'production'
const isProd = loaderContext.mode === 'production'
const query = qs.parse(loaderContext.resourceQuery.slice(1))
const scopeId = query.id as string
const descriptor = getDescriptor(loaderContext.resourcePath)
Expand All @@ -45,13 +41,17 @@ const TemplateLoader: webpack.loader.Loader = function (source, inMap) {

const compiled = compileTemplate({
source,
inMap,
filename: loaderContext.resourcePath,
inMap,
// @ts-ignore
id: scopeId,
isProd,
ssr: isServer,
// @ts-ignore
ssrCssVars: descriptor.cssVars,
compiler,
compilerOptions: {
...options.compilerOptions,
ssrCssVars: generateCssVars(descriptor, scopeId, isProduction),
scopeId: query.scoped ? `data-v-${scopeId}` : undefined,
bindingMetadata: script ? script.bindings : undefined,
},
Expand Down

0 comments on commit b85244b

Please sign in to comment.