Skip to content

[SSR] Lazy loading view not working when style block is present in component #285

Open
@DeLandtsheerTijl

Description

@DeLandtsheerTijl

I'm implementing SSR in an existing project, and I have been stuck on lazy loading. I created a clean vue project, to pin down the problem.

I noticed lazy loading only worked on certain pages, that had no style blocks in the template.
When I import the route on top of the router.js file, the route gets resolved and there is no problem. I'm using vueconfig to configure the build process.

const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
const nodeExternals = require('webpack-node-externals');
const merge = require('lodash.merge');
const webpack = require('webpack');

const TARGET_NODE = process.env.WEBPACK_TARGET === 'node';
const target = TARGET_NODE ? 'server' : 'client';

module.exports = {
  filenameHashing: false,
  css: {
    extract: process.env.NODE_ENV === 'production',
    loaderOptions: {
      scss: {
        prependData: '@import "https://github.com/@/assets/scss/quarks/_colors.scss"; @import "https://github.com/@/assets/scss/utils/mixins/index.scss"; @import "https://github.com/@/assets/scss/quarks/_globals.scss";',
      },
    },
  },
  configureWebpack: () => ({
    entry: `./src/entry-${target}.js`,
    target: TARGET_NODE ? 'node' : 'web',
    devtool: TARGET_NODE ? 'source-map' : undefined,
    node: TARGET_NODE ? undefined : false,
    plugins: [
      TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin(),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
        'process.env.VUE_ENV': TARGET_NODE ? "'server'" : "'client'",
      }),
    ],
    externals: TARGET_NODE
      ? nodeExternals({
        whitelist: /\.(css|sass|scss)$/,
      })
      : undefined,
    output: {
      libraryTarget: TARGET_NODE ? 'commonjs2' : undefined,

    },
  }),
  chainWebpack: (config) => {
    if (TARGET_NODE) config.optimization.delete('splitChunks');
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap((options) => merge(options, {
        optimizeSSR: false,
      }));
  },
};

My router looks like this, with both lazy loaded routes. In this case About works since there are no imported components with a style block inside. Home does not works since it uses the HelloWorld component, which contains a style block.

const routes = [
  {
    path: '/',
    name: 'Home',
    component() {
      return import(/* webpackChunkName: "home" */ '../views/Home.vue');
    },
  },
  {
    path: '/about',
    name: 'About',
    component() {
      return import(/* webpackChunkName: "about" */ '../views/About.vue');
    },
  },
];

const router = new VueRouter({
  mode: 'history',
  routes,
});

export default router;

This is the output of the build:

  ..\wwwroot\js\chunk-vendors.js    122.19 KiB           41.79 KiB
  ..\wwwroot\js\main.js             4.36 KiB             2.01 KiB
  ..\wwwroot\js\home.js             3.39 KiB             1.00 KiB
  ..\wwwroot\js\about.js            0.48 KiB             0.33 KiB
  ..\wwwroot\css\main.css           0.25 KiB             0.19 KiB
  ..\wwwroot\css\home.css           0.17 KiB             0.13 KiB

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions