Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<script setup> #227

Merged
merged 20 commits into from Jul 1, 2021
Merged

<script setup> #227

merged 20 commits into from Jul 1, 2021

Conversation

yyx990803
Copy link
Member

@yyx990803 yyx990803 commented Nov 9, 2020

This PR separates the <script setup> as proposed in #222 from the ref: sugar so it can be discussed and advanced on its own. It also has incorporated edits based on feedbacks in #222 that are specifically related to <script setup>.

<script setup>
// imported components are also directly usable in template
import Foo from './Foo.vue'
import { ref } from 'vue'

// write Composition API code just like in a normal setup()
// but no need to manually return everything
const count = ref(0)
const inc = () => { count.value++ }
</script>

<template>
  <Foo :count="count" @click="inc" />
</template>

Rendered

- Provide separate examples for `<script setup>` and ref sugar
- Add "yet another way of doing things" in drawbacks
@yyx990803 yyx990803 added the sfc Single File Components label Nov 9, 2020
This was referenced Nov 9, 2020
@axetroy
Copy link

axetroy commented Nov 9, 2020

I have some concerns that it will block tree-shake.

It is difficult to analyze whether a var has been used in the template

<template>
  <div></div>
</template>

<script>
// Can you know where the lodash is used?
import _ from "lodash"
</script>

@mgdodge
Copy link

mgdodge commented Nov 9, 2020

Does auto-exposing imported vue components mean that PascalCase is now required in SFCs? Consider the following:

<script setup>
import MyDatePicker from './my-date-picker.vue';
</script>

<template>
    <!-- This is obvious -->
    <MyDatePicker />

    <!-- Will this still work? -->
    <my-date-picker />
</template>

Right now the vue style guide says this is "strongly recommended", but not required. The kebab-casing is something I've seen in plenty of code I've reviewed. As people refactor, this might be something worth calling out explicitly.

@antfu
Copy link
Member

antfu commented Nov 9, 2020

@mgdodge I believe they will work for both styles in template.

@jods4
Copy link

jods4 commented Nov 9, 2020

Great that you have split the RFC! This part is much less controversial and might move forward faster.
There's a lot to love in here.

First a general question:
How much better do you think the dev experience + runtime perf of <script setup> will be over regular setup() w/ Composition API or even Options API?
I have a feeling the answer is "a good amount" and it gets me thinking... That makes it really compelling and not as optional as it is presented. What do you think?

Top level bindings are exposed to template

I like the local component example but how does that work exactly?
Does it work for local directives as well? Will there be no need to distinguish what's a component vs what's a directive?
I assume this is gonna generate code like h(MyComponent), which is more optimized than the current string lookup, right?
Will it work in <component :is=xyz> as well?

Closed by Default
Closed by default for parent component + explicit exposure model is good. (random thought... could the explicit exposure be export then?).

I note that this closes the door to MVVM style testing practices, which encourages unit testing a component without actually executing any UI.
Given that you generate bindings metadata anyway, it may be nice to have a function reserved for tests that could still return an object with instance data/functions that is bound to the view. Maybe behind a compilation flag if it needs to.

Another concern: when it comes to debugging, will we have easy access to instance data? Or will it be in a form that is really hard to get to?

export default can still be used inside <script setup> for declaring component options such as props.

That felt ok when you had the other export proposal.
Now that there are none left, it feels out of place, esp. given that it will be lifted out of the block.

I don't have a great suggestion here but... maybe put it in a <script props> block, with simplified syntax?
After all you put one-time initialization code in a separate block, <script setup> is supposed to be the setup() body.

To type setup arguments like props, slots and emit, simply declare them:

I ❤️ this, so much better than the current code.
Can we come up with something lean to declare default values? It's a pretty common scenario.

How will it work for more advanced scenarios, e.g. if we want to tap into prop validation? I assume we will use the JS props syntax, will it still declare the props type automatically as it does today?

Note that the props type declaration value cannot be an imported type

Surely you mean this won't work:

import T from "types"
declare const props: T

But surely this would, right?

import T from "types
declare const props: { foo: T }

Usage alongside normal <script>

It's a bit weird to reference variables across scripts blocks but hey.

My understanding of the RFC is that components defined in <script setup> block are always the default export of the sfc file they're defined in, right?

