laravel / precognition

Anticipate the outcome of a future HTTP request.
https://laravel.com/docs/precognition
MIT License
130 stars 31 forks source link

Support for Nuxt 3 or add axios configuration #21

Closed nilskretschmer closed 1 year ago

nilskretschmer commented 1 year ago

Hey,

first of all thank you for this library. For inertia or vue based projects this works just fine.

For Nuxt 3 projects precognition is currently not working. I already tried a few approaches but there are some general problems integrating it:

  1. Nuxt 3 is not using axios. Instead it relies on the ofetch library which uses the standard Fetch API internally. I already managed authentication and csrf token with fetch.
  2. Precognition uses axios internally. This is fine for inertia or vue projects. For Nuxt 3 this is not needed, because useFetch() should be used.
  3. If I use the precognition-vue in a clientonly component the requests are sent without problems, but laravel returns 419 status, because there is no CSRF cookie set.

Ideas:

If I can help to Support Nuxt 3 I am glad to. If I understand it correctly this shouldn't be a big problem, because the library just sends requests to the same endpoint the form would be submit to, including Special precognition headers and the data value. Handling request sending itself is done by using vue/nuxt onchange events.

timacdonald commented 1 year ago

Hey there,

We don't currently have plans to make extensive changes to how we handle HTTP requests, however support for Nuxt should not be a problem.

Axios already detects the CSRF token and send it to Laravel if it is present in the X-XSRF-TOKEN header or the XSRF-TOKEN cookie.

If you need to specify these manually, once #25 is merged, you may do the following:

import { client } from 'laravel-precognition-vue'

client.axios().defaults.headers.common['Authorization'] = AUTH_TOKEN;
client.axios().defaults.headers.common['X-XSRF-TOKEN'] = XSRF_TOKEN;
RuneClaeys commented 1 year ago

Can this issue be re-opened? I'm trying to use this library with Nuxt 3, but get the following error:

[4:40:59 PM] Error [ERR_MODULE_NOT_FOUND]: Cannot find module '{{PATH_TO_MY_APP}}/node_modules/laravel-precognition/dist/client' imported from {{PATH_TO_MY_APP}}/node_modules/laravel-precognition/dist/index.js
    at new NodeError (node:internal/errors:399:5)
    at finalizeResolution (node:internal/modules/esm/resolve:326:11)
    at moduleResolve (node:internal/modules/esm/resolve:945:10)
    at defaultResolve (node:internal/modules/esm/resolve:1153:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:838:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

This is my component, keep in mind it's being rendered on the server.

<script lang="ts" setup>
import { useForm } from 'laravel-precognition-vue';

useForm('post', '/register', {
   first_name: '',
   last_name: '',
   phone_number: '',
   email: '',
   password: '',
   confirm_password: '',
});
</script>

<template>
   <div :class="'test'"></div>
</template>

<style lang="scss" scoped>
.test {
}
</style>
Minotti commented 1 year ago

Hey @RuneClaeys, I'm getting the same error.

nilskretschmer commented 1 year ago

Hey @timacdonald thank your for that.

I want to mention that this is no real Nuxt Support - it is just a workaround. The real problem is that Nuxt isn't using Axios at all, because it uses the useFetch-Composable which uses the ofetch library to handle client- and server-side requests properly (https://nuxt.com/docs/api/composables/use-fetch). Using Axios in Nuxt "destroys" this approach making this only usable on client-side-rendering.

Furthermore you will need to set the CSRF-Token and other authentication-related headers yourself for Nuxt 3 projects if using Axios if you use useFetch() for all other requests in your Nuxt 3 app. I also use useFetch in my App to authenticate the user so Axios is never doing the login and csrf-fetch-requests and therefore does not set the headers automatically.

Using the useForm function only on client-side-rendered component shouldn't be a big deal, because it is just a request to handle form validation so there is no real need to do this server-side (@Minotti / @RuneClaeys: Have you tried using useForm() in a ClientOnly-wrapped component?). But using the native Nuxt functions would be better in my oppinion. But I understand that you can't or won't support this.

I would provide my own library to support Nuxt, but I am not sure if I am allowed to do this in the Laravel namespace? So building a laravel-precognition-nuxt package? The problem is that it will be a lot different - mainly because there are different dependencies to use it with Nuxt. Can you give me an advice on this?

Thanks in advance.

timacdonald commented 1 year ago

@nilskretschmer you could build to Nuxt package in your own namespace and release it yourself. It doesn't need to be under the Laravel namespace.

We may one day consider a Nuxt version, but that isn't currently on our roadmap for Precognition.

timacdonald commented 1 year ago

@RuneClaeys I think that may be related to https://github.com/laravel/precognition/issues/30. Will be looking into that shortly.

sot1986 commented 1 year ago

Hello @timacdonald, please have a look to this repo. This is basically your code, adapted for $fetch.

timacdonald commented 8 months ago

Very cool, @sot1986. Thanks for putting that together. Hopefully others can use that to use Precog in Nuxt projects.

timacdonald commented 8 months ago

@RuneClaeys @Minotti I know it has been a while, but did you get to the bottom of this import issue?