Skip to content
This repository has been archived by the owner on Apr 9, 2023. It is now read-only.

vue-cli v3, can't get it to work.. no errors but pre-rendered routes don't contain static html #215

Closed
vesper8 opened this issue Jul 5, 2018 · 24 comments

Comments

@vesper8
Copy link

vesper8 commented Jul 5, 2018

Hi there.. I've been trying to follow the examples but I can't seem to get it to work.

This is my vue.config.js

const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');

module.exports = {
  baseUrl: process.env.npm_lifecycle_event === 'serve' ? '/' : '/v3',
  outputDir: 'dist',
  lintOnSave: true,
  configureWebpack: {
    resolve: {
      modules: [path.resolve(__dirname, 'src/spark'), 'node_modules'],
      alias: {
        vue$: 'vue/dist/vue.js',
      },
    },
    plugins: [
      new PrerenderSPAPlugin({
        staticDir: path.join(__dirname, 'dist'),
        routes: [
          '/',
          '/about,
        ],
      }),
    ],
  },
};

This file contains the only change I've made to my app.. if I'm supposed to make other changes.. then sorry.. it seemed as though everything else is optional.

When I do npm run build, I don't get any errors or warnings, it does generate an about folder with an index.html in it.. as well as an index.html in the root. But those don't contain any of the static html from the view component.

Perhaps one thing that might be at play is how I import my components in the router and in the views. I use dynamic imports like this (my about route in my vue-router):

I am using history mode by the way

{
    name: 'about',
    path: '/about',
    component: () => import('@/views/About'),
    meta: {
      title: 'About Us',
      description: "Learn about us",
    },
  },

And through my application I use dynamic imports like this too

But to be honest I've done some tests where I just do a regular import and it doesn't make a difference

I'm pretty lost as to what I might be missing.. help would be much appreciated!

Even though the next two questions will make more sense once I actually get this to work.. I thought I might ask them now.. first.. is it required to have a trailing slash in order to load the pre-rendered html? And second.. these routes I want pre-rendered, such as the about page, they can be accessed both while my users are logged in and logged out.. and the header (menu) is different whether they are logged in or out. I really only care about pre-rendering the page for logged out users however.. because Google can't reach the logged-in page and once the user is logged in the SPA loads pages super fast anyway. Is there something I should do to take this into account?

Let me know if you need me to share anything else. Many Thanks!!

@vesper8
Copy link
Author

vesper8 commented Jul 5, 2018

still haven't figured it out. But I decided to try with a fresh vue-cli project (rc3) and that works fine

you might like to use this repo to add another example

https://github.com/vesper8/vue-cli-3-prerender-spa-plugin-demo

Would still appreciate your thoughts on what might be causing this.. I will report back if I figure it out as well

@vesper8
Copy link
Author

vesper8 commented Jul 5, 2018

ok.. I found the guilty party.. it's this line

  baseUrl: process.env.npm_lifecycle_event === 'serve' ? '/' : '/v3',

I tried both paths separately

baseUrl: '/', // works
baseUrl: '/v3', // doesn't work

This is pretty problematic... but let's see if I can work around it

@JoshTheDerf
Copy link
Collaborator

Yeah, I haven't figured out the ideal way to deal with webpack's various output modifying settings. However, you might also want to configure the renderer like so:

new PrerenderSPAPlugin({
  staticDir: path.join(__dirname, 'dist'),
  routes: [
    '/',
    '/about'
  ],
  renderer: new PrerenderSPAPlugin.PuppeteerRenderer({
    renderAfterTime: 5000, // Wait five seconds for your app to start before rendering the page.
    headless: false // Let's you watch what's happening.
  })
}),

@lbjones
Copy link

lbjones commented Jul 19, 2018

If anyone has figured it out and can describe a workaround, that would be super awesome!

I also have found this is a problem to use baseUrl. I've tried prepending all my routes with the baseUrl but that doesn't do it. Plus I've tried a bunch of other stuff but still can't find a workaround.

@vesper8
Copy link
Author

vesper8 commented Jul 19, 2018

I've just had to do away with the dependency of the baseUrl.. which was a lot of work but made me realize this was the direction I should have taken all along.

Previously I had my vue application served through a catchall route in Laravel which is why I needed all my files to load from the /public/baseUrl/ folder in my Laravel installation. Now I've completely decoupled by front-end from my back-end and no longer need to generate my files in a subfolder. It's probably different for you but.. chances are there's a way you can get around needing to use a subfolder

@lbjones
Copy link

lbjones commented Jul 19, 2018

Hey thanks for the explanation @vesper8.

I think you're right, a URL prefix is not ideal. But in my case, i was not able to change that. I found a workaround by adding this to my vue router: base: process.env.VUE_APP_PATH_PREFIX ? process.env.VUE_APP_PATH_PREFIX : '/',