How can I import the component that is defined in the <script setup> block of my own file? import X from "./same-file.vue" would work?

Therefore, <script setup> cannot be used with the src attribute.

I was really torn about that one and changed my mind several time, but I agree it's weird and tricky. There are some bits that would be tricky technically, and for users you couldn't really reference globals in other script blocks, or props and emits, and it'd be a bit weird.

The question: what happens when your component gets really big? is still relevant.
You can extract code into external functions (in any way you want) and simply assign them to global variables in <script setup>. I think that's prob. the best solution.

I still feel differently about the ref part, but that's another RFC now.

Tooling Compatiblity

I'm still wary about this, because even if you don't use this RFC, you probably still use Vetur.
Not only should the compilation and refactorings work, but in my IDE a lot of things must happen as I type (lightbulbs, completions, errors, etc.)
This means the solution needs to be robust on invalid/incomplete code and fast enough for interactive usage when I type.

Can you confirm that the following is a good understanding of your plans?
With this RFC, the language service (both JS or TS) can see raw unmodified code from the script block when I'm typing. It is valid JS and everything is semantically as it should be. The only undeclared variables would be props and context, which a TS user would type with declare statements.

So what the IDE plugin needs to do in the <script setup> block is:

  • Kick-in to transform code before and after a refactoring.
  • Hide warnings for unused variables that are used in template.
  • Maybe some syntax highlighting of said variables.

That would seem a reasonable complexity and it wouldn't negatively impact the coding experience.

@yyx990803
Copy link
Member Author

@axetroy

Re tree-shaking: we definitely can reverse prune the exposed bindings because we do know what exactly the template uses during the template compilation process. The only downside is maybe we'll have to process the script twice - but we can cache the previous AST and only redo code generation.

So yeah, short answer is this is fixable (just some extra implementation cost).

@yyx990803
Copy link
Member Author

@mgdodge

Does auto-exposing imported vue components mean that PascalCase is now required in SFCs?

It can keep supporting kebab-case.

@yyx990803
Copy link
Member Author

yyx990803 commented Nov 9, 2020

@jods4

How much better do you think the dev experience + runtime perf of <script setup> will be over regular setup() w/ Composition API or even Options API?

I haven't really benched this, but my intuition would be non-trivial and it scales with the number of bindings used in the template.

I like the local component example but how does that work exactly?

During the script compile it generates binding metadata, and the components will be listed as setup bindings as well. When compiling the template, we will check if a component is exposed in setup and directly use the setup binding instead of attempting to resolve it at runtime.

I assume this is gonna generate code like h(MyComponent), which is more optimized than the current string lookup, right?

Yes.

Will it work in <component :is=xyz> as well?

Yes.

Does it work for local directives as well?

No. Directives will still need to use export default { directives: { ... }}.

I note that this closes the door to MVVM style testing practices, which encourages unit testing a component without actually executing any UI.

With explicit expose() you can still do that. You can even wrap the expose in a conditional block with compile time flag so it's only exposed during tests.

Another concern: when it comes to debugging, will we have easy access to instance data? Or will it be in a form that is really hard to get to?

You can still get a hold of the internal instance for debugging since you control the code.

How will it (TS props declaration) work for more advanced scenarios, e.g. if we want to tap into prop validation? I assume we will use the JS props syntax, will it still declare the props type automatically as it does today?

This is a good question to which I don't have a good answer for yet. But in general if you use TS declarations you have less need for manual validators anyway.

For imported types:

import T from "types"
declare const props: { foo: T }

Yes the above will work, but it will only generate a type-less runtime prop declaration since the compiler won't be able to trace the exact type of T.

My understanding of the RFC is that components defined in <script setup> block are always the default export of the sfc file they're defined in, right?
How can I import the component that is defined in the <script setup> block of my own file? import X from "./same-file.vue" would work?

It works the same since it compiles down to export default { setup() { ... }}.

Re: tooling plan

Yes, your understanding is largely on point.

@jods4
Copy link

jods4 commented Nov 9, 2020

No. Directives will still need to use export default { directives: { ... }}.

Unfortunate, is there really nothing you can do about this? Maybe when encountering v-my-directive in template look up if MyDirective was imported and auto-register it?

