Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue + Laravel && SSR + Code-splitting == is real? #238

Open
yurshery opened this issue Apr 16, 2019 · 1 comment
Open

Vue + Laravel && SSR + Code-splitting == is real? #238

yurshery opened this issue Apr 16, 2019 · 1 comment

Comments

@yurshery
Copy link

yurshery commented Apr 16, 2019

I have an app with Vue+Vuex+Vue-router and Laravel+spatie/laravel-server-side-rendering.

It works well with SSR and it renders well to:

  1. app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Test SSR</title>
    <link href="{{ mix('/atd/css/main.css') }}" type="text/css" rel="stylesheet">
    <script>window.ssrData = @json($data);</script>
    <script defer src="{{ mix('atd/js/app-client.js') }}"></script>
</head>
<body>
    {!!
        ssr('atd/js/app-server.js')
            ->context(['data' => $data])
            ->fallback('<div id="app"></div>')
            ->render()
    !!}
</body>
</html>
  1. routes
import HomePage from '../../pages/HomePage';
import Page404 from '../../pages/Page404';
import AppMainHeader from '../../components/layout/AppMainHeader';
import AppMainFooter from '../../components/layout/AppMainFooter';

export default [
    {
        path: '/',
        name: 'HomePage',
        components: {
            default: HomePage,
            'main-header': AppMainHeader,
            'main-footer': AppMainFooter,
        },
    },
    {
        path: '/404',
        name: 'Page404',
        component: Page404,
    },
    {
        path: '*',
        redirect: { name: 'Page404' },
    },
];
  1. app-server.js
/* eslint-disable */
import app from './app';
import router from './router';
import store from './store';
import renderVueComponentToString from 'vue-server-renderer/basic';

new Promise((resolve, reject) => {
    router.push(context.url);

    store.commit('ssrData', context.data);

    router.onReady(() => {
        const matchedComponents = router.getMatchedComponents();

        if (!matchedComponents.length) {

            return reject({ code: 404 });
        }
        resolve(app);

    }, reject);
})
    .then((app) => {
        renderVueComponentToString(app, (err, html) => {
            if (err) {
                throw new Error(err);
            }

            dispatch(html);
        });
    });
  1. webpack.mix.js
const mix = require('laravel-mix');
const path = require('path');

const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const imageminMozjpeg = require('imagemin-mozjpeg');

mix.js('resources/atd/app-client.js', 'public/atd/js')
    .js('resources/atd/app-server.js', 'public/atd/js')
    // .sourceMaps()
    .options({
        extractVueStyles: 'public/atd/css/main.css',
    })
    .browserSync({
        proxy: 'ssr-test.loc',
        open: false,
        files: 'public/atd',
    })
    .webpackConfig({
        resolve: {
            alias: {
                vue$: 'vue/dist/vue.common.js',
            },
        },
        module: {
            rules: [
                {
                    test: /\.pug$/,
                    loader: 'pug-plain-loader',
                },
            ],
        },
        plugins: [
            new SVGSpritemapPlugin('resources/atd/assets/svg/**/*.svg', {
                output: {
                    filename: 'atd/svg/icon-sprite.svg',
                    // svg4everybody: false,
                    svgo: {
                        plugins: [
                            {
                                removeTitle: true,
                            },
                            {
                                removeAttrs: {
                                    attrs: '(stroke|fill)',
                                },
                            },
                        ],
                    },
                },
                sprite: {
                    generate: {
                        symbol: '-',
                        use: true,
                        view: true,
                    },
                },
                styles: path.join(__dirname, 'resources/atd/assets/sass/sprites.scss'),
            }),
            new CopyWebpackPlugin([
                {
                    from: 'resources/atd/assets/images',
                    to: 'atd/images',
                },
            ]),
            new ImageminPlugin({
                test: /\.(jpe?g|png|gif)$/i,
                disable: process.env.NODE_ENV !== 'production', // Disable during development
                plugins: [
                    imageminMozjpeg({
                        quality: 65,
                    }),
                ],
            }),
        ],
    });

// Production mode
if (mix.inProduction()) {
    mix.version(['public/atd/images', 'public/atd/svg']);
}

But if I try to do it with lazy-load with the same code only routes changed for code-splitting:

import HomePage from '../../pages/HomePage';
import AppMainHeader from '../../components/layout/AppMainHeader';
import AppMainFooter from '../../components/layout/AppMainFooter';

export default [
    {
        path: '/',
        name: 'HomePage',
        components: {
            default: HomePage,
            'main-header': AppMainHeader,
            'main-footer': AppMainFooter,
        },
    },
    {
        path: '/404',
        name: 'Page404',
        // LAZY LOAD MODEL
        component: () => import('../../pages/Page404'),
    },
    {
        path: '*',
        redirect: { name: 'Page404' },
    },
];

It always use fallback ssr('atd/js/app-server.js')->context(['data' => $data])->fallback('<div id="app"></div>')->render() with app-client.js and I don’t have SSR…
Is it real to do code-splitting with SSR?

@sentiasa
Copy link

sentiasa commented Oct 8, 2019

@yurshery did you find a solution?

Update: This is how I solved it. - https://stackoverflow.com/questions/58216963/lazy-loaded-vue-router-components-dont-work-with-ssr

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

No branches or pull requests

2 participants