nuxt-modules / prismic

Easily connect your Nuxt.js application to your content hosted on Prismic
https://prismic.nuxtjs.org
MIT License
245 stars 48 forks source link

Cannot get Previews to work with SPA app #114

Closed jameshhood closed 3 years ago

jameshhood commented 3 years ago

I've been trying to figure out how to get Preview functionality to work with my SPA app for the longest time. Does anyone have a working example they could possible provide that isn't using nuxt generate?

lihbr commented 3 years ago

Hi @jameshhood and sorry for the delay!

Can you share your nuxt.config.js file here and how you're deploying your application? If you can provide some information about the error you're getting that'd be perfect also!

If I remember correctly, to deploy a Nuxt app as an SPA you need to set target: "static" and ssr: false in the config file, then run nuxt generate to get the SPA output. Did some quick test here and everything seems to work as expected πŸ€” (also tried with target: "server" and nuxt build && nuxt start and it's working as expected)

Also, for next time, just letting you know you can usually get support much quicker using Prismic community forum ☺️

jameshhood commented 3 years ago

@lihbr Nuxt allows you to build in SPA, Static, or SSR. SPA generates a single index.html that we host via a ngnix cluster.

I don't get any errors at all. The problem is the UI doesn't seem to respond to the preview token/request. I'm not sure what configuration needs to change on the UI or server to make this work for an SPA.

I have my config files broken down into separate files

// spa.config.js
module.exports = {
  router: {
    mode: 'hash',
    base: process.env.ROUTER_BASE || '/',
    middleware: ['useragent', 'auth', 'cookieconsent', 'updatelegal']
  },
  ssr: false,
  ...require('./vuetify.config.js'),
  ...require('./axios.config.js'),
  ...require('./base.config.js')
}
// sudo version of base.config.js
module.exports = {
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxt/typescript-build',
    '@nuxtjs/eslint-module',
    '@nuxtjs/vuetify'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/auth',
    'nuxt-i18n',
    'nuxt-sm',
    '@nuxtjs/prismic'
  ],
  ...require('./auth.config.js'),
  ...require('./prismic.config.js'),
  build: {
    /*
     ** You can extend webpack config here
     */
    quiet: false,
    extractCSS: true,
    followSymlinks: true,
    templates: [
      {
        src: './templates/version.json',
        dst: '../static/version.json',
        options: {
          version: version
        }
      }
    ],
    // publicPath: '/nuxt/',
    transpile: ['vuex-module-decorators', 'vue-slicezone', 'nuxt-sm'],
    extend(config, ctx) {
      // Run ESLint on save
      if (ctx.isDev && ctx.isClient) {
        config.devtool = '#source-map'
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    }
  }
}
// prismic.config.js
module.exports = {
  prismic: {
    endpoint: process.env.PRISMIC || '/prismic',
    linkResolver: '@/plugins/linkResolver.js',
    preview: '/preview/'
  }
}
lihbr commented 3 years ago

I see, thanks for sharing those details!

I tried to reproduce the preview failing using your config (router & prismic config and things related to generation of the index.html) but unfortunately, I wasn't able to achieve a similar result. To be sure we're on the same side and if that can help here's a step by step of what I've done with Nuxt.js 2.14+:

  1. Set my config to generate an SPA like you, mainly:
    export default {
    router: {
    mode: "hash",
    base: "/"
    },
    ssr: false,
    module: ["@nuxtjs/prismic"],
    prismic: {
    endpoint: "https://***.prismic.io/api/v2",
    preview: "/preview/"
    }
    };
  2. Generate the dist folder with index.html using $ nuxt build
  3. Host the dist folder on a platform (used Netlify for the sake of simplicity)
  4. Get to the Prismic repository, Settings, then Previews, and configured a new one using my domain name and /#/preview/ as the resolver
  5. Edit a document, save, and preview

What browser are you using? (we're aware Safari has some privacy policy preventing previews to work correctly on it) Can you also check your cookies? When ok you're expecting an io.prismic.preview cookie to be set on your website containing a JSON string.

I'm sorry for the inconvenience, I hope we'll find out soon how to troubleshoot your issue πŸ™‚

jameshhood commented 3 years ago

So when I click the preview button from primsic, it opens the correct webpage at /#/preview/?token... but it immediately redirects back to the root page '/' and no editing becomes available. If I were to run a development version of the app where "preview" is enabled by default I can access and view my testing documents. So for what ever reason the token is not being handled properly. Even when I tried explicitly defining a preview page in nuxt, the redirect happened. I'm not sure what would cause this and how to fix it.

jameshhood commented 3 years ago

When I clear the application's cookies and storage and click the preview button over from prismic, I get a prismic login page. After signing in, it redirects to the /preview/?token page. Upon the loading of that, it redirects back to the root page. From what I read, that's pretty normal without defining any special link-resolver. The only thing that doesn't seem to happen is that the "preview" functionality does not get enabled upon getting the token ect.

lihbr commented 3 years ago

Hey James, thanks for providing additional information!

I did some more testing on my side using dynamic pages. Indeed without a link resolver set up (or the routes option on the API) everything will redirect to the index indeed, that's the expected behavior. Although when setting up one it will still do so because of the router.mode: "hash" option which appears not to have been handled on our side. That's definitely an issue of us! In the meantime navigating back to the previewed page can work that around (while not being ideal)

Regarding the website not previewing I'm still puzzled at it as I'm not able to reproduce it in any way πŸ€”

Can you check/confirm the following statements while I'm asking a colleague about your issue? Thanks!

  1. What browser & version are you using?
  2. Can you share the name of your Prismic repository? (this way we can make sure there's nothing wrong with it)
  3. Are you seeing any errors in the console/network tab of the browser dev tool?
  4. Can you try previewing after having your middleware disabled? (Given their name I suspect some of them might be messing with cookies?)
jameshhood commented 3 years ago

So all of the content that I pull from my repo is done through $prismic.api.getSingle(...) which is typically done on the mounted event. This should be and is executed on the redirect from /preview/ to /

When I typically run the app in development mode (localhost) the prismic toolbar functionality is on by default. When I build for production and deploy, that is off by default and I would assume by going to /preview/ and downloading the cookie, that would get enabled but that's what we're trying to figure out?

Also by manually going to /preview I still get redirected back to the home page. It seems like all the bells and whistles are working correctly other than the fact that the module is not recognizing that it needs to go into development mode and activate the prismic toolbar

My user-agent/browser information : Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Repo name: gartman-nxp

Errors: No errors, just for what ever reason the prismic toolbar is not becoming active to even view/edit documents. I had thought that maybe the auth module would be affecting it, however you define a custom prefix for how it names cookies. Here is a list of other modules I use. Maybe you may know of one that may cause issues?

buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxt/typescript-build',
    '@nuxtjs/eslint-module',
    '@nuxtjs/prismic',
    '@nuxtjs/vuetify'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/auth',
    'nuxt-i18n',
    'nuxt-sm'
  ],
lihbr commented 3 years ago

Thanks for your patience and information!

So all of the content that I pull from my repo is done through $prismic.api.getSingle(...) which is typically done on the mounted event. This should be and is executed on the redirect from /preview/ to /

True, I would have used asyncData but in SPA mode I think those behave the exact same, so, well ^^

When I typically run the app in development mode (localhost) the prismic toolbar functionality is on by default. When I build for production and deploy, that is off by default and I would assume by going to /preview/ and downloading the cookie, that would get enabled but that's what we're trying to figure out?

Interesting, can you try running the app locally in production mode ($ npm run start will spin up a simple HTTP server for it) and check for the Prismic toolbar?

Actually, here is more information about how the toolbar behaves that may help you troubleshoot that perhaps:

Perhaps it's not working on your production because your Nginx cluster has some Content Security Policies set preventing iframe or cookies from 3rd party? To check this assumption perhaps you could try to host your SPA on Netlify quickly by drag'n'dropping your dist folder to it? (you might want to rebuild it with generate.fallback: true in your Nuxt config if you encounter 404s) If that works there then I think we figured out what to tweak πŸ™‚

Also by manually going to /preview I still get redirected back to the home page. It seems like all the bells and whistles are working correctly other than the fact that the module is not recognizing that it needs to go into development mode and activate the prismic toolbar

Yes, sounds like expected behavior.

My user-agent/browser information : Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Repo name: gartman-nxp

Browser looks good (Safari has some issues with its CSP), I'll check on our side if anything's wrong with your repository, but I think it's ok.

Errors: No errors, just for what ever reason the prismic toolbar is not becoming active to even view/edit documents. I had thought that maybe the auth module would be affecting it, however you define a custom prefix for how it names cookies. Here is a list of other modules I use. Maybe you may know of one that may cause issues?

Thanks for trying, I think that's ok, I'm not familiar with the auth module but this should mess with it.

I'm really sorry for the delay it's taking to resolve this issue and thank you again for your patience, we're getting there!

jameshhood commented 3 years ago

So if I build/start it and run it locally it works just fine. Do you have documentation/recommended on a configuration for Nginx settings. That seems to be the issue. I'm working with my Systems Engineer right now about getting it resolved.

jameshhood commented 3 years ago

This is what we set for our response headers for test purposes. Is there additional things we need to add for prismic?

content-security-policy: default-src *  data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval' 'unsafe-dynamic'; script-src * data: blob: 'unsafe-inline' 'unsafe-eval'; connect-src * data: blob: 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src * data: blob: ; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';

It still doesn't seem to work. Not sure what other kind of information we can provide?

lihbr commented 3 years ago

Hey that's awesome James, can you try with this one:

content-security-policy: default-src * data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval'; script-src * data: blob: 'unsafe-inline' 'unsafe-eval'; connect-src * data: blob: 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src * data: blob: 'unsafe-inline' 'unsafe-eval' ; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';

Here I allowed unsafe-inline and unsafe-eval for the frame-src directive and removed the unsafe-dynamic one from default-src since it's not a conventional one from what I know (I'm by far not an expert but well...) If that works going forward your systems engineers might want to narrow those directive to *.prismic.io, let me know!


A more visual preview:

image

jameshhood commented 3 years ago

So after tinkering with our CSP we found that the issue had nothing to do with that.

We found that the https://static.cdn.prismic.io/prismic.js?new=true&repo=<repo name> was not being loaded into the head of the document

We have it working now using a work-around, however, I thought the nuxtjs/prismic module was supposed to handle this automatically? I wonder if this has anything to do with it being an SPA and not having a server to generate the head of the document?

lihbr commented 3 years ago

Thanks for sharing that James,

Indeed the script gets injected at the end of the body (for performance purpose) programmatically when Nuxt is starting: https://github.com/nuxt-community/prismic-module/blob/master/src/templates/plugins/prismic.js#L97-L101

Glad you figured out a workaround and that it's working though, but that wouldn't explain why it was working locally / on Netlify πŸ€”

jameshhood commented 3 years ago

Yeah I have no idea. The only thing I can possibly think of is that we have a single web app that we configure the endpoint to point to different customers repos. We use a js file to inject the new values into the window and maybe the plugin may remove that script injection if no values exist? My local version has all those values directly passed.

lihbr commented 3 years ago

Closing this one for now since we didn't manage to find a clear reproduction for it, thanks again for your patience James~