With explicit expose() you can still do that. You can even wrap the expose in a conditional block with compile time flag so it's only exposed during tests.

Not really:

  • public component API and internal template VM are definitely not the same.
  • You're suggesting exposing everything that is globally declared and used, I might as well use the good old setup() return statement if I do that.
  • Conditional block would change the shape of expose public API during tests, which would break other components using it (again, VM bound in template is not the same as public API).

You can still get a hold of the internal instance for debugging since you control the code.

It's not about controlling the code: I was afraid that after transformation everything would be local scope captures in a render function, which would be quite less practical in debug. You need to be in the right scope to get a peek with the debugger.

Today, with Vue devtools plugin or even without, if you can grab the component instance from Vue you can see and modify its internal state.

It works the same since it compiles down to export default { setup() { ... }}

Well yes but same-file references to the component shouldn't be compiled to an import...
Rather you'll need to compile to:

const _default = { setup() { } }
export default _default

// Code that imported default from itself would then reference _default constant.

@shawn-yee
Copy link

shawn-yee commented Nov 9, 2020

I hope snake_case_style works well too, because it is convenient for custom snippets and looks very nice.

import ${1:my_header_left} from "@/components/${1:my_header_left}.vue"

Although the underscore(_) character is not well highlighted in the standard template scope, it works well in the template lang="pug/jade" scope.

@ahaoboy
Copy link

ahaoboy commented Nov 10, 2020

some questions:
how can I explicitly return something I don't used in the template

in this Child.vue I can explicitly return say function or not

<template>
<div>child:{{ count }}</div>
</template>
<script>
import { ref } from "vue";
export default {
  setup() {
    const count = ref(0);
    const say = () => {
      count.value++;
      console.log("child2 say", count);
      return count;
    };
    return { count };
  },
};
</script>

in app.vue i can use the function say if child component return it

<script setup>
import { ref } from "vue";
import Child from "./Child.vue";
const childRef = ref();
const click = () => {
  console.log("app count", childRef.value.count);
  console.log("app click", childRef.value.say());
};
</script>
<template>
  <button @click="click">click</button>
  <Child ref="childRef" />
</template>

but in setup script, the say function i don't use in template, Will it be exported?
how can I hide some functions I don't want to export?

<template>
  <div>child:{{ count }}</div>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
const say = () => {
  count.value++;
  console.log("child say", count);
  return count;
};
</script>

@Justineo
Copy link
Member

how can I hide some functions I don't want to export?

You don't need to do that. All variables are available to template but closed to external access by default.

johnsoncodehk added a commit to vuejs/language-tools that referenced this pull request Nov 10, 2020
@yyx990803
Copy link
Member Author

Update: https://github.com/vuejs/vue-next/tree/ref-sugar now implements an option for compileScript in @vue/compiler-sfc that compiles the template of an SFC using <script setup> as inline render function:

Screen Shot 2020-11-10 at 5 27 32 PM

