Skip to content

Commit fb09c8b

Browse files
committed
feat: support <script setup>
1 parent eec3c80 commit fb09c8b

11 files changed

+144
-74
lines changed

example/App.vue

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
<div>
44
{{ count }}
55
<span>{{ count }}</span>
6-
<Button><span>slot</span></Button>
6+
<Button foo="hello!"><span>slot</span></Button>
7+
<ScriptSetup/>
78
</div>
89
</template>
910

1011
<script>
1112
import Button from './Button.vue'
13+
import ScriptSetup from './ScriptSetup.vue'
1214
1315
export default {
1416
data() {
1517
return { count: 0 }
1618
},
1719
components: {
18-
Button
20+
Button,
21+
ScriptSetup
1922
}
2023
}
2124
</script>

example/Button.vue

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<template>
2+
<p>prop foo: {{ foo }}</p>
23
<button @click="inc">{{ count }}</button>
34
<slot/>
45
</template>
@@ -7,7 +8,10 @@
78
import { ref } from 'vue'
89
910
export default {
10-
setup() {
11+
props: {
12+
foo: String
13+
},
14+
setup(props) {
1115
const count = ref(0)
1216
return {
1317
count,

example/ScriptSetup.vue

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<h2>{{ hello }}</h2>
3+
<div>
4+
{{ count }} <button @click="inc">+</button>
5+
<Button/>
6+
</div>
7+
</template>
8+
9+
<script setup>
10+
import { ref } from 'vue'
11+
export { default as Button } from './Button.vue'
12+
13+
export const count = ref(0)
14+
15+
export function inc() {
16+
count.value++
17+
}
18+
19+
export const hello = 'hi from script setup'
20+
</script>

example/webpack.config.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
const fs = require('fs')
22
const path = require('path')
3+
const webpack = require('webpack')
34
const hash = require('hash-sum')
4-
const VueLoaderPlugin = require('../dist/plugin')
5+
const VueLoaderPlugin = require('../dist/plugin').default
56
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
67

78
module.exports = (env = {}) => {
@@ -86,6 +87,10 @@ module.exports = (env = {}) => {
8687
new VueLoaderPlugin(),
8788
new MiniCssExtractPlugin({
8889
filename: '[name].css'
90+
}),
91+
new webpack.DefinePlugin({
92+
__VUE_OPTIONS_API__: true,
93+
__VUE_PROD_DEVTOOLS__: false
8994
})
9095
],
9196
optimization: {

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
"@types/loader-utils": "^1.1.3",
4949
"@types/webpack": "^4.41.0",
5050
"@types/webpack-merge": "^4.1.5",
51-
"@vue/compiler-sfc": "^3.0.0-rc.6",
51+
"@vue/compiler-sfc": "^3.0.0-rc.10",
5252
"babel-loader": "^8.0.6",
5353
"cache-loader": "^4.1.0",
5454
"css-loader": "^3.3.2",
@@ -65,7 +65,7 @@
6565
"ts-jest": "^26.2.0",
6666
"typescript": "^4.0.2",
6767
"url-loader": "^3.0.0",
68-
"vue": "^3.0.0-rc.6",
68+
"vue": "^3.0.0-rc.10",
6969
"webpack": "^4.41.2",
7070
"webpack-cli": "^3.3.10",
7171
"webpack-dev-server": "^3.9.0",

src/index.ts

+33-13
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ import hash from 'hash-sum'
1414
import loaderUtils from 'loader-utils'
1515
import {
1616
parse,
17+
compileScript,
1718
TemplateCompiler,
1819
CompilerOptions,
1920
SFCBlock,
2021
SFCTemplateCompileOptions,
21-
SFCStyleBlock
22+
SFCScriptCompileOptions,
23+
SFCStyleBlock,
24+
SFCScriptBlock
2225
} from '@vue/compiler-sfc'
2326
import { selectBlock } from './select'
2427
import { genHotReloadCode } from './hotReload'
@@ -30,6 +33,8 @@ import VueLoaderPlugin from './plugin'
3033
export { VueLoaderPlugin }
3134

3235
export interface VueLoaderOptions {
36+
// https://babeljs.io/docs/en/next/babel-parser#plugins
37+
babelParserPlugins?: SFCScriptCompileOptions['babelParserPlugins']
3338
transformAssetUrls?: SFCTemplateCompileOptions['transformAssetUrls']
3439
compiler?: TemplateCompiler | string
3540
compilerOptions?: CompilerOptions
@@ -121,6 +126,29 @@ export default function loader(
121126
!!(descriptor.script || descriptor.template) &&
122127
options.hotReload !== false
123128

129+
// script
130+
let script: SFCScriptBlock | undefined
131+
let scriptImport = `const script = {}`
132+
if (descriptor.script || descriptor.scriptSetup) {
133+
try {
134+
script = (descriptor as any).scriptCompiled = compileScript(descriptor, {
135+
babelParserPlugins: options.babelParserPlugins
136+
})
137+
} catch (e) {
138+
loaderContext.emitError(e)
139+
}
140+
if (script) {
141+
const src = script.src || resourcePath
142+
const attrsQuery = attrsToQuery(script.attrs, 'js')
143+
const query = `?vue&type=script${attrsQuery}${resourceQuery}`
144+
const scriptRequest = stringifyRequest(src + query)
145+
scriptImport =
146+
`import script from ${scriptRequest}\n` +
147+
// support named exports
148+
`export * from ${scriptRequest}`
149+
}
150+
}
151+
124152
// template
125153
let templateImport = ``
126154
let templateRequest
@@ -129,22 +157,14 @@ export default function loader(
129157
const idQuery = `&id=${id}`
130158
const scopedQuery = hasScoped ? `&scoped=true` : ``
131159
const attrsQuery = attrsToQuery(descriptor.template.attrs)
132-
const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${resourceQuery}`
160+
const bindingsQuery = script
161+
? `&bindings=${JSON.stringify(script.bindings)}`
162+
: ``
163+
const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${bindingsQuery}${resourceQuery}`
133164
templateRequest = stringifyRequest(src + query)
134165
templateImport = `import { render } from ${templateRequest}`
135166
}
136167

137-
// script
138-
let scriptImport = `const script = {}`
139-
if (descriptor.script) {
140-
const src = descriptor.script.src || resourcePath
141-
const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js')
142-
const query = `?vue&type=script${attrsQuery}${resourceQuery}`
143-
const scriptRequest = stringifyRequest(src + query)
144-
scriptImport =
145-
`import script from ${scriptRequest}\n` + `export * from ${scriptRequest}` // support named exports
146-
}
147-
148168
// styles
149169
let stylesCode = ``
150170
let hasCSSModules = false

src/select.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function selectBlock(
2222

2323
// script
2424
if (query.type === `script`) {
25-
const script = descriptor.script!
25+
const script = (descriptor as any).scriptCompiled
2626
if (appendExtension) {
2727
loaderContext.resourcePath += '.' + (script.lang || 'js')
2828
}

src/templateLoader.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ const TemplateLoader: webpack.loader.Loader = function(source, inMap) {
3737
compiler,
3838
compilerOptions: {
3939
...options.compilerOptions,
40-
scopeId
40+
scopeId,
41+
bindingMetadata: JSON.parse(query.bindings as string)
4142
},
4243
transformAssetUrls: options.transformAssetUrls || true
4344
})

test/core.spec.ts

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ import { bundle } from './utils'
33
test('basic', async () => {
44
await bundle({ entry: 'basic.vue' })
55
})
6+
7+
test('script setup', async () => {
8+
await bundle({ entry: 'ScriptSetup.vue' })
9+
})

test/fixtures/ScriptSetup.vue

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<template>
2+
<button @click="inc">{{ count }}</button>
3+
</template>
4+
5+
<script setup>
6+
import { ref } from 'vue'
7+
8+
export const count = ref(0)
9+
10+
export function inc() {
11+
count.value++
12+
}
13+
</script>

yarn.lock

+53-53
Original file line numberDiff line numberDiff line change
@@ -1419,36 +1419,36 @@
14191419
dependencies:
14201420
"@types/yargs-parser" "*"
14211421

1422-
1423-
version "3.0.0-rc.6"
1424-
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.0-rc.6.tgz#d5bae6ba028068aa54706a5c9c1e8e34a296b4ce"
1425-
integrity sha512-ZECV6eMIO+cY1aMQoPMZvkS1Bjv5tfeYrcd/qE4YdsjMUtId6N9EO3xob9FUo4fL4SZt2woHmGkc8x4nKu9+NQ==
1422+
1423+
version "3.0.0-rc.10"
1424+
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.0-rc.10.tgz#a76f713fb0462429ec0ec10a472fff1f539c5772"
1425+
integrity sha512-kQzHzRsM0NPAWHeqSTb2J4VsHhjRkGeLTsGzeMnW+sojgTnS3T94KacwvYgVS4qeZAKiDq0bMNZoJWrHVQ3T8g==
14261426
dependencies:
14271427
"@babel/parser" "^7.10.4"
14281428
"@babel/types" "^7.10.4"
1429-
"@vue/shared" "3.0.0-rc.6"
1429+
"@vue/shared" "3.0.0-rc.10"
14301430
estree-walker "^2.0.1"
14311431
source-map "^0.6.1"
14321432

1433-
1434-
version "3.0.0-rc.6"
1435-
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.0-rc.6.tgz#6d7adec707834ab75b2ab89d53f484e74eec7253"
1436-
integrity sha512-ZlBvrH5FUPtMLKHib1yR0eLvVbjMarz/fWRD3MtDJiCpH5TTHo5I24HLaMhbjSB0nnwahwAbc/ni2538agmJkg==
1433+
1434+
version "3.0.0-rc.10"
1435+
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.0-rc.10.tgz#dd1380d1ee61170de76f9eb91e0d8ac7985f0ae0"
1436+
integrity sha512-pqIUf5leZm0P9379utrRSVBMxhV8XaqJTEFFp5etCtbEa/H5ALs29EjFMtMcm9sQaVkZlKLu86mgIacbYB9Q3w==
14371437
dependencies:
1438-
"@vue/compiler-core" "3.0.0-rc.6"
1439-
"@vue/shared" "3.0.0-rc.6"
1438+
"@vue/compiler-core" "3.0.0-rc.10"
1439+
"@vue/shared" "3.0.0-rc.10"
14401440

1441-
"@vue/compiler-sfc@^3.0.0-rc.6":
1442-
version "3.0.0-rc.6"
1443-
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.0-rc.6.tgz#22eccc19936abeb860535b3be1f00869456507b4"
1444-
integrity sha512-ebzFDNhnQYsmZFh0t+TF/ro8LinyHebdNQEfCZ2sYLJZC0fn4NyvryxflLXwpFtPMl+5s3dWk37wQMDL8NbYHw==
1441+
"@vue/compiler-sfc@^3.0.0-rc.10":
1442+
version "3.0.0-rc.10"
1443+
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.0-rc.10.tgz#4351ece66cdf4d758877482f69421c43d994dbaf"
1444+
integrity sha512-VIJ+VXqeM7WoRNgD9uYSARVb6CYq+JS2NNHfeerfNc7Uk3pjYHRv1MwEicAvN6zWFm5GLC1ZYTVD+WFg3xGAkQ==
14451445
dependencies:
14461446
"@babel/parser" "^7.10.4"
14471447
"@babel/types" "^7.10.4"
1448-
"@vue/compiler-core" "3.0.0-rc.6"
1449-
"@vue/compiler-dom" "3.0.0-rc.6"
1450-
"@vue/compiler-ssr" "3.0.0-rc.6"
1451-
"@vue/shared" "3.0.0-rc.6"
1448+
"@vue/compiler-core" "3.0.0-rc.10"
1449+
"@vue/compiler-dom" "3.0.0-rc.10"
1450+
"@vue/compiler-ssr" "3.0.0-rc.10"
1451+
"@vue/shared" "3.0.0-rc.10"
14521452
consolidate "^0.15.1"
14531453
estree-walker "^2.0.1"
14541454
hash-sum "^2.0.0"
@@ -1460,42 +1460,42 @@
14601460
postcss-selector-parser "^6.0.2"
14611461
source-map "^0.6.1"
14621462

1463-
1464-
version "3.0.0-rc.6"
1465-
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.0.0-rc.6.tgz#88635676e227cd08a2caa3110a16824727d4baab"
1466-
integrity sha512-dowz48cpbsUNyPeabH2WbBbP1R3zE/BZo6l8EEGXfmg8A0Qi3pu+m/9fZB0GJIWLpGaxDe4a7swLflo0bEa2ZA==
1463+
1464+
version "3.0.0-rc.10"
1465+
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.0.0-rc.10.tgz#95a5f6b65b19a514c94f056994ec144b3b1b03ae"
1466+
integrity sha512-JBPil8sO5j7puB8acX2CQMRXEYB/EP8PoEur7RcF/+aqATI7C4yqWcSLC5TRJpigj6xE6ku6sx8om+j7ZHvgBw==
14671467
dependencies:
1468-
"@vue/compiler-dom" "3.0.0-rc.6"
1469-
"@vue/shared" "3.0.0-rc.6"
1468+
"@vue/compiler-dom" "3.0.0-rc.10"
1469+
"@vue/shared" "3.0.0-rc.10"
14701470

1471-
1472-
version "3.0.0-rc.6"
1473-
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.0-rc.6.tgz#2bca7dd8b0b4219cce6d6e31fac5f30d78ac4845"
1474-
integrity sha512-FBAoswICU75OlmeWPSINvpKZnqpZ7ILBDPWBn816SbCbPj2V3W+aVyswgJXkDWWSw6XBng+WxVwdoNFyR537UQ==
1471+
1472+
version "3.0.0-rc.10"
1473+
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.0-rc.10.tgz#34d5f51bcc5a7c36e27d7a9c1bd7a3d25ffa7c56"
1474+
integrity sha512-mkUZfOJlbqGZx2cARmhCs5r2+xLJPL7VFNagmlA3Fd66ZXBc3ZvTQdYsY4VUbYJFe5ByIzqu9TZiAkzXY+JVaA==
14751475
dependencies:
1476-
"@vue/shared" "3.0.0-rc.6"
1476+
"@vue/shared" "3.0.0-rc.10"
14771477

1478-
1479-
version "3.0.0-rc.6"
1480-
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.0-rc.6.tgz#cca883b6cc941db304c84ca79f43458dd8b3a5bc"
1481-
integrity sha512-p/nA8Nl4w28uO3s0E5ZnIT9YPx8LOY35YAA0YGSfXAbeq09NQaFRv/LkJSVzNKRFvLiE5brPpQ+gb3YGKdtwjQ==
1478+
1479+
version "3.0.0-rc.10"
1480+
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.0-rc.10.tgz#9055aef5113cbc328aaec29760c2151e0ed3cf40"
1481+
integrity sha512-VK/kq4gDDoqZ45CVwdbLLpikXLYLCt6YLhdgXX3fhf20gvPqrbEZv1ZNLruNnhhTpf9cLyU4tZ18DHeaUYPziw==
14821482
dependencies:
1483-
"@vue/reactivity" "3.0.0-rc.6"
1484-
"@vue/shared" "3.0.0-rc.6"
1483+
"@vue/reactivity" "3.0.0-rc.10"
1484+
"@vue/shared" "3.0.0-rc.10"
14851485

1486-
1487-
version "3.0.0-rc.6"
1488-
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.0-rc.6.tgz#1dd18f1a92f7e7838641741c5aa1d24ce508c5a3"
1489-
integrity sha512-fRiAW3bMe6wTHQU9aK66wSwVnrXoMahsdESdngXiulXEW6swSspsarzFI0RlYyiPaN1OQbr3Dtpxxjzq1HNyZw==
1486+
1487+
version "3.0.0-rc.10"
1488+
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.0-rc.10.tgz#50f95cb991483a4262163723320967ad17bb321f"
1489+
integrity sha512-bH4GuneHt3FQ+/21jba5orM/CO9N1cnT7J3wtrxopFJ4/4H5cvHXyG6v+ZVTu1d733Ij/6yMRA7xbtfi9a4zJw==
14901490
dependencies:
1491-
"@vue/runtime-core" "3.0.0-rc.6"
1492-
"@vue/shared" "3.0.0-rc.6"
1491+
"@vue/runtime-core" "3.0.0-rc.10"
1492+
"@vue/shared" "3.0.0-rc.10"
14931493
csstype "^2.6.8"
14941494

1495-
1496-
version "3.0.0-rc.6"
1497-
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.0-rc.6.tgz#36f70b76df1e58afc1262d44a227276ea1156e59"
1498-
integrity sha512-DqsDUKyVQK9fDurH7woj8LGT36BPYXd9FbSkN3i2lsLl4RtA5qFNx8nR5yApLoTOUiOy/XxorD/AC3erEJ8s8g==
1495+
1496+
version "3.0.0-rc.10"
1497+
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.0-rc.10.tgz#e7ab62abcabbfc738545902b96a3aa78f59f3286"
1498+
integrity sha512-fI6gVhhgb3cAmEkY4oeVVA2hWZ2xvkgogHdBI5PL7gSvZnOB6XZ2eQGsYjC4W+7BegvEkoMBuZsFXVa4ZQ07XQ==
14991499

15001500
"@webassemblyjs/[email protected]":
15011501
version "1.8.5"
@@ -8485,14 +8485,14 @@ void-elements@^2.0.1:
84858485
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
84868486
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
84878487

8488-
vue@^3.0.0-rc.6:
8489-
version "3.0.0-rc.6"
8490-
resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-rc.6.tgz#856baa7c5701e9f960b7831f8683232eb6a687d6"
8491-
integrity sha512-A6zXzKNFbYfAwCrwzyQIB5sbIcONhVUBCQPrCk3KQrYIx5bVF6yHUK+CaMeXcioHAhuoyMGbS3VuTlblUazTpg==
8488+
vue@^3.0.0-rc.10:
8489+
version "3.0.0-rc.10"
8490+
resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-rc.10.tgz#31298a757b4fad6ee8973d0fa27c4fde8574bd01"
8491+
integrity sha512-nRsyIQtOWLDMBb5dsPwg/WdIqznCMVWN6O6wJSzhseKC768wHlZKcJ7SPHhWPid9wi3Ykhtl9vtgvxTK/qICkw==
84928492
dependencies:
8493-
"@vue/compiler-dom" "3.0.0-rc.6"
8494-
"@vue/runtime-dom" "3.0.0-rc.6"
8495-
"@vue/shared" "3.0.0-rc.6"
8493+
"@vue/compiler-dom" "3.0.0-rc.10"
8494+
"@vue/runtime-dom" "3.0.0-rc.10"
8495+
"@vue/shared" "3.0.0-rc.10"
84968496

84978497
w3c-hr-time@^1.0.2:
84988498
version "1.0.2"

0 commit comments

Comments
 (0)