Code Monkey home page Code Monkey logo

vue2-ssr-docs's Introduction

vue2-ssr-docs

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.

Development

This site is powered by VuePress.

yarn
yarn dev

vue2-ssr-docs's People

Contributors

alex-sokolov avatar changjoo-park avatar chikathreesix avatar chrisvfritz avatar dear-lizhihua avatar dependabot[bot] avatar ifwu avatar jbruni avatar jinjiang avatar kazupon avatar lvjinlong avatar machinisteweb avatar metapragma avatar miixc avatar mizumaki avatar morkro avatar mstaack avatar munierujp avatar obertrand avatar olayinkaos avatar pi0 avatar reed-jones avatar riophae avatar rkunev avatar ryotabannai avatar snugug avatar sotayamashita avatar uiuifree avatar ulivz avatar yyx990803 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue2-ssr-docs's Issues

ssr + client only

制作webapp过程中,通常只有一个入口。入口处做ssr服务器渲染,后续js包部分使用预加载功能载入

Client data fetching in beforeMount mixin double-fetches

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

How to call async data if the rendered component is the same but with a different ID

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

设置 runInNewContext 出现内存泄漏

系统: mac
node 版本:6.10.3
vue 版本 :2.4.1
项目:vue-hackernews-2.0(官方 demo)

经过几千次请求测试发现,设置 runInNewContext = false 或者 'once' 会出现内存泄漏(200MB 左右)。不设置的 runInNewContext 内存就会控制的比较好(60MB)左右。

请问是 node 版本问题吗 ?

Add info about MiniCssExtractPlugin

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.

404 page

How can I handle 404 status to render component with 404 error using SSR?

vue ssr express boilerplate

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!

Cookies and LocalStorage: provide a basic example

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:

  • how to handle setting and getting localStorage.
  • how to handle setting and getting a cookie.

I'd argue this would be useful for a number of reasons:

  • There seems to be a general lack of documentation about this issue, resulting in a number of unanswered questions in the forum, such as these: example 1, example 2
  • Most sites that require the complexity of SSR probably also require handling login/authentication management.

Thanks in advance, and keep up with the great work!

Data pre fetch: When resolving which components not to render, we need to consider the same component in different routes

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));
})

Question: Code Splitting and CSS

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 文件打包一下?
文档衔接看的好突然= =

data-server-rendered="true"

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).

`registerModule` would be better to called in `beforeCreate` instead of `asyncData`

@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.

Prevent overwriting html.

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?

Replace state on client happens after beforeEach router hook

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?

How could I disable prefetch injection?

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.

Cannot import *.vue files with ssr

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.

Using a Page Template Interpolation,it's error,help please!

My code:

  1. index.js
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)
  1. index.template.html
<!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>

Error code:

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>)

How to deal it?

Don't Assume Previous Webpack Knowledge

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

Create Brazilian Portuguese translation on GitLocalize

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?

vue run build

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

使用mini-css-extract-plugin服务端报错document is not defined

最近使用 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 示例,或者帮我解决一下上面的问题,非常感谢。

Need translation workflow?

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:

  • Have a split view to make people translate
  • When original one is updated, we will notify translators
  • Translation flow looks like a GitHub flow:
    1. Sync GitHub and GitLocalize
    2. Translate
    3. Create a review request such as Pull Request of GitHub
    4. GitLocalize will create pull request to GitHub repository
    5. And merge. That's it ✨

Looking forward to hearing your thoughts 😄

cc:/ @kazupon @yyx990803

how to access store instance in external file with new factory pattern

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!!

A spell mistake in zh‘s doc, hope to fix it.

中文文档,
构建配置的客户端配置章节中,
使用代码分割特性构建后的服务器渲染的 HTML 代码,
第七行注释,prefetch 笔误为 preload,
望修正。

Why set comments:true not working?

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~

Mistake in section #routing-with-vue-router code example

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?

Client bundle injected twice

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.

SSR/store code organization

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 !

Get to working code faster

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.

Accessing the context data

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>

I am having problems on building the entry-server.js

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 =)

example request

is there a demo project using vue & vue-server-renderer >= 2.3.0 ?

Error during first move to another route

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.

Vuex getters doesn't get pre-rendered

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?

Vue SSR in node not creating hydratable components

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.