Some notes:

  • The new compiled output has no end-behavior difference from current output, but should provide non-trivial performance benefits as it removes the need to dynamically access properties from the render proxy.

  • This solves the tree-shaking issue raised by @axetroy, since variables not used in the render function won't be referenced in generated code.

  • This mode will only be used in production, because it prevents the template from being hot-reloaded in isolation from the script. There could be concerns regarding behavior consistency between prod and dev, but the possible cases are finite and we should be able to weed them out as we test drive this.

  • This will need dedicated integration in rollup-plugin-vue and vue-loader (so it's not currently testable yet).

@luwanquan
Copy link

Ask a question, can it receive eslint@typescript-eslint/no-unused-vars rule prompt?

@caikan
Copy link

caikan commented Nov 11, 2020

  • This mode will only be used in production, because it prevents the template from being hot-reloaded in isolation from the script. There could be concerns regarding behavior consistency between prod and dev, but the possible cases are finite and we should be able to weed them out as we test drive this.

@yyx990803 I think we can use eval to keep templates hot-reloaded in development mode.

const hotReloadRender = ref(function() {
    return h('div', unref(count))
})

export default {
    setup() {
        const count = ref(0)
        const inc = () => count.value++

        return () => {
            let render
            eval('render =' + hotReloadRender.value.toString())
            return render()
        }
    }
}

@vberlier
Copy link

Since we're aggressively trimming syntax down anyway, why not go all-out and make it possible to write js/ts directly at the root?

import { ref, useProps, useEmit } from 'vue'

const { message } = useProps<{ message: string }>()

const emit = useEmit<{ change: number }>()

const count = ref(0)
const inc = () => {
  count.value++
  emit('change', count.value)
}

<template>
  <p>
    {{ count }} {{ message }}
  </p>
  <button @click="inc">Increment</button>
</template>

The useProps and useEmit helpers could make it possible to have much more concise declarations for typescript users.

I'm not gonna lie though, my true hope is to one day be able to write vue templates (not jsx) inline anywhere and have them extracted and compiled as we've come to expect:

import { ref, createComponent } from 'vue'

const Counter = createComponent<{ 
  message: string,
  emit: {
    change: number,
  },
}>(({ message }, emit) => {
  const count = ref(0)
  const inc = () => {
    count.value++
    emit('change', count.value)
  }

  const { redText } = (
    <style>
      .redText {
        color: 'red'
      }
    </style>
  )

  return (
    <template>
      <p :class="redText">
        {{ count }} {{ message }}
      </p>
      <button @click="inc">Increment</button>
    </template>
  )
})

@RobbinBaauw
Copy link

RobbinBaauw commented Nov 11, 2020

I do think that the useProps and useEmit (and possibly other similar functions) could make <script setup> a lot better:

  • It doesn't require the export default, which is quite weird given it's the only export statement in the entire block
  • It doesn't require the setup="props, { emit }", which also seems like a workaround to pass the props & context
  • It could be typed similarly to how props currently are, without the need for IDEs to catch up (they won't provide type hints for the export default without something explicitly telling it how it should be typed). This even makes sure that you can use imported types in your prop definition!
  • It uses the VCA paradigm, so everyone understanding the VCA will understand what the functions do

Since a similar technique is proposed for the ref:, I'm sure this can be implemented without adding too much complexity. You may even be able to extend it to actually work in composition functions (using either a compile time loader or a runtime change of props and attrs, though I'm not sure if that's preferable).

For me, these functions change <script setup> from "Ew" to "I'll definitely use it"!

@caikan
Copy link

caikan commented Nov 11, 2020

@vberlier Many of your ideas are similar to mine, and I think you might like my proposal 😉: #221

@yyx990803
Copy link
Member Author

@vberlier Vue SFC is defined as using HTML syntax with script embedded in it. This is what allows style blocks, custom blocks, and the current parser/tooling is all built upon that assumption.

Your proposal flips it the other way around. By definition, it's not SFC anymore. If you want to make *.vue files work like that, it will essentially require major rewrite of all SFC related tooling with minimal benefits (if any). You might be better off just using JSX or something like vue-lit.

@yyx990803
Copy link
Member Author

yyx990803 commented Nov 11, 2020

@RobbinBaauw

It doesn't require the export default, which is quite weird given it's the only export statement in the entire block

export default not just allows you to declare props and emits: it is a catch-all for any component options that cannot be expressed inside setup(). It also works exactly the same way as in normal <script>, which current users are already familiar with.

It doesn't require the setup="props, { emit }", which also seems like a workaround to pass the props & context

It is a workaround. However, functions like useProps or useEmit are hacky too: they can't be implemented as real functions, because props and emits must be resolved before the setup() function is even called. So technically useProps and useEmit calls can only be implemented as compile-time macros that compiles to export default in the end. They also won't have access to any local scope variables. They look too much like normal functions so people are more likely to get bitten by the gotchas. On the other hand, export default looks "weird" exactly because we want people to know this is something different (it's hoisted out).

It could be typed similarly to how props currently are, without the need for IDEs to catch up (they won't provide type hints for the export default without something explicitly telling it how it should be typed). This even makes sure that you can use imported types in your prop definition!

IDE support should be trivial because export default is where props are inferred from in normal <script> as well. In fact it already works... what's needed is just exposing top scope variables to template which is unrelated to props typing.

Current <script setup> props declaration can use imported types in nested properties, it's just the entire props declaration itself cannot be an imported type (e.g. declare const props: ImportedInterface)

It uses the VCA paradigm, so everyone understanding the VCA will understand what the functions do

As explained above... they can't be actual VCA functions so it may be confusing when people realize they are just compiler hints.

@yyx990803
Copy link
Member Author

yyx990803 commented Nov 11, 2020

To clarify what I mean by useProps must be a compiler hint:

export default {
  setup(props) {
    // props must already be resolved before useProps is even called!
    useProps({
      foo: String
    })
  }
}

So we have to hoist it out:

export default {
  // argument of useProps hoisted here
  props: {
    foo: String
  },
  setup(props) {
    // ...
  }
}

But what if the user tries to do something like this?

import { useProps } from 'vue'
import { useSomething } from './utils'

useProps({
  foo: useSomething() ? String : Number
})

Note this will compile and run because useSomething is an import and thus is usable outside of setup(), but it is a composition function that implicitly relies on being called inside setup(), so it won't produce the desired runtime result!

Technically export default has the same issue, but I think it's easier to understand why export default is hoisted out compared to a normal-looking useXXX function.

Finally, I think such cases should be extremely rare in production because 99% of props declarations are probably static... so maybe useProps isn't that much of a problem.

@RobbinBaauw
Copy link

RobbinBaauw commented Nov 11, 2020

@yyx990803

They also won't have access to any local scope variables

That's a good point, didn't think of that.

To clarify what I mean by useProps must be a compiler hint:

Yep, this is what I meant wih "using either a compile time loader or a runtime change of props and attrs, though I'm not sure if that's preferable". I did not take local variables into account though, but that is a problem to solve either way.

Although: if useSomething calls any lifecycle hook it'll be clear in the console that it doesn't work, but it may not be entirely developer friendly.

@yyx990803
Copy link
Member Author

yyx990803 commented Nov 11, 2020

Played with the useProps idea for a bit. One issue is that we need to provide this for every property on the setup context, and useSlots, useAttrs etc. can be a bit much.

What if we consolidate it down to a single function:

import { useSetupContext } from 'vue'

const { props, emit, slots, attrs } = useSetupContext({
  props: {
    foo: String
  },
  emits: ['foo', 'bar']
})

With type-only declarations:

import { useSetupContext } from 'vue'

const { props, emit, slots, attrs } = useSetupContext<{
  props: { foo: string },
  emit: (e: 'foo' | 'bar') => void
}>()

The argument of useSetupContext cannot reference local scope variables (similar to export default) - this can be statically asserted and will result in a compile error.

@RobbinBaauw
Copy link

RobbinBaauw commented Nov 11, 2020

Would the following work (if xProps doesn't use any lifecycle hooks)?

import { composableProps } from "./my-composable";

const { composableProps } = useSetupContext({
   props: {
       ...xProps
   }
})

or even

import { composablePropsFn } from "./my-composable";

const { composablePropsFn } = useSetupContext({
   props: {
       ...xProps({ someOverride: 1 })
   }
})

This is a pattern I see emerging for composables (I think this is the best pattern for this use-case) and I think it may become quite common as a replacement for mixins. See for example https://www.notion.so/Composables-0574a105b61c4da1bc0993c6bcb59aed.

@Benoit-Vasseur
Copy link

Thanks for your replies @avil13 and @yyx990803 .

But I more concerned about the "design code" of the component itself.(not the compilation result or if the vars are accessibles outside, even if the defineExpose fn seems great).

For exemple if I have this component :

<script setup>
const privatFn = () => {
  // some "internal" code
}

const publicFn = () => {
// ceremony / config needed that the privateFn will do its job correctly
privateFn()
// some other stuff
}

// etc ... maybe I have three fn that use privateFn internally

// desired "feature" : to be able to give the message to my futur me and my colleague that "privateFn" is private
// and that it may not be appropriate to call it directly in the template 
// return {publicFn}
</script>

This is a "non sense" example and do not have a better one in my head right now but I definitively sometimes with the setup fn do not return everything that I have created inside (function or variables).

Without the "classic return feature" we loose some kind of nuance don't you think ?

@iamandrewluca
Copy link
Contributor

iamandrewluca commented Nov 26, 2021

So basically they want to do something like this (not real code)

<script setup>
// does not exist
import { defineReturn } from 'vue'

const privatFn = () => 'private function'
const publicFn = () => 'public function'

defineReturn({ publicFn })
</script>

<template>
  {{ privatFn() }} this one is not accessible
  {{ publicFn() }}
<template>

@yooneskh
Copy link

@Benoit-Vasseur what stops you from refactoring the privateFunction and public function into another file and exporting only the public function?

@mgdodge
Copy link

mgdodge commented Nov 26, 2021

I'd made similar comments in #222 which seemed to be well received by some, before this issue/feature was split off of it. I chose to use unit tests for my example, which was a contentious topic by itself and won't be discussed further here. Separating those private functions out into a separate file is not always desirable, so let's not suggest using composition when it's not helpful/needed. The desire to explicitly declare which values were "public" seems to be alive and well.

The way I read the last few comments on this, defineExpose seems like the best option. Supposedly it "compiles away", but it serves as an indication that the values contained within are "exposed/public" outside the component itself.

Since script setup has shipped, I doubt there's enough value here to introduce a breaking change - defineReturn or some equivalent would likely serve no other purpose than to document the visibility of its argument(s), another no-op that would just "compile away". Changing the way <script setup> works to actually prevent access to anything not explicitly wrapped in a new defineReturn is probably too disruptive a change.

That being said, I have yet to use <script setup> and instead use a standard script block with defineComponent and a setup function, partially for the same reason - I can define the return value there to explicitly state what is available and what is not. Typescript autocompletion seems to work just fine. <script setup> is just sugar, after all.

@yooneskh
Copy link

@mgdodge what you say that not everything can be extracted away is absolutely valid, but i personally have not faced a scenario as you said regarding private and public function. aside from this, as you say, script setup is out and we cannot make large breaking change, although i completely agree with design decisions made regarding script setup.

another point in your message that i have to point is that defineExpose does compile away, but is not noop! and is not only for documentation. it changes what properties are accessible from the vue component object, for example when you asisgn it to a ref.

also, in the recent talks @yyx990803 has made, i think the ref sugars are useable in every file if i'm not mistaken.

@Benoit-Vasseur
Copy link

@Benoit-Vasseur what stops you from refactoring the privateFunction and public function into another file and exporting only the public function?

I definitively can do that yes. I just point that the setup script drop a "basic standard JS feature" => the return ^^

@yooneskh
Copy link

@Benoit-Vasseur practically, the script setup does not seem to be in a function, so having a return might surprise some users

@mgdodge
Copy link

mgdodge commented Nov 26, 2021

I apologize for wording my prior comment in a way that suggests defineExpose is no-op. It clearly has a different purpose. My point was that a new defineReturn would be similar only in signaling to developers that values are going to be used elsewhere/later on. The no-op portion was meant to indicate that defineReturn should do nothing itself, <script setup> must work with our without defineReturn.

The direction that <script setup> has taken is fine with me as well, for the most part, though I do wish for explicit returns, but that's my only difference.

@vberlier
Copy link

vberlier commented Nov 26, 2021

@Benoit-Vasseur I'm a strong -1 on this. One of the original motivation for the script setup syntax is precisely to get rid of the redundant return statement.

Edit: motivation in original RFC https://github.com/vuejs/rfcs/blob/sfc-improvements/active-rfcs/0000-sfc-script-setup.md#motivation

@iamandrewluca
Copy link
Contributor

@vberlier I also thought of that. Because in Options API, template could access anything from this, and setup() { return {} } was like a regression 👀

@kunbo-Jiang
Copy link

kunbo-Jiang commented Dec 28, 2021

How can I use JSX with script setup ?

@kadiryazici
Copy link

how to use jsx in setup grammar?

<script lang="tsx">

export default defineComponent({
  render() {
    return <div> Hello </div>
  }
})
</script>

@kunbo-Jiang
Copy link

kunbo-Jiang commented Dec 28, 2021

how to use jsx in setup grammar?

<script lang="tsx">

export default defineComponent({
  render() {
    return <div> Hello </div>
  }
})
</script>

but cant use script-setup and jsx...

@kunbo-Jiang
Copy link

@yyx990803 Do you have any plans to support 【script-setup-render】 grammar in the future。That is not supported by the website...

@yyx990803
Copy link
Member Author

yyx990803 commented Dec 31, 2021

Do you have any plans to support 【script-setup-render】 grammar in the future。That is not supported by the website...

If you are writing a render function then you don't even need SFC or <script setup>.

@iamandrewluca
Copy link
Contributor

@yyx990803 Do you have any plans to support 【script-setup-render】 grammar in the future。That is not supported by the website...

https://dev.to/iamandrewluca/render-in-vue-16-ways-d50

kawamataryo added a commit to kawamataryo/chikamichi that referenced this pull request Jan 3, 2022
diff --git a/README.md b/README.md
index 8faad38..882547e 100644
--- a/README.md
+++ b/README.md
@@ -1,132 +1,21 @@
-# WebExtension Vite Starter
+# Fussy history search

-A [Vite](https://vitejs.dev/) powered WebExtension ([Chrome](https://developer.chrome.com/docs/extensions/reference/), [FireFox](https://addons.mozilla.org/en-US/developers/), etc.) starter template.
-
-<p align="center">
-<sub>Popup</sub><br/>
-<img width="655" src="https://user-images.githubusercontent.com/11247099/126741643-813b3773-17ff-4281-9737-f319e00feddc.png"><br/>
-<sub>Options Page</sub><br/>
-<img width="655" src="https://user-images.githubusercontent.com/11247099/126741653-43125b62-6578-4452-83a7-bee19be2eaa2.png"><br/>
-<sub>Inject Vue App into the Content Script</sub><br/>
-<img src="https://user-images.githubusercontent.com/11247099/130695439-52418cf0-e186-4085-8e19-23fe808a274e.png">
-</p>
+A very simple Chrome extension that enables fuzzy search of browsing histories.

 ## Features

-- ⚡️ **Instant HMR** - use **Vite** on dev (no more refresh!)
-- 🥝 Vue 3 - Composition API, [`<script setup>` syntax](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md) and more!
-- 💬 Effortless communications - powered by [`webext-bridge`](https://github.com/antfu/webext-bridge) and [VueUse](https://github.com/antfu/vueuse) storage
-- 🍃 [Windi CSS](https://windicss.org/) - on-demand CSS utilities
-- 🦾 [TypeScript](https://www.typescriptlang.org/) - type safe
-- 📦 [Components auto importing](./src/components)
-- 🌟 [Icons](./src/components) - Access to icons from any iconset directly
-- 🖥 Content Script - Use Vue even in content script
-- 🌍 WebExtension - isomorphic extension for Chrome, Firefox, and others
-- 📃 Dynamic `manifest.json` with full type support
-
-## Pre-packed
-
-### WebExtension Libraries
-
-- [`webextension-polyfill`](https://github.com/mozilla/webextension-polyfill) - WebExtension browser API Polyfill with types
-- [`webext-bridge`](https://github.com/antfu/webext-bridge) - effortlessly communication between contexts
-
-### Vite Plugins
-
-- [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) - Directly use `browser` and Vue Composition API without importing
-- [`unplugin-vue-components`](https://github.com/antfu/vite-plugin-components) - components auto import
-- [`unplugin-icons`](https://github.com/antfu/unplugin-icons) - icons as components
-  - [Iconify](https://iconify.design) - use icons from any icon sets [🔍Icônes](https://icones.netlify.app/)
-- [`vite-plugin-windicss`](https://github.com/antfu/vite-plugin-windicss) - WindiCSS support
-
-### Vue Plugins
-
-- [VueUse](https://github.com/antfu/vueuse) - collection of useful composition APIs
-
-### UI Frameworks
-
-- [Windi CSS](https://github.com/windicss/windicss) - next generation utility-first CSS framework
-
-### Coding Style
-
-- Use Composition API with [`<script setup>` SFC syntax](vuejs/rfcs#227)
-- [ESLint](https://eslint.org/) with [@antfu/eslint-config](https://github.com/antfu/eslint-config), single quotes, no semi
-
-### Dev tools
-
-- [TypeScript](https://www.typescriptlang.org/)
-- [pnpm](https://pnpm.js.org/) - fast, disk space efficient package manager
-- [esno](https://github.com/antfu/esno) - TypeScript / ESNext node runtime powered by esbuild
-- [npm-run-all](https://github.com/mysticatea/npm-run-all) - Run multiple npm-scripts in parallel or sequential
-- [web-ext](https://github.com/mozilla/web-ext) - Streamlined experience for developing web extensions
-
-## Use the Template
-
-### GitHub Template
-
-[Create a repo from this template on GitHub](https://github.com/antfu/vitesse-webext/generate).
-
-### Clone to local
-
-If you prefer to do it manually with the cleaner git history
-
-> If you don't have pnpm installed, run: npm install -g pnpm
-
-```bash
-npx degit antfu/vitesse-webext my-webext
-cd my-webext
-pnpm i
-```
-
-## Usage
-
-### Folders
-
-- `src` - main source.
-  - `contentScript` - scripts and components to be injected as `content_script`
-  - `background` - scripts for background.
-  - `components` - auto-imported Vue components that shared in popup and options page.
-  - `styles` - styles shared in popup and options page
-  - `manifest.ts` - manifest for the extension.
-- `extension` - extension package root.
-  - `assets` - static assets.
-  - `dist` - built files, also serve stub entry for Vite on development.
-- `scripts` - development and bundling helper scripts.
-
-### Development
-
-```bash
-pnpm dev
-```
-
-Then **load extension in browser with the `extension/` folder**.
-
-For Firefox developers, you can run the following command instead:
-
-```bash
-pnpm start:firefox
-```
-
-`web-ext` auto reload the extension when `extension/` files changed.
-
-> While Vite handles HMR automatically in the most of the case, [Extensions Reloader](https://chrome.google.com/webstore/detail/fimgfedafeadlieiabdeeaodndnlbhid) is still recommanded for cleaner hard reloading.
-
-### Build
-
-To build the extension, run
-
-```bash
-pnpm build
-```
+- ⚡️ Fuzzy search your browsing history. powered by [Fuse.js](https://fusejs.io/)
+- 🔐 All processing is done within the browser. No history data will be sent to the any server.

-And then pack files under `extension`, you can upload `extension.crx` or `extension.xpi` to appropriate extension store.
+## Demo

-## Credits
+https://user-images.githubusercontent.com/11070996/147921381-500b1045-c544-4938-bc5f-f88759cc415b.mp4

-![](https://user-images.githubusercontent.com/11247099/127029137-6b5ad5db-76c4-4061-86ff-489911a8adfb.png)
+## install

-This template is originally made for the [volta.net](https://volta.net) browser extension.
+// TODO

-## Variations
+I am currently in the process of submitting an extension to the public.

-This is a variant of [Vitesse](https://github.com/antfu/vitesse), check out the [full variations list](https://github.com/antfu/vitesse#variations).
+## Contributing
+Contributions are welcome 🎉 We accept contributions via Pull Requests.
diff --git a/package.json b/package.json
index e9de3f1..6061c11 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
 {
-  "name": "vitesse-webext",
-  "displayName": "Vitesse WebExt",
+  "name": "fussy-histoty-search",
+  "displayName": "Fussy history search",
   "version": "0.0.1",
-  "description": "[description]",
+  "description": "A very simple Chrome extension that enables fuzzy search of browsing histories.",
   "private": true,
   "scripts": {
     "dev": "npm run clear && cross-env NODE_ENV=development run-p dev:*",
@ubershmekel
Copy link

I got an error message that brought me to this pull request. For anyone else that is the same, here is how you use onMounted in Vue 3:

<script setup>
import { ref, onMounted } from 'vue'

const el = ref()

onMounted(() => {
  el.value // <div>
})
</script>

@Blaisepasca
Copy link

app.js:2 Uncaught SyntaxError: Unexpected token '<' le probleme c'est quoi au juste

@Blaisepasca
Copy link

app.js:2 Uncaught SyntaxError: Unexpected token '<'

@yooneskh
Copy link

app.js:2 Uncaught SyntaxError: Unexpected token '<'

@Blaisepasca Please provide a reproduction and also you can probably open a new issue.

@martinszeltins
Copy link

@Blaisepasca this PR was already merged 3 years ago.

cleverfish0v0 pushed a commit to cleverfish0v0/luffycity that referenced this pull request Apr 17, 2024
…S module exports. If you are using a previous version of <script setup>, please consult the updated RFC at vuejs/rfcs#227.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
final comments This RFC is in final comments period sfc Single File Components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet