Comprehensive guide for SSR (Server-Side Rendering) in Vue 2. Live at v2.ssr.vuejs.org.
The latest SSR guide for Vue 3, see Vue 3 docs.
This site is powered by VuePress.
yarn
yarn dev
Vue.js Server-Side Rendering Guide (for Vue 2)
Comprehensive guide for SSR (Server-Side Rendering) in Vue 2. Live at v2.ssr.vuejs.org.
The latest SSR guide for Vue 3, see Vue 3 docs.
This site is powered by VuePress.
yarn
yarn dev
制作webapp过程中,通常只有一个入口。入口处做ssr服务器渲染,后续js包部分使用预加载功能载入
Option 2, Fetch data after the matched view is rendered, calls asyncData
in beforeMount
.
The pseudo-syntax is
if (asyncData)
asyncData()
This does not check if asyncData
was already called by the server! Thus, guided by the official docs, this leads to duplicate fetches. In the case of dynamic module registration, even to duplicate modules.
What is the suggested way around this? Could we please have some documentation here?
If this issue is unclear, I explain it in greater detail at vuejs/vue#9252, including a repro link. But it is more of a docs issue
I have been dealing with a bug wherein if two different routes render the same component then the async data is not being called and that is because of the code below in entry-client.js
` const matched = router.getMatchedComponents(to)
const prevMatched = router.getMatchedComponents(from)
// we only care about non-previously-rendered components,
// so we compare them until the two matched lists differ
let diffed = false
const activated = matched.filter((c, i) => {
return diffed || (diffed = (prevMatched[i] !== c))
})
if (!activated.length) {
return next()
}`
Eg: url are /item/start
and /item/end
they render the same component but with different data. Any reason that we have the check.
https://ssr.vuejs.org/guide/data.html#client-data-fetching
系统: mac
node 版本:6.10.3
vue 版本 :2.4.1
项目:vue-hackernews-2.0(官方 demo)
经过几千次请求测试发现,设置 runInNewContext = false 或者 'once' 会出现内存泄漏(200MB 左右)。不设置的 runInNewContext 内存就会控制的比较好(60MB)左右。
请问是 node 版本问题吗 ?
I've spent half of my workday trying to render my app on a server and didn't understand what's wrong. The problem was in MiniCssExtractPlugin because it doesn't care about SSR.
I had document is not defined
error at first. I've tried to mock document in NodeJs using JSDOM (I understood that something wrong if I need to do it) and the error has gone, but nothing just rendered, router.onReady
didn't resolve anything.
Many hours of searching later I've accidentally found some issue (can't provide a reference) where someone said that MiniCssExtractPlugin doesn't care about SSR. Then I've switched to ExtartTextPlugin and everything worked.
So please add a note about this plugin in docs.
How can I handle 404 status to render component with 404 error using SSR?
ref vuejs/vuex#1214
It maybe good if we have a docs for how to declare asyncData
in TypeScript. It is not an API of any libraries, so we cannot directly declare it in any d.ts
files. I guess it would be appropriate to describe it in the SSR docs.
Hi,
I am building my app using Vue 2, and I love it, but I see that I will need SSR on most of my pages but just by following documentation I think I am unable to finish it.
Is there any boilerplate of Vue SSR + Express + Vuex(maybe) where I could see how the structure is, how things connect and interact with each other... I would just need a hint.
Looking forward to receive from someone,
Regards,
Cheers!
Hi there,
First of all, wonderful work on the docs - I went through them and found them to be a pleasure to use and implement.
A point of improvement would be to give an example on:
I'd argue this would be useful for a number of reasons:
Thanks in advance, and keep up with the great work!
Scenario: Two routes; A, B. Both point to component C, which loads data based upon the name of the route. When filtering components, this means a transition from A to B will not get its component loaded.
I'm a little low on time, so don't have time for proper PR and more detailed explanation, but below is a snippet from my code we use:
// we only care about none-previously-rendered components,
// so we compare them until the two matched lists differ
// Also, if same components but different routes - we
// can't be sure we don't need to reload the data, so
// reload data in such cases (make everything differ)
let diffed = to.name !== from.name;
const activated = matched.filter((c, i) => {
return diffed || (diffed = (prevMatched[i] !== c));
})
I was wondering if there are any resources about how one might achieve code splitting for both javascript and css across routes.
Is this something that could be added to the guide? Or is it something that I should avoid doing in the first place? Or is it something that is just not clear how to do.
Any insight would be much appreciated!
Thanks for the terrific guide! It was super helpful 👍
(The only comment about this I saw in the guide is: "CSS inside async components will remain inlined as JavaScript strings and handled by vue-style-loader.")
built-server-bundle.js 文件怎么来的?
vue-ssr-server-bundle.json 文件又是怎么来的
baseConfig 里面的配置是怎样的 有示例看一下吗?
没看明白在这里webpack是怎么用的,是当做一个函数引用的还是要手动webpack把vue 文件打包一下?
文档衔接看的好突然= =
The docs say hydration takes place when the app's root element has data-server-rendered="true"
. However, it seems that the actual attribute Vue looks for is server-rendered="true"
(no data-
prefix).
@yyx990803 When we are using SSR, client will not call asyncData
at first render, then we will not be able to use registered store module because it has not been registered on client.
So, if it is as expected, registerModule
would be better to called in beforeCreate
instead of asyncData
, so that it will be registered on client at first render, of course preserveState: process.env.VUE_ENV !== 'server'
should also be used.
Following up our chat last week, it was hard to find out that hydration was also possible using vm.$mount.
Only data-server-rendered case is mentioned here https://ssr.vuejs.org/guide/hydration.html
$mount is used only as part of the explanation why it doesn’t fit but the 2nd argument (bool for hydration) is omitted.
Thanks again for the chat, I’ve been enjoying the vue.
I managed to get server side rendering work correctly, but I don't like that vue is re-drawing server rendered html. How to tell vue that its template is olready injected in html and he doesn't need to redraw?
We started the ja
(lead by @kazupon) and ko
(lead by @ChangJoo-Park) translation project with GitLocalize.
GitLocalize repository: https://gitlocalize.com/repo/62
GitHub Repository: https://github.com/open-source-translators/vue-ssr-docs
If you are interested in it, please tell us. 😉
The renderToString function of the renderer strips the <!DOCTYPE> declaration. Is there a reason for this behaviour? Can it be suppressed?
I want some unauthorized users to prevent from visiting pages on site.
I added beforeEach hook for each route that looks like
//main.js
router.beforeEach((to,from,next) => {
let authorized = store.state.user !== null;
if(to.matched.some(record => record.meta.auth === true)){
if(!authorized){
next({ name: 'Error', params: [to.path], replace: true });
}
}
next();
});
And it works for me just fine but when it comes to user side it looks like this hook work before replacing local store state with server side fetched data.
So the page always redirects me to error and I get plenty of warnings about DOM tree not matching server rendered DOM.
The only idea I have is to replace state just after creating store so createApp function will look something like this:
export function createApp() {
const store = createStore();
if(SERVER === false && window.__INITIAL_STATE__){
store.replaceState(window.__INITIAL_STATE__);
}
const router = createRouter();
router.beforeEach((to,from,next) => {
let authorized = store.state.user !== null;
if(to.matched.some(record => record.meta.auth === true)){
if(!authorized){
next({ name: 'Error', params: [to.path], replace: true });
}
}
next();
});
const app = new Vue({
router,
store,
render: h => h(App)
});
return {app, router, store};
}
But it doesn't look good. If there's a way to do it right?
I want to keep preload tags and don't want to prefetch async chunks, but I can only find the shouldPreload
options to disable preload. How could I achieve that? Thank you very much.
Hi, I've been working with vue for a while, and I like it very much, but I find documentation for vue server side rendering very bizarre. Luckily, parts of this docs helped me to make ssr work, but I need to write components in *.js
format, because when I start server it throws error that
SyntaxError: /path_to_component/home.vue: Unexpected token (1:0)
<template>
I understand that webpack passes it through vue-loader
and then injects it to the code, but when I build projects I don't have this logic and node throws error. Even when I changed imports to lazy imports, like in docs
export function createRouter () {
return new VueRouter({
mode: 'history',
routes: [
{ path: '/', name: 'index', component: ()=>import('../components/Home.vue') }
]
});
}
it didn't solved the problem.
您好,尤大,对您编写 vue-ssr 英文文档表示致敬!
之前 @dingyiming 和我组织一些人翻译了 Vue.js 2 和 vuex 2 的中文文档,之后我们还翻译了 webpack 2 文档。
对此我们很有兴趣继续翻译您编写的文档,希望能够得到您的支持,谢谢!
const Vue = require('vue')
const server = require('express')()
const { createRenderer } = require('vue-server-renderer')
const renderer = createRenderer()
server.get('*',(req, res) => {
const app = new Vue({
template: require('fs').readFileSync('./index.template.html', 'utf-8')
})
const context = {
title: 'hello',
meta:`
<meta name='keywords' content='xxx'>
<meta name="author" content="jzg,[email protected]">
`
}
renderer.renderToString(app, context, (err, html) => {
if (err) {
console.log(err)
res.status(500).end('Internal server error\n'+err)
return
}
console.log(html)
res.end(html)
})
})
server.listen(8080)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon">
<title>{{ title }}</title>
{{{ meta }}}
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
Internal server error
Error:
Error compiling template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon">
<title>{{ title }}</title>
{{{ meta }}}
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
- invalid expression: Unexpected token ) in
"\n\t"+_s({ meta)+"}\n"
Raw expression: {{{ meta }}}
(found in <Root>)
There are likely going to be many uses who are not already familiar with webpack as there are a number of other bundling options and users are likely to choose one and run with it. Given that this documentation is reliant on webpack, it should include the basic documentation for configuring webpack that it assumes users already have
Hi, I'm the translation leader of the Vue.js brazilian community. We're aiming to translate this SSR documentation and already started doing it as a fork, but it would make far more sense to do it right here. Could you please create the pt-br
folder inside the docs
folder and assign it to me in GitLocalize?
when I use the code: vue run build in the cmd, I always get warnings:
help wanted!!! thank you!
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "E:\Program Files\nodejs\node.exe" "E:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "run" "build"
npm ERR! node v6.11.3
npm ERR! npm v3.10.10
npm ERR! missing script: build
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR! https://github.com/npm/npm/issues
npm ERR! Please include the following file with any support request:
npm ERR! E:\leaflet\npm-5.4.2\npm-debug.log
This document descibing data pre-fetching about the components whitch router.getMatchedComponents
But how about the sub components those belong the matched components,
how to load pre-fetching data with these components?
最近使用 webpack 4 配置 ssr 环境,发现一个奇怪的问题:
当使用 mini-css-extract-plugin 这个插件的时候,如果 在 vue-router 中配置 动态加载的形式
export default [
{
path: '/',
component: () => import(/* webpackChunkName: "index" */ '../views/index.vue')
},
{
path: '/login',
component: () => import(/* webpackChunkName: "login" */ '../views/login.vue')
}
]
那么只要在其中人一个.vue文件中中写 css 样式,那么在访问页面的时候就会报错:document is not defined
打开 vue-ssr-server-bundle.json 文件发现 有很多地方使用了 document
于是 就尝试着换回 [email protected],但是又出现,打包的时候会生成一个 manifest 的空 css 文件,不知如何解决。
我使用的是自己配置的环境,地址在 https://github.com/Maxlasting/vue-ssr-template
请问,能否给一个 基于 webpack 4 的 ssr 示例,或者帮我解决一下上面的问题,非常感谢。
引进第三方依赖,便会报此错误
不知如何解决
In open source community, translation is important but it is very difficult so we are creating localization tool to help translated ones updated as well. 💯 Its name is GitLocalize. The reason that we built it was translation problem of Node.js.
It have been used in "forked GitHub - vuejs/vue-ssr-docs, GitLocalize - vuejs/vue-ssr-docs". Japanese team are translating it into Japanese now. So I think it is a time to try our service in original vue-ssr-docs community. We provide these features below:
Looking forward to hearing your thoughts 😄
cc:/ @kazupon @yyx990803
hey guys, i need some help.
Trying to do import store from './vuex/index'
something like that in a external file, so that i can do store.commit any where i want.
but with the new pattern, store/router are created by a factory function. which make the import store not work.
anyone can offer some help would be appreciate, thx!!
中文文档,
构建配置的客户端配置章节中,
使用代码分割特性构建后的服务器渲染的 HTML 代码,
第七行注释,prefetch 笔误为 preload,
望修正。
I hope it can offer a pdf book. I think it's more convenient.
I'm Using vue-ssr version^2.5.9 and set comments:true at Root vue (App.vue),but it seems not work.Has anybody ever met such problem? Has any suggestions? thank you very much~
In code example server.js, there is a 404 error in renderToString's cb,
// server.js
const createApp = require('/path/to/built-server-bundle.js')
server.get('*', (req, res) => {
const context = { url: req.url }
createApp(context).then(app => {
renderer.renderToString(app, (err, html) => {
if (err) {
if (err.code === 404) {
res.status(404).end('Page not found')
} else {
res.status(500).end('Internal Server Error')
}
} else {
res.end(html)
}
})
})
})
But in entry-server.js, the 404 error is in reject
// entry-server.js
import { createApp } from './app'
export default context => {
// since there could potentially be asynchronous route hooks or components,
// we will be returning a Promise so that the server can wait until
// everything is ready before rendering.
return new Promise((resolve, reject) => {
const { app, router } = createApp()
// set server-side router's location
router.push(context.url)
// wait until router has resolved possible async components and hooks
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
// no matched routes, reject with 404
if (!matchedComponents.length) {
return reject({ code: 404 })
}
// the Promise should resolve to the app instance so it can be rendered
resolve(app)
}, reject)
})
}
I wonder if there is a mistake in this example?
I am having this problem of having 2 client bundles in the SSR generated html.
<script src="/client.js" defer></script> <script src="/register.js" defer></script> <script type="text/javascript" src="/client.js"></script>Register is another bundle lazy loaded by vue-router
As expected the deferred one runs later resulting everything to happen twice.
Here's the client manifest except modules
"publicPath": "/", "all": [ "logout.js", "about.js", "home.js", "location.js", "login.js", "client.js", "register.js", "0.js", "1.js", "manifest.js", "index.html" ], "initial": [ "client.js" ],
"vue-server-renderer": "^2.5.16",
"vue-loader": "^15.2.4",
"vue-router": "^3.0.1",
node 8.11.2
Most likely I am missing something but can't figure it out.
Hi guys, Im currently refactoring an app and converting all my base code into vue. One of my requirements is to do server side rendering.
I have been follow vue ssr example along with hacker news example to help me understand ssr.
I do have however a question for which I cant find any good answer, and before further development, I want to make sure we are doing the right thing.
I want to know if its a good practice to have some actions in a vue store calling an api for server side rendering.
All the examples I have found deal with a real external endpoint they connect and perform request. But that is not the setup we have.
We do have a "normal" express app with its own endpoints; so, for example, express router looks a bit like this:
// This is our post model, it lives on the same app, so its not a external API
app.get('/posts', (req, res) => Posts.getPosts());
// Resolve request for SSR rendering, pretty much the same as in [vue ssr example](https://ssr.vuejs.org/guide/routing.html#routing-with-vue-router)
app.get(
const context = { url: req.url }
createApp(context).then(app => {
renderer.renderToString(app, (err, html) => {
if (err) {
if (err.code === 404) {
res.status(404).end('Page not found')
} else {
res.status(500).end('Internal Server Error')
}
} else {
res.end(html)
}
})
})
);
This part works fine on both client and server. If you request something to /posts you get your response back.
To have a more modular code, we are using vuex stores; being one of the actions called fetchPosts and this action is the responsible of fetching the current posts in the view.
...
actions: {
fetchPosts({ commit }) {
return $axios.get('/posts').then((response) => {
commit('setPosts', {
posts: response.data
});
});
}
},
...
I believe for client side this is good, but when rendering on the server, this is probably not optimal.
Reason being axios performing an actual http request, which will also have to implement auth mechanism, and in general, really poor performant.
My question is: is this the recommended and standard way of doing this ?
What are other possibilities that works in server and client ?
Do people actually creates separated apps for api and rendering app ?
Thanks !
There are a lot of concepts introduced in this manual, but for most of it actually getting it to run is waved aside until Bundle Rendering. If something doesn't work when we get to that stage, it's hard to work backwards to figure what exactly was the cause of the break. Introducing bundling earlier to get the server running and then continuing on with the other concepts will allow a user's knowledge to grow with working code.
Hello,
At this point https://ssr.vuejs.org/guide/#using-a-page-template, where do you pass the context object, how does it get that message
data in the component?
const renderer = createRenderer({
template: require('fs').readFileSync('./index.html', 'utf-8'),
});
const context = {
message: 'Esto es otro',
};
app.message = 'Hello';
renderer.renderToString(app, context, (err, html) => {
return res.status(200).send(html);
});
After searching for a few hours, I was able to get the data through the parent
, is it the right way, or is there another way?
<template>
<div class="greeting">Esto es un mensaje 1233 - {{message}} </div>
</template>
<style lang="css">
.greeting {
font-size: 20px;
color:red !important;
}
</style>
<script>
export default {
created() {
this.message = this.$parent.message; //Grab this data from the parent
}
};
</script>
在renderer中使用了template, 但是在client.js中window.__INITIAL_STATE__为undefined
Hi, i dont know if it is the apropiate site to issue this problem but I didnt where to issue this.
My problem is that when I run webpack --config bundler/webpack/webpack-server.config.js for get the bundle of entry server the build process throws me this error:
/home/raul/Documentos/Workshop/vuejs website template/node_modules/vue-server-renderer/server-plugin.js:58
throw new Error(
^
Error: Server-side bundle should have one single entry file. Avoid using CommonsChunkPlugin in the server config.
at Compiler.<anonymous> (/home/raul/Documentos/Workshop/vuejs website template/node_modules/vue-server-renderer/server-plugin.js:58:13)
at Compiler.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:206:13)
at Compiler.emitAssets (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compiler.js:358:8)
at onCompiled (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compiler.js:244:9)
at applyPluginsAsync.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compiler.js:514:14)
at next (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:202:11)
at Compiler.<anonymous> (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/CachePlugin.js:78:5)
at Compiler.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:206:13)
at compilation.seal.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compiler.js:511:11)
at Compilation.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:195:46)
at self.applyPluginsAsync.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:671:19)
at Compilation.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:195:46)
at self.applyPluginsAsync.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:662:11)
at Compilation.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:195:46)
at self.applyPluginsAsync.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:657:10)
at Compilation.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:195:46)
at sealPart2 (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:653:9)
at Compilation.applyPluginsAsyncSeries (/home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:195:46)
at Compilation.seal (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:596:8)
at applyPluginsParallel.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compiler.js:508:17)
at /home/raul/Documentos/Workshop/vuejs website template/node_modules/tapable/lib/Tapable.js:289:11
at _addModuleChain (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:498:11)
at processModuleDependencies.err (/home/raul/Documentos/Workshop/vuejs website template/node_modules/webpack/lib/Compilation.js:468:14)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
I dont know what to do... Watching the documentation doesn't helps me...
This are the webpacks files:
webpack-base.config.js
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// enable CSS extraction
extractCSS: isProduction
}
},
{
test: /\.css$/,
// important: use vue-style-loader instead of style-loader
use: isProduction
? ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
: ['vue-style-loader', 'css-loader']
}
// ...
]
},
plugins: [
// it is common to extract deps into a vendor chunk for better caching.
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// a module is extracted into the vendor chunk when...
return (
// if it's inside node_modules
/node_modules/.test(module.context) &&
// do not externalize if the request is a CSS file
!/\.css$/.test(module.request)
)
}
}),
// extract webpack runtime & manifest
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest'
}),
]
};
webpck-server.config.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./webpack-base.config.js')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const nodeExternals = require('webpack-node-externals')
module.exports = merge(baseConfig, {
// Point entry to your app's server entry file
entry: __dirname + '/../entries/entry-server.js',
// This allows webpack to handle dynamic imports in a Node-appropriate
// fashion, and also tells `vue-loader` to emit server-oriented code when
// compiling Vue components.
target: 'node',
// For bundle renderer source map support
devtool: 'source-map',
// This tells the server bundle to use Node-style exports
output: {
libraryTarget: 'commonjs2',
filename: '[name].bundle.js',
path: __dirname + '/../../server-bundles/'
},
// https://webpack.js.org/configuration/externals/#function
// https://github.com/liady/webpack-node-externals
// Externalize app dependencies. This makes the server build much faster
// and generates a smaller bundle file.
externals: nodeExternals({
// do not externalize dependencies that need to be processed by webpack.
// you can add more file types here e.g. raw *.vue files
// you should also whitelist deps that modifies `global` (e.g. polyfills)
whitelist: /\.css$/
}),
// This is the plugin that turns the entire output of the server build
// into a single JSON file. The default file name will be
// `vue-ssr-server-bundle.json`
plugins: [
new VueSSRServerPlugin()
]
})
webpack-client.config.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const nodeExternals = require('webpack-node-externals')
const baseConfig = require('./webpack-base.config.js')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
module.exports = merge(baseConfig, {
entry: __dirname + '/../entries/entry-client.js',
output: {
filename: '[name].bundle.js',
path: __dirname + '/../../assets/'
},
plugins: [
// Important: this splits the webpack runtime into a leading chunk
// so that async chunks can be injected right after it.
// this also enables better caching for your app/vendor code.
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
minChunks: Infinity
}),
// This plugins generates `vue-ssr-client-manifest.json` in the
// output directory.
new VueSSRClientPlugin()
]
})
Please help =)
is there a demo project using vue & vue-server-renderer >= 2.3.0
?
vue.runtime.esm.js:559 TypeError: Cannot read property 'runtime' of undefined
at ModuleCollection.unregister (vuex.esm.js:213)
at Store.unregisterModule (vuex.esm.js:450)
at VueComponent.destroyed (app.js:27)
at callHook (vue.runtime.esm.js:2697)
at VueComponent.Vue.$destroy (vue.runtime.esm.js:2511)
at destroy (vue.runtime.esm.js:3604)
at invokeDestroyHook (vue.runtime.esm.js:5335)
at invokeDestroyHook (vue.runtime.esm.js:5340)
at invokeDestroyHook (vue.runtime.esm.js:5340)
at invokeDestroyHook (vue.runtime.esm.js:5340)
I think this is due to the fact that we are trying to deregister the storage module, which was registered only on the server.
That is, first need to check whether there is such a module, and only then try to delete it.
I have several reusable components which have been bundled by webpack to umd
and published to npm
. Now they can not support SSR, is there any document for me?
Hi,
I try to get SSR working with Vuex Getters without any luck. I don't get any markup pre-rendered when I have a computed property with getters
export default {
computed: {
articles() {
// return this.$store.getters.articles; // this works but all my articles are rendered at client
return this.$store.state.articles[this.$store.state.tag]; // this works and gets pre-rendered
}
},
asyncData ({ store }) {
return store.dispatch('FETCH_ARTICLES');
},
}
My getters.js looks like this:
export default {
articles (state) {
const { articles, tag } = state
return articles[tag];
},
}
Am I missing something or is this expected behaviour?
I am working an isomorphic app with Vue.js , and having an issue where the returned page does not result in hydratable nodes in a very specific (and odd) way. One example of this is:
The page source is (as pulled from the chrome source window):
<div class="col-xs-10 col-sm-6 col-md-8"><a class="logo"></a><h3 class="padlock-title main-heading-font heading3"><span class="padlock-icon"><i class="fa fa-lock"></i></span><span class="title-text">Checkout</span></h3></div>
The vue error set is (as pulled from console):
Parent: <div class="col-xs-10 col-sm-6 col-md-8"><a class="logo"></a><h3 class="padlock-title main-heading-font heading3">…</h3></div>
vue.js:6028 Mismatching childNodes vs. VNodes:
NodeList(2)
0: a.logo
1: h3.padlock-title.main-heading-font.heading3
length: 2
__proto__: NodeList
Array(3)
0: VNode {tag: "a", data: {…}, children: undefined, text: undefined, elm: a.logo, …}
1: VNode {tag: undefined, data: undefined, children: undefined, text: " ", elm: text, …}
2: VNode {tag: "h3", data: {…}, children: Array(3), text: undefined, elm: h3.padlock-title.main-heading-font.heading3, …}
length: 3
__proto__: Array(0)
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
And the resulting bailed hydration HTML is...
<div class="col-xs-10 col-sm-6 col-md-8"><a href="//0.0.0.0:8000" class="logo"></a> <h3 class="padlock-title main-heading-font heading3"><span class="padlock-icon"><i class="fa fa-lock"></i></span> <span class="title-text">Checkout</span></h3></div>
Digging into the error itself, we find we reach it at line 5974 of vue.js :
if (!assertNodeMatch(elm, vnode, inVPre))
where it tries to compare node 1 of the Array above, to node 1 of the NodeList above, finds them not the same, and bails out. (Notably, it sees the Node as type 1, and the VNode as of type 3. The EXTRA weird thing is that the VNode in question says that its 'elm' at the time is the h3 tag, but otherwise is an empty super undefined text tag.)
Another interesting piece of weirdness is that I can manage to make this error disappear, sometimes, by removing line returns from the HTML file used for rendering (these are not single file components, they are requires), however, not every line return ends up causing this error, only some of them. Node is doing the server-side rendering work (v10.9.0) , vue 2.5.17, vue-server-renderer ^2.5.17.
So the question here is: what, exactly, is going on? Has anyone run into something that looks like this?
It is not immediately apparent that each store module needs to be a function that returns a fresh module, which needs to be combined with other store modules when the root store is created afresh.
The above sentence is really confusing. See discussion here to understand what I mean:
https://forum.vuejs.org/t/debugging-state-pollution-with-the-new-behaviour-of-vue-2-3-ssr/11724
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.