Skip to content

feat(sfc): allow multiple template and script blocks in a SFC #7264

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

Closed
wants to merge 2 commits into from
Closed

feat(sfc): allow multiple template and script blocks in a SFC #7264

wants to merge 2 commits into from

Conversation

rigor789
Copy link

@rigor789 rigor789 commented Dec 18, 2017

What kind of change does this PR introduce? (check at least one)

  • Bugfix
  • Feature
  • Code style update
  • Refactor
  • Build-related changes
  • Other, please describe:

Does this PR introduce a breaking change? (check one)

  • Yes
  • No

If yes, please describe the impact and migration path for existing applications:

The PR fulfills these requirements:

If adding a new feature, the PR's description includes:

  • A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

Other information:
The reason I'm submitting this PR is because for nativescript-vue we would like to introduce code-sharing between web and native, but one limiting factor is that we can't have more than 1 template or script tag in a SFC.

We would like to write our SFC like so:

<template native>
    <StackLayout></StackLayout>
</template>
<template web>
    <div></div>
</template>

<style native>
    StackLayout { background: red; }
</style>
<style web>
    div { background: red; }
</style>

<script>
    export default {
        methods: {} // the core code
    }
</script>
<script native>
    export default {
        methods: {} // methods that interact with the UI.
    }
</script>
<script web>
    export default {
        methods: {} // methods that interact with the UI.
    }
</script>

(More information can be found at tralves/ns-vue-loader#2)

The current implementation assumes only 1 of these blocks, and only the last one is kept, with this PR it will parse all of the blocks, and return them in an array, while keeping it backwards compatible.

@rigor789 rigor789 mentioned this pull request Dec 18, 2017
13 tasks
@posva
Copy link
Member

posva commented Dec 18, 2017

This is great!
My 2 cents: I think having an attribute name (or similar) on the template and script to identify them would also allow us to build an object instead of an array and always take the one without a name or (name="default") instead of the last defined template or script

@rigor789
Copy link
Author

@posva We could add a name attribute, but that would limit us with syntax, unless we auto-generate a name (default, template-1, template-2, etc.) when none is provided. For nativescript-vue it could work like

<template></template> <!-- default -->
<template name="native"></template>

But I still think it is nicer to have / write like so

<template web></template>
<template native></template>

@posva
Copy link
Member

posva commented Dec 18, 2017

The reason I'm proposing an attribute with a value is because it doesn't make sense to write <template web native>, which is possible, and this is because the real attribute in your case is the platform, which can be native or web. The other way feels like web and native are boolean attributes

@phanan
Copy link
Member

phanan commented Dec 18, 2017

Can't we solve the problem from the build layer i.e. having multiple files (component.(native|web).vue or (native|web)/component.vue etc.) and configuring Webpack in a certain way? Having all templates and scripts in the same file would make it harder to maintain between different developers IMO, and the files would grow quite fat in no time.

@rigor789
Copy link
Author

rigor789 commented Dec 18, 2017

The reason I'm proposing an attribute with a value is because it doesn't make sense to write <template web native>, which is possible, and this is because the real attribute in your case is the platform, which can be native or web. The other way feels like web and native are boolean attributes

That's a valid point, but I would leave that to the tool to validate what should / shouldn't be possible

Can't we solve the problem from the build layer i.e. having multiple files (component.(native|web).vue or (native|web)/component.vue etc.) and configuring Webpack in a certain way? Having all templates and scripts in the same file would make it harder to maintain between different developers IMO, and the files would grow quite fat in no time.

Sure we can, but I would leave this up to the tool / loader to decide. For example we plan on doing more than just compiling one .vue file for web and one for native, we will utilize mixins to automatically merge platform specific code with platform-independent code and I think it would make sense to have it in a single file (we will only know if this is feasible once we try it).

(edit: fixed formatting)

@yyx990803
Copy link
Member

yyx990803 commented Dec 18, 2017

I personally feel the syntax is less maintainable than @phanan 's suggestion. What I'd personally do is:

- Foo.web.vue
- Foo.native.vue
- Foo.shared.js # shared between web and native
- Foo.shared.scss # shared between web and native

The shared js can be imported by both *.vue files and used as a mixin, or a base for extends. If a convention is used (e.g. if file ends with .shared.js), this can be done automatically without modifying the SFC syntax.

The shared CSS can be SASS mixins or whatever reuse mechanism the pre-processor allows. Again, can be done automatically.

Note that we want to keep the SFC syntax as consistent possible, because it involves a big ecosystem of tools that need to support any new features added (e.g. Vetur would need to do something very different for handling SFCs with multiple scripts/templates). The proposed syntax, IMO, does not justify adding the new syntax.

@yyx990803 yyx990803 closed this Dec 18, 2017
@rigor789
Copy link
Author

I do understand that there is a big ecosystem around SFC syntax, although I do not think this addition would require all the tooling to support it, since there are no breaking changes. It would only allow us to experiment with the new syntax in our own loader implementation without maintaining a fork of the parser.

We will keep experimenting with the proposed syntax using my fork, to see how it works out in the real world.

Thanks for your feedback!

@yyx990803
Copy link
Member

yyx990803 commented Dec 18, 2017

@rigor789 yeah, I think exploring in a fork would be a plausible step for now, we can revisit this with more real world feedback.

@rigor789
Copy link
Author

@yyx990803 Absolutely! Thanks

@plantir
Copy link

plantir commented Sep 10, 2018

is there any repo for this?
I want to use vue native and vue pwa in one project
https://github.com/vrwebdesign/vue-native-web
this is my source code but not work correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants