SolarLiner / vue-cli-plugin-prerender-spa

Boost SEO by prerendering your Vue application. Powered by prerender-spa-plugin.
https://www.npmjs.com/package/vue-cli-plugin-prerender-spa
MIT License
174 stars 26 forks source link

TypeError: Cannot set property of 'template' of undefined #24

Open erikrenaud opened 5 years ago

erikrenaud commented 5 years ago

I get this Error:

-  Building for production... **ERROR  TypeError: Cannot set property 'template' of undefined
TypeError: Cannot set property 'template' of undefined**
    at config.plugin.tap.args (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\vue-cli-plugin-prerender-spa\index.js:55:26)
    at Object.tap (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\webpack-chain\src\Plugin.js:24:24)
    at config (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\vue-cli-plugin-prerender-spa\index.js:54:29)
    at webpackChainFns.forEach.fn (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\Service.js:227:40)
    at Array.forEach (<anonymous>)
    at Service.resolveChainableWebpackConfig (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\Service.js:227:26)
    at PluginAPI.resolveChainableWebpackConfig (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\PluginAPI.js:128:25)
    at module.exports (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\commands\build\resolveAppConfig.js:2:22)
    at build (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\commands\build\index.js:138:50)
    at api.registerCommand (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\commands\build\index.js:85:13)
    at Service.run (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\lib\Service.js:221:12)
    at Object.<anonymous> (C:\Users\erikr\source\repos\ToDoStudio\To-Do.Studio Info\TDS.Web\node_modules\@vue\cli-service\bin\vue-cli-service.js:36:9)
    at Module._compile (internal/modules/cjs/loader.js:722:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! to-do.studio.info@0.1.0 build: `vue-cli-service build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the to-do.studio.info@0.1.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

I am using a normal vue-cli based project using multiple pages (and no main.js)

pages: {
    "index": {
      entry: "src/home.js",
      template: "public/home.html",
      filename: "index.html",
    },
    "home-french": {
      entry: "src/homeFrench.js",
      template: "public/home-french.html",
      filename: "home-french.html",
    },
    "privacy-policy": {
      entry: "src/privacyPolicy.js",
      template: "public/privacy-policy.html",
      filename: "privacy-policy.html",
    },
    "terms-of-use": {
      entry: "src/termsOfUse.js",
      template: "public/terms-of-use.html",
      filename: "terms-of-use.html",
    },
  },

  pluginOptions: {
    prerenderSpa: {
      registry: undefined,
      renderRoutes: [
        '/',
        '/home-french',
        '/terms-of-use',
        '/privacy-policy'
      ],
      useRenderEvent: true,
      headless: true,
      onlyProduction: true
    }
erikrenaud commented 5 years ago

When looking at code ` if (process.env.NODE_ENV === "production") {

  config.plugin("html").tap(args => {

    args[0].template = api.resolve("public/index.html");

    args[0].filename = "app.html";

    return args;

  });

} There seems to be something hardcoded for index.html, but i dont have that as you can see in my pages elements. Shouldn`t it use the template variable of vue config pages element ?

mmusket commented 5 years ago

I'm running into a similar issue. I converted my website to a multi page setup and this plugin stopped working in the same line.

I still have public/index.html but it still crashes for the same reason.

mmusket commented 5 years ago

In multi page mode vue creates different objects for every 'page'

I noticed I have

'html-index' => [Object],
'html-app' => [Object],

rather than just html

changing the line

config.plugin("html").tap(args => {

to

config.plugin("html-index").tap(args => {

allows to the plugin to keep working, although I am unsure at what side effect problems it creates. I suspect that if you want to prerender view from different pages the plugin will not work at this stage.

Cookizza commented 5 years ago

Any update on this? The change above works but why is it needed?

mmusket commented 5 years ago

because the plugin expects your app to be under index. if you change your app name or have a multi page app, the plug n is unable the right webpack module? to process.

I don't know a lot about the webpack process so i can't give you a more precise answer. But someone more knowledgable should create a pull request where we can pass this as a parameter in the config. or even better make the plug in handle multiple apps in one project.

SolarLiner commented 5 years ago

I'm really sorry I have not gotten any notifications for this (or any project I maintain or follow) in the past months, I'm sorry I've missed all of this.

Regarding multi-page setups, I don't really know how to approach this. I feel like this plugin was written too much with single-page in mind and don't really know how to proceed; should the plugin prerender all pages? One page only? How to make a selection of pages that is convenient enough.

I'm open to suggestions!

mmusket commented 5 years ago

Hi @SolarLiner no worries,

I am not sure how feasible my suggestion is but I think that vue cli parcels every page as its own object while processing in webpack. In fact you should be able to refer to them using their key name in the config.

So in theory in the prerender config renderRouters we should be able to define pages as [multi-page-keyname]/[name-of-route] and you'll have enough information to render them.

Alternatively a nested dictionary

 renderRoutes { 
[multi-page-keyName] { 
/[route] 
}
}
SolarLiner commented 5 years ago

This sounds good to me - however what should be done when not all keys are defined in renderRoutes ?

mmusket commented 5 years ago

Not sure I understand your question but in renderroutes if a route is missing you do not render it? Don't think that changes as per current implementation.

Once you go the multi page route all pages must be defined ill post my current config as an example.


  pages: {
    index: {
      entry: 'src/Website/main.js',
      template: 'public/index.html',
      filename: 'index.html',
      title: 'Brandollo Website',
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    plantool: {
      entry: 'src/App/main.js',
      template: 'public/app-index.html',
      filename: 'app/index.html',
      title: 'Brandollo App',
      chunks: ['chunk-vendors', 'chunk-common', 'plantool']
    },
  },

So with the proposed changes renderroutes would look something like this

  renderRoutes: [        
        "index/landing",
        "index/product",
        "plantool/free",
         "plantool/other"
]

or

 renderRoutes: {        
       index: [ "/alt",
        "/product"] ,
        plantool: ["/free"] 
}

which ever is easier to implement :)

Thinking about it more I imagine a challenge would be to auto detect if the project is a single page or a multi page setup.

wvffle commented 5 years ago

I've occured same error when using pug template. I have /src/index.pug file and no /src/public/index.html file.

My config is as so:

  pages: {
    index: {
      entry: './src/main.js',
      template: './src/index.pug'
    }
  }
trialsNow commented 5 years ago

Didnt work for me even after this change

  config.plugin("html-index").tap(args => {
        args[0].template = api.resolve("public/index.html");
kenberkeley commented 4 years ago

Any update? https://github.com/SolarLiner/vue-cli-plugin-prerender-spa/issues/10

popcornkiller1088 commented 4 years ago

I've occured same error when using pug template. I have /src/index.pug file and no /src/public/index.html file.

My config is as so:

  pages: {
    index: {
      entry: './src/main.js',
      template: './src/index.pug'
    }
  }

yes I have the same issue as well ... any update?