vuejs / vue2-ssr-docs

Vue.js Server-Side Rendering Guide (for Vue 2)
565 stars 239 forks source link

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

Open yurshery opened 5 years ago

yurshery commented 5 years ago

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>
  2. 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' }, }, ];


 3. 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);
    });
});
4. 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 commented 5 years ago

@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