Now the prerender works properly, but the only downside was that I have to manually move some assets around after I build.

@Eunknight
Copy link

Eunknight commented Aug 25, 2018

找到方法了
prerender-spa-plugin 在dist目录起了一个服务
资源的引用路径是 根目录/baseUrl/*
但是实际上资源的路径为 根目录/*
所以prerender-spa-plugin无法找到资源
不能预渲染
我们把资源输出目录改为 dist/baseUrl
入口index.html 改为 dist/baseUrl/index.html
prerender-spa-plugin 输出改为 dist/baseUrl

建议添加 process.env.NODE_ENV === 'production' 判断,不然开发时时影响性能。

google translate:

Found a way

Prerender-spa-plugin started a service in the dist directory
The reference path for the resource is root/baseUrl/*
But actually the path to the resource is root/*
So prerender-spa-plugin can't find resources
Cannot prerender
We changed the resource output directory to dist/baseUrl
Change the index.html to dist/baseUrl/index.html
The prerender-spa-plugin output is changed to dist/baseUrl

It is recommended to add process.env.NODE_ENV ==='production' to judge, otherwise development will affect performance.

const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
module.exports = {
  baseUrl: '/testBaseUrl',
  outputDir: path.join(__dirname, 'dist/testBaseUrl'),
  configureWebpack: {
    plugins: [
      new PrerenderSPAPlugin({
        staticDir: path.join(__dirname, 'dist'),
        outputDir: path.join(__dirname, 'dist/testBaseUrl'),
        indexPath: path.join(__dirname, 'dist', '/testBaseUrl/index.html'),
        routes: [
          '/',
          '/about',
          '/contact',
        ],
      }),
    ],
  },
};

@SHERlocked93
Copy link

@Eunknight 老哥,你这是什么模板啊,webpack-simple么?

@SHERlocked93
Copy link

@Eunknight 可以参考一下我的做法

@volodalexey
Copy link

If you use chainWebpack this might help in vue.config.js:

const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')

module.exports = {
  chainWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config
        .plugin('prerender-spa-plugin')
        .use(PrerenderSPAPlugin, [
          {
            staticDir: path.join(__dirname, 'dist'),
            routes: ['/'], // List of routes to prerender.
            renderer: new PrerenderSPAPlugin.PuppeteerRenderer() // without this line does not work in my case
          }
        ])
    } else {
      // ...
    }
  }
}

@Eunknight
Copy link

@SHERlocked93 看这个issue标题,vue-cli v3 模板.

@JohnRSim
Copy link

Anyone else having issues with vue <router-link and prerender-spa-plugin in Vue-cli v3.

In Vue History mode
The following -
welcome
redirects to /welcome - seems to ignore history mode and act as an anchor tag..

welcome
Does nothing.

If I remove prerender-spa-plugin from vue.config.js then all works as expected.

  • my routes appear to be generated fine though in dist

@BruneXX
Copy link

BruneXX commented Dec 11, 2018

Hi guys, I'm using this with angular 6 but it seems that is not working there's no html code generated in specified routes...

@JoshTheDerf
Copy link
Collaborator

@BruneXX How are you dispatching the render event? I haven't used Angular 6 so I'm not sure exactly how that would work.

@BruneXX
Copy link

BruneXX commented Dec 12, 2018

Hi @tribex I'm using this configuration below:

new PrerenderSPAPlugin({
        // Required - The path to the webpack-outputted app to prerender.
        staticDir: path.join(__dirname, '../dist'),
        // Required - Routes to render.
        routes: [ '/' ]
      })

But the code generated is the same as I got with the previous configuration, I can't see the "home" page html code generated after plugin configuration...

Below tag I've only scripts and no html content..

@JoshTheDerf
Copy link
Collaborator

JoshTheDerf commented Dec 12, 2018

@BruneXX It looks like you haven't set any render triggers. The basic usage example only works for basic pages with synchronous JavaScript.

Try something more like this:

    new PrerenderSPAPlugin({
      // Required - The path to the webpack-outputted app to prerender.
      staticDir: path.join(__dirname, 'dist'),

      // Required - Routes to render.
      routes: [ '/' ],

      // Renderer configuration
      renderer: new Renderer({
        // Wait to render until the specified event is dispatched on the document.
        // eg, with `document.dispatchEvent(new Event('render-page'))`
        renderAfterDocumentEvent: 'render-page',
      })
    })

You'll then need to fire document.dispatchEvent(new Event('render-page')) somewhere in your Angular app once it loads.

@BruneXX
Copy link

BruneXX commented Dec 12, 2018

Hi @tribex Excellent, I'll do that and I'll let you know the results soon! thanks a lot!

@JoshTheDerf
Copy link
Collaborator

JoshTheDerf commented Dec 12, 2018

@BruneXX One other thing, it looks like Angular (unlike Vue and React) doesn't support DOM hydration yet, so you may see a white flash between the time the prerendered page loads and when the JS finishes running. There's no real way around that, unfortunately.

See: angular/angular#13446

@BruneXX
Copy link

BruneXX commented Dec 12, 2018

@tribex I've got the same result as before with the dispatchEvent.. I don't know why is not working..

@LiamMaru
Copy link

I found a solution that works for me. It's not pretty, but it's working for me.

First, set the base option in your router:

const router = new Router({
  base: "/some/path/to/somewhere/",
  ...
});

export default router

Next, in your vue.config.js file, set the baseUrl to the desired path, and the outputDir accordingly:

module.exports = {
  baseUrl: "/some/path/to/somewhere/",
  outputDir: "dist/some/path/to/somewhere/",
  ...
}

Finally, configure the SPA plugin like so:

new PrerenderSpaPlugin({
  staticDir: path.join(__dirname, "dist"),
  indexPath: path.join(__dirname, "dist/some/path/to/somewhere/index.html"),
  ...
});

As far as I can tell, all these settings really do is match up the directory structure with your routes (I'm barely knowledgeable about this stuff). To deploy your application, grab your contents from dist/some/path/to/somewhere. For example, if you were building a Docker image based on NGINX you'd do something like:

FROM nginx:latest

...

COPY  dist/some/path/to/somewhere /usr/share/nginx/html

CMD ["nginx", "-g", "daemon off;"]

Hope this helps.

This was referenced Jun 9, 2019
@elegantYU
Copy link

@Eunknight 老哥厉害,我一开始一直在修改routes里面的路径,后面发现是资源路径不对,却不知如何修改。终于,缘分让我们相聚:satisfied:

@RanmanticOfMonicaKS
Copy link

Anyone else having issues with vue <router-link and prerender-spa-plugin in Vue-cli v3.

In Vue History mode
The following -
welcome
redirects to /welcome - seems to ignore history mode and act as an anchor tag..

welcome
Does nothing.

If I remove prerender-spa-plugin from vue.config.js then all works as expected.

  • my routes appear to be generated fine though in dist

yep I have seen a solution just now . i seems to give route-to a '/' ,and $route.push('/route') instandsof $route.push('rout')
sry for my english

@dunhuang
Copy link

dunhuang commented Dec 2, 2020

The plugin provides the solution, prerender-spa-cdn-plugin.
Example: vue-cli3 with PUBLIC_PATH=//cdn.abcd.com

const PrerenderSpaCdnPlugin = require('prerender-spa-cdn-plugin')
// ...
new PrerenderSpaCdnPlugin({
  staticDir: path.join(__dirname, 'dist'),
  routes: ['/', '/about'],
  rendererOptions: {
    maxConcurrentRoutes: 1,
    injectProperty: '__PRERENDER_INJECTED',
    inject: {
      rendering: true
    }
  }
})

@hello-astar
Copy link

找到方法了 prerender-spa-plugin 在dist目录起了一个服务 资源的引用路径是 根目录/baseUrl/* 但是实际上资源的路径为 根目录/* 所以prerender-spa-plugin无法找到资源 不能预渲染 我们把资源输出目录改为 dist/baseUrl 入口index.html 改为 dist/baseUrl/index.html prerender-spa-plugin 输出改为 dist/baseUrl

建议添加 process.env.NODE_ENV === 'production' 判断,不然开发时时影响性能。

google translate:

Found a way

Prerender-spa-plugin started a service in the dist directory The reference path for the resource is root/baseUrl/* But actually the path to the resource is root/* So prerender-spa-plugin can't find resources Cannot prerender We changed the resource output directory to dist/baseUrl Change the index.html to dist/baseUrl/index.html The prerender-spa-plugin output is changed to dist/baseUrl

It is recommended to add process.env.NODE_ENV ==='production' to judge, otherwise development will affect performance.

const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
module.exports = {
  baseUrl: '/testBaseUrl',
  outputDir: path.join(__dirname, 'dist/testBaseUrl'),
  configureWebpack: {
    plugins: [
      new PrerenderSPAPlugin({
        staticDir: path.join(__dirname, 'dist'),
        outputDir: path.join(__dirname, 'dist/testBaseUrl'),
        indexPath: path.join(__dirname, 'dist', '/testBaseUrl/index.html'),
        routes: [
          '/',
          '/about',
          '/contact',
        ],
      }),
    ],
  },
};

厉害厉害

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

No branches or pull requests