L
L
LazarusNucleros2020-05-09 17:59:09
Search Engine Optimization
LazarusNucleros, 2020-05-09 17:59:09

How is SEO with multi-page apps on Vue?

Hello everyone

I am currently working on a website for an online store.
Wordpress with Woocommerce acts as a back end, I plan to use Vue on the front.
The customer started talking about SEO. And then it became sad. Because, as far as I've heard, sites that use client-side markup rendering technologies are not doing very well with SEO.

In short - how will the search robot evaluate the site page if it is entirely rendered on the client?

(the server returns only html with one element in the body).
But at the same time, no data is requested asynchronously, everything that is needed is already on the front (either "wired" directly to the front, or transferred to the front along with the markup).

Like on this site for example .
Judging by Wappalyzer, the site uses Vue.js, and if you look at the markup, it consists of components, not the usual html tags. How will such a site be indexed? After all, it is clearly impossible to see his metrics.

Thank you all in advance for your replies.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Dima Pautov, 2020-05-09
@bootd

SSR and everything will be fine

V
Vladimir Korotenko, 2020-05-09
@firedragon

As an example of prerendering, put here what needs to be indexed

// vue.config.js
var path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
    configureWebpack: {
        module: {
            rules: [
                {
                    test: /\assets\/.*.css$/i,
                    use: ['style-loader', 'css-loader'],
                },
            ],
        },
        plugins: [
            new BundleAnalyzerPlugin(),
            new PrerenderSPAPlugin({
                // Required - The path to the webpack-outputted app to prerender.
                staticDir: path.join(__dirname, 'dist'),

                // Optional - The path your rendered app should be output to.
                // (Defaults to staticDir.)
                outputDir: path.join(__dirname, 'prerendered'),

                // Optional - The location of index.html
                indexPath: path.join(__dirname, 'dist', 'index.html'),

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

                // Optional - Allows you to customize the HTML and output path before
                // writing the rendered contents to a file.
                // renderedRoute can be modified and it or an equivelant should be returned.
                // renderedRoute format:
                // {
                //   route: String, // Where the output file will end up (relative to outputDir)
                //   originalRoute: String, // The route that was passed into the renderer, before redirects.
                //   html: String, // The rendered HTML for this route.
                //   outputPath: String // The path the rendered HTML will be written to.
                // }
                postProcess(renderedRoute) {
                    // Ignore any redirects.
                    renderedRoute.route = renderedRoute.originalRoute;
                    // Basic whitespace removal. (Don't use this in production.)
                    renderedRoute.html = renderedRoute.html.split(/>[\s]+</gmi).join('><')
                    // Remove /index.html from the output path if the dir name ends with a .html file extension.
                    // For example: /dist/dir/special.html/index.html -> /dist/dir/special.html
                    if (renderedRoute.route.endsWith('.html')) {
                        renderedRoute.outputPath = path.join(__dirname, 'dist', renderedRoute.route);
                    }

                    return renderedRoute;
                },

                // Optional - Uses html-minifier (https://github.com/kangax/html-minifier)
                // To minify the resulting HTML.
                // Option reference: https://github.com/kangax/html-minifier#options-quick-reference
                minify: {
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    decodeEntities: true,
                    keepClosingSlash: true,
                    sortAttributes: true
                },

                // Server configuration options.
                server: {
                    // Normally a free port is autodetected, but feel free to set this if needed.
                    port: 8001
                },

                // The actual renderer to use. (Feel free to write your own)
                // Available renderers: https://github.com/Tribex/prerenderer/tree/master/renderers
                renderer: new Renderer({
                    // Optional - The name of the property to add to the window object with the contents of `inject`.
                    // injectProperty: '__PRERENDER_INJECTED',
                    // Optional - Any values you'd like your app to have access to via `window.injectProperty`.
                    //  inject: {
                    //    foo: 'bar'
                    // },

                    // Optional - defaults to 0, no limit.
                    // Routes are rendered asynchronously.
                    // Use this to limit the number of routes rendered in parallel.
                    maxConcurrentRoutes: 4,

                    // Optional - Wait to render until the specified event is dispatched on the document.
                    // eg, with `document.dispatchEvent(new Event('custom-render-trigger'))`
                    // renderAfterDocumentEvent: 'custom-render-trigger',

                    // Optional - Wait to render until the specified element is detected using `document.querySelector`
                    // renderAfterElementExists: 'my-app-element',

                    // Optional - Wait to render until a certain amount of time has passed.
                    // NOT RECOMMENDED
                    // renderAfterTime: 5000, // Wait 5 seconds.

                    // Other puppeteer options.
                    // (See here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)
                    headless: true //  было false Display the browser window when rendering. Useful for debugging.
                })
            })
        ]
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question