inertia
inertia copied to clipboard
Convert Inertia Vue 2 & 3 adapters to TypeScript
based on #770
When developing this PR, I found that now Vue 2 adapter only uses Options API, while Vue 3 can use both Options and Composition API, which will be confusing when developing, so I supported the Composition API for Vue 2 adapter for this reason. Although the number of users may not be more, this can unify the Vue 2 / 2.7 / 3 versions of the API, and both the Options API and Composition API can be used at the same time, reducing the cost of conversion when developing, and the introduction in the documentation will also be clearer.
Has a package called vue-demi, I have tested this package to develop vue adapter, I think maybe merge the @inertiajs/inertia-vue and @inertiajs/inertia-vue3, but the code base difference of Vue 2/3 adapters is too big, finally, give up merge it.
Note Update on 2022/07/14: now support the Vue 2.7 support Composition API without
@vue/composition-api, use thevue-demito support both Vue 2 & 2.7 (only usevue-demiin vue 2 version)
For the test part, because there are 4 ways to use the vue adapter, adding Cypress test will be very time-consuming, so we are using PingCRM for now. can see if has plans to increase the test in the future.
I have some examples of using Vue x TypeScript below, and I hope to add them to the documentation after modifying them as a basis.
Any suggestion for this PR? 🤔
⭐ Main Changes
- Vue 2 adapter
- Support TypeScript
- Support Composition API
- can use
usePage(),useForm(),useRemember() - if you use Composition API or not, the
@vue/composition-apiwill always be installed.
- can use
- Vue 3 adapter
- Support TypeScript
- Other
- Update microbundle to ^0.14.0, will update typescript to ^4.1.3 (microbundle@^0.12.0 dependents the typescript ^3.9, version too old)
- Add
cross-envto tests to support runcypress:openon Windows OS - Add
--stagesflag to wsrun, will build main @inertiajs/inertia before other packages. (build all packages, in stages, starting from those that don't depend on other packages.) see: https://github.com/hfour/wsrun#examples
⭐ Vue versions & APIs
The Vue now has 2 main versions and 2 style APIs, there are 4 ways to use them:
- Vue 2 + Options API
- Vue 2 + Composition API
- Vue 3 + Options API
- Vue 3 + Composition API
Only the Vue 2 + Composition API does not have built-in support, so use the @vue/composition-api.
Anyway, you can use the above 4 ways to use Inertia.
PingCRM demo:
- PingCRM: Vue 2 + Options API + TS
- PingCRM: Vue 2 + Composition API + TS
- PingCRM: Vue 3 + Options API + TS
- PingCRM: Vue 3 + Composition API (
<script setup>) + TS
⭐ Develop or Try it!
The above PingCRM demo is all using the released version of inertia, if you want to try this PR, clone this branch to local:
git clone https://github.com/ycs77/inertia.git
cd inertia
git checkout inertia-vue23-ts
yarn
yarn build
use Vue 2 version (Don't use yarn link, and must change the [inertia-path]):
# move to vue 2 pingcrm
# fallow the pingcrm README installation...
yarn add @inertiajs/inertia@file:../[inertia-path]/inertia/packages/inertia
yarn add @inertiajs/inertia-vue@file:../[inertia-path]/inertia/packages/inertia-vue
yarn dev
yarn ssr:serve
php artisan serve
use Vue 3 version (Don't use yarn link, and must change the [inertia-path]):
# move to vue 3 pingcrm
# fallow the pingcrm README installation...
yarn add @inertiajs/inertia@file:../[inertia-path]/inertia/packages/inertia
yarn add @inertiajs/inertia-vue3@file:../[inertia-path]/inertia/packages/inertia-vue3
yarn dev
yarn ssr:serve
php artisan serve
⭐ Known Issue
Layout Function has type error on Vue 3
Now can't direct use Layout Function on Vue 3, must add the Layout Function type to complete the type hint and clear error:
<script lang="ts">
import { LayoutFunction } from '@inertiajs/inertia-vue3/types/app'
export default defineComponent({
layout: ((h, child) => h(child)) as LayoutFunction,
})
</script>
I think this API must be re-design in Composition API,
defineLayout()(#1117) is an API that I think is more feasible.And the function can use Generic and Method Overriding, friendly to TypeScript.
Of course, this issue needs further discussion...
⭐ User Guide (Docs)
With Vue 2 (<=2.6)
Must be added the alias of @vue/composition-api after upgrade @inertiajs/inertia and @inertiajs/inertia-vue:
webpack.config.js
module.exports = {
resolve: {
alias: {
'@vue/composition-api$': path.resolve('./node_modules/@vue/composition-api/dist/vue-composition-api.mjs'),
},
},
}
The @vue/composition-api is installed and run the Vue.use() in inertia-vue, Don't re-use in your application.
But if you want to use Composition API in your Vue 2 application, can be added @vue/composition-api todependencies of package.json.
With Vue 3
Upgrade @inertiajs/inertia and @inertiajs/inertia-vue3 to latest version.
Composition API
usePage()
Get page value with Composition API:
import { usePage } from '@inertiajs/inertia-vue3'
// Usage 1:
const { props } = usePage()
console.log(props.value.name) // "Your Name"
// Usage 2:
// If define Vue's props variable, there will be a conflict, so you need to define other variable names.
const { props: pageProps } = usePage()
console.log(pageProps.value.name) // "Your Name"
// Usage 3:
// If use `reactive()` wrap the `usePage()`, no need to add the `.value`.
const page = reactive(usePage())
console.log(page.props.name) // "Your Name"
Follow Best Practice | VueUse.
TypeScript
Define Global Page Props Types
Create a resources/js/inertia.d.ts file, and add the global page props types:
declare module '@inertiajs/inertia' {
interface PageProps {
auth: {
id: number
name: string
email: string
}
flash: {
success: string | null
error: string | null
}
}
}
export {}
It should be noted that it cannot be added to env.d.ts, otherwise it will be invalid.
usePage()
Define current page props type:
const { props } = usePage<{ myName: string }>()
props.value.myName // string
If you has define the global page props type, can direct use the props:
const { props } = usePage()
props.value.auth.id // number
Recommended IDE Setup
Thanks for picking this up! 🚀
Added the Vue 2.7 support
Curious if/when this is going to be merged, the Vue 2 adapter updates (usePage(), etc.) for the new composition API support and <script setup> would be extremely useful.
Curious if/when this is going to be merged, the Vue 2 adapter updates (
usePage(), etc.) for the new composition API support and<script setup>would be extremely useful.
@reinink @claudiodekker
@reinink any chance to have composition API in vue 2.7?
@ycs77 wow this is a ton of work, thanks! I'm worried that it might be very out of sync with my current next branch, and I'm not sure I want to implement TS for the Vue adapters quite yet, but I'd love to get this PR rebased against the next branch if you'd be willing – just so I can use it as a reference for now? Thanks! 🙏
@reinink any chance to have composition API in vue 2.7?
@makroxyz Yup! I'm actively working on making that happen — see #1282 👍
@ycs77 wow this is a ton of work, thanks! I'm worried that it might be very out of sync with my current
nextbranch, and I'm not sure I want to implement TS for the Vue adapters quite yet, but I'd love to get this PR rebased against thenextbranch if you'd be willing – just so I can use it as a reference for now? Thanks! 🙏
Of course~😊
@ycs77 You're also welcome to just wait until I finish the next PR and then we can figure out where to go from there — your call. I'm kind of hoping that we can add composition API (and <script setup>) support without having to add the vue-demi library to the project, since I think we can use the Vue 2.7 APIs for the hooks that will only work in Vue 2.7 projects anyway, but maybe I'm wrong?
@reinink
You're also welcome to just wait until I finish the next PR and then we can figure out where to go from there.
No problem! waiting for you to finish.
I'm kind of hoping that we can add composition API (and
I think you are right. If the composition API is the main thing in the future, you can abandon Vue 2.6 and use 2.7.