question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SSR fails when split code

See original GitHub issue

Version

2.5.16

Reproduction link

https://github.com/vincent-yao27/vue-ssr-bug

Steps to reproduce

  1. Create a project with vue-cli 3.
  2. Set up SSR.
  3. Use import('path/to/component.vue') to split code.
  4. Build server bundle.
  5. Start a server to render the pages.
// vue.config.js 

const SSRServerPlugin = require('vue-server-renderer/server-plugin')
const nodeExternals = require('webpack-node-externals')

module.exports = {
	configureWebpack: {
		entry: './src/entry-server',
		target: 'node',
		devtool: 'source-map',
		output: {
			libraryTarget: 'commonjs2'
		},
		externals: nodeExternals({ whitelist: /\.css$/ }),
		optimization: {
			splitChunks: false
		},
		plugins: [new SSRServerPlugin()],
	}
}


// router.js

import Vue from 'vue'
import Router from 'vue-router'
import About from './views/About.vue'

Vue.use(Router)

export function createRouter() {
  return new Router({
    mode: 'history',
    routes: [
      {
        path: '/',
        name: 'home',
        component: () => import('./views/Home.vue')
      },
      {
        path: '/about',
        name: 'about',
        component: About
      }
    ]
  })
}


// main.js

import Vue from 'vue'
import App from './App.vue'
import { createRouter } from './router'

Vue.config.productionTip = false

export function createApp() {
  const router = createRouter()

  const app = new Vue({
    router,
    render: h => h(App)
  })

  return { app, router }
}


// entry-server.js

import { createApp } from './main'

export default (context) => new Promise((resolve, reject) => {
	const { app, router } = createApp()

	router.push(context.url)

	router.onReady(() => {
		const matchedComponents = router.getMatchedComponents()
		if (!matchedComponents.length) {
			return reject({ code: 404 })
		}
		resolve(app)
	}, reject)
})


// server.js

const express = require('express')
const { createBundleRenderer } = require('vue-server-renderer')

const app = express();
const bundle = require('./dist/vue-ssr-server-bundle.json')

const renderer = createBundleRenderer(bundle, {
	runInNewContext: false,
})

app.get('*', (req, res) => {
	const context = { url: req.url }
	renderer.renderToString(context, (err, html) => {
		if (err) console.error(err)
		res.end(html)
	})
})

app.listen(3000)

What is expected?

Render path /, /about successfully.

What is actually happening?

  1. Get ReferenceError: document is not defined when path / is rendered.
  2. Render path /about successfully.
  3. After deleting configureWebpack.optimization.splitChunks in vue.config.js, it shows an Error: Server-side bundle should have one single entry file. Avoid using CommonsChunkPlugin in the server config during building.

system: OS X 10.11.6 node: 8.11.3 vue-server-renderer: 2.5.16 webpack: 4.15.1

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:20 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
fengerwoocommented, Nov 25, 2019

参考我的vue.config.js 配置文件

SSR真是坑,足足被坑了几个小时才解决 一直在报 Error: Server-side bundle should have one single entry file. Avoid using CommonsChunkPlugin in the server config.

解决方法: 注意我的第46行配置为: splitChunks: TARGET_NODE ? false : undefined node环境下必须将splitChunks才不报错

完整vue.config.js文件


//webpack 服务端、客户端插件
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 TARGET_NODE = process.env.WEBPACK_TARGET === "node"
const target = TARGET_NODE? "server": "client"

module.exports = {

    css: {
        extract: false
    },

    // 根据服务器或者客户端,编译到不同文件夹
    outputDir: './dist/'+target,

    configureWebpack: ()=>({
        // 将entry指向应用程序的 server/client 文件
        entry: `./src/entry-${target}.js`,
        // 对 bundle renderer 提供 source map支持
        devtool: 'source-map',
        // 这运行 webpack 以 Node 适用方式处理动态导入(dynamic import)
        // 并且还会在编译 Vue 组件时告知 'vue-loader' 输出面向服务器代码(server-oriented code)
        target: TARGET_NODE? 'node' : 'web',
        node: TARGET_NODE? undefined : false,
        output: {
            // 此处告知 server bundle 使用Node风格导出模块
            libraryTarget: TARGET_NODE ? "commonjs2" : undefined
        },
        //外置化应用程序依赖模块。可以使服务器构建速度更快,并生成较小的bundle文件
        externals: TARGET_NODE
            ? nodeExternals({
                // 不要外置化webpack  需要处理的依赖模块
                // 可以在这里添加更多的文件类型。例如,未处理 *.vue 原始文件
                // 你还应该将修改 `global` (例如 polyfill)的依赖模块列入白名单
                whitelist: [/\.css$/]
            })
            : undefined,
        optimization: {
            splitChunks: TARGET_NODE ? false : undefined 
        },
        // 这是将服务器的整个输出构建为单个JSON文件的插件
        // 服务端默认文件名为 `vue-ssr-server-bundle.json`
        plugins: [TARGET_NODE? new VueSSRServerPlugin(): new VueSSRClientPlugin()]
    }),

    chainWebpack: config => {
        config.module
            .rule('vue')
            .use('vue-loader')
            .tap(options => {
                merge(options, {
                    optimizeSSR: false
                })
            })
    }
}
2reactions
Gefcommented, Aug 13, 2019

chainWebpack: config => { if (process.env.NODE_ENV === 'production') { config.optimization.delete('splitChunks') } }

This is a simple option

Read more comments on GitHub >

github_iconTop Results From Across the Web

SSR fails after splitting code - Get Help - Vue Forum
I just split the code of a popular ssr example by changing 2 lines of codes, then npm run build and npm start...
Read more >
SSRS Split expression #Error - Stack Overflow
The expression is made on a textbox and I need to have this function cause our costumer requires it. I want this input...
Read more >
Why code splitting is hard in react server side rendering?
Recap to our initial problem statement, we would like to do code splitting during Server side rendering or commonly termed as SSR.
Read more >
What's the point of SSR when code splitting/lazy loading exists ...
To me, SSR and client side rendering (again especially with code splitting and lazy loading) falls under same category, unless SEO is necessary, ......
Read more >
Inside the Code Split - DEV Community ‍ ‍
The problem with SSR is a hydrate function - you have to load "everything you need", before rendering on the Client "the same...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found