问题
I have such a problem, after reloading the page an error occurs."render function or template not defined in component: anonymous". I think the error is due to socket.io. What does this error do not occur on the local machine, but on the production. dev версия error
server.js
const APP_ENV = require('./.env.js')
const { Nuxt, Builder } = require('nuxt')
const app = require('express')()
let server = require('http').Server(app)
if(APP_ENV.ssl) {
const fs = require('fs')
const options = {
key: fs.readFileSync(APP_ENV.ssl_key),
cert: fs.readFileSync(APP_ENV.ssl_cert)
}
server = require('https').Server(options, app)
}
const port = process.env.PORT || APP_ENV.ws_port
const isProd = process.env.NODE_ENV === 'production'
// We instantiate Nuxt.js with the options
let config = require('./nuxt.config.js')
config.dev = !isProd
const nuxt = new Nuxt(config)
// Start build process in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
builder.build()
}
app.use(nuxt.render)
if (APP_ENV.socket) {
const io = require('socket.io')(server)
const Redis = require('ioredis')
const redis = new Redis(APP_ENV.redis.port, APP_ENV.redis.host)
redis.psubscribe(['*'])
redis.on('pmessage', function (subscribe, channel, message) {
message = JSON.parse(message)
console.log('Server: ', subscribe, channel, message.data.message)
io.emit(channel + ':' + message.event, message.data)
})
// io.on('connection', function (socket) {
// })
}
server.listen(port, function () {
console.log('Listening on Port ' + port)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
plugins/socket.io.js
``
import io from 'socket.io-client'
const socket = io(process.env.WS_URL)
export default socket
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
io/index.js
module.exports = function () {
const APP_ENV = require('../.env.js')
const server = require('http').createServer(this.nuxt.renderer.app)
// overwrite nuxt.listen()
this.nuxt.listen = (port, host) => new Promise((resolve) => server.listen(port || 3000, host || 'localhost', resolve))
// close this server on 'close' event
this.nuxt.hook('close', () => new Promise((resolve) => server.close(resolve)))
// Add `socket.io-client` in vendor
this.addVendor('socket.io-client')
if (APP_ENV.socket) {
const io = require('socket.io')(server)
const Redis = require('ioredis')
const redis = new Redis(APP_ENV.redis.port, APP_ENV.redis.host)
redis.psubscribe(['*'])
redis.on('pmessage', function (subscribe, channel, message) {
message = JSON.parse(message)
console.log('Server: ', subscribe, channel, message.data.message)
io.emit(channel + ':' + message.event, message.data)
})
// io.on('connection', function (socket) {
// })
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
message/index.vue
<template>
<div class="my-messages">
<div class="container">
<div class="row">
<div class="col">
<h3>Мои сообщения</h3>
</div>
</div>
<div class="row">
<div class="col">
<div class="chat-wrap">
<div class="chat-tabs__content active">
<div class="chat-tabs">
<!--<div class="chat-tabs__item active">Входящие <span v-if="userMessage.count > 0">{{ userMessage.count }}</span></div>-->
<!--<div class="chat-tabs__item">Системные-->
<div v-for="(tab,index) in tabs" :key="index">
<div class="chat-tabs__item" @click="changeTab(index)" :class="{'chat-tabs__item active': tab.active}">{{tab.title}}
</div>
<!-- <span>1</span> -->
</div>
</div>
<div class="chats-list">
<div class="chats-list__body" data-simplebar >
<div class="">
<div class="chat-item" v-if="user.name != 'Системные' && tabs.incoming.active" @click.stop="chengeTab(index, user.id)" :class="{ active: tabUsers[index] }" v-for="(user, index) in userMessage.users" :key="index">
<div class="chat-item__ava">
<img v-if="user.user_avatar_path" :src="baseUrl + 'items-original/' + user.user_avatar_path" :alt="user.name">
<span v-else>{{ user.name[0] | uppercase }}{{ user.name[1] | uppercase }}</span>
<div v-if="user.unread > 0" class="chat-item__new-messages">{{ user.unread }}</div>
</div>
<div class="chat-item__interlocutor">
{{ user.name }}
</div>
<!--<div class="chat-item__last-messages" v-html="user.message">-->
<!--</div>-->
<div class="chat-item__data">
<!-- 13:25 -->
</div>
</div>
</div>
</div>
</div>
<div v-if="!chat_mob" class="chats">
<div class="chat-body active">
<div class="chat">
<div class="chat__header">
<div class="chat__interlocutor">
<div class="chat-back" @click="chatBack">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="14.617px" height="8px" viewBox="0 0 14.617 8" style="enable-background:new 0 0 14.617 8;" xml:space="preserve">
<path style="fill:#DDE1E6;" d="M10.585,5.447c-0.85,0-1.7,0.013-2.549-0.003C6.603,5.418,6.419,5.531,6.489,6.973
c0.008,0.158-0.011,0.312-0.052,0.468C6.303,7.95,5.766,8.159,5.32,7.867C4.009,7.009,2.699,6.15,1.388,5.291
c-0.321-0.21-0.65-0.41-0.966-0.628C-0.131,4.282-0.146,3.7,0.41,3.332C2.011,2.271,3.626,1.23,5.23,0.171
C5.909-0.278,6.516,0.224,6.49,0.896C6.48,1.153,6.489,1.41,6.489,1.667c0,0.58,0.288,0.871,0.864,0.871c2.135,0,4.269,0,6.404,0
c0.573,0,0.859,0.291,0.86,0.876c0,0.415,0.003,0.83-0.001,1.245c-0.004,0.475-0.322,0.787-0.798,0.788
C12.74,5.447,11.663,5.447,10.585,5.447z"/>
</svg>
</div>
<div v-if="chatUser && (chatUser.name != 'Системные' && tabs.incoming.active )">{{ chatUser.name }}</div>
</div>
<!-- <div class="chat__actions">
<div class="chat-menu">
<div class="chat-menu__icon" @click.prevent="show = !show">
<svg class="icon-svg icon-svg-header-chat-menu"><use xlink:href="/img/sprite.svg#header-chat-menu"></use></svg>
</div>
<ul class="chat-menu__dropdown" :class="{ show: show }">
<li>
Отключить уведомения
</li>
<li>
Очистить историю
</li>
<li>
Заблокировать контакт
</li>
</ul>
</div>
</div> -->
</div>
<div class="chat__body" data-simplebar ref="chatBody">
<!-- <pre>
{{
chatMessage
}}
</pre> -->
<div id="message-container" v-if="chatMessage !== []">
<div class="message_wrapper" v-if="checkMessage(message.sender_id) && (message.sender_id != null && tabs.incoming.active)" v-for="(message, index) in chatMessage" :key="index">
<div class="message" :class="{ 'message--to': userCurrent.id === message.sender_id, 'message--from': userCurrent.id !== message.sender_id }">
<div class="message__post-data"></div>
<div class="chat-item__ava message__ava" v-if="userByIdMessage(message.sender_id)" >
<img v-if="userByIdMessage(message.sender_id).user_avatar_path !== null" :src="baseUrl + 'items-original/' + userByIdMessage(message.sender_id).user_avatar_path" alt="" class="">
<div v-else >
<span>{{ userByIdMessage(message.sender_id).name[0] | uppercase }}{{ userByIdMessage(message.sender_id).name[1] | uppercase }}</span>
</div>
</div>
<div class="chat-item__ava message__ava" v-else>
<img v-if="userCurrent.user_avatar_path !== null" :src="baseUrl + 'items-original/' + userCurrent.user_avatar_path" alt="" class="">
<div v-else>
<span>{{ userCurrent.user_name[0] | uppercase }}{{ userCurrent.user_name[1] | uppercase }}</span>
</div>
</div>
<div class="message__text" v-html="message.message" >
</div>
</div>
<div class="chat-item__last-messages" :class="{ 'created_time_to': userCurrent.id === message.sender_id, 'created_time_from': userCurrent.id !== message.sender_id }">{{message.created_at}}</div>
</div>
</div>
</div>
<form class="chat__form">
<textarea placeholder="Введите сообщение..." @keyup.ctrl.enter="onSendMessage" v-model="message"></textarea>
<div v-html="img"></div>
<div class="chat__form-controls">
<div class="add-additions">
<label class="message_img" for="image"><img src="/img/affix.svg" alt=""></label>
<input class="img_input" id="image" type="file" accept="image/png, image/jpeg, image/gif, image/jpg" @change="uploadImg($event)">
</div>
<button @click.prevent="onSendMessage" >
<img src="/img/telega.svg" alt="">
</button>
</div>
</form>
</div>
<div class="interlocutor" v-if="chatUser">
<img
v-if="chatUser.user_avatar_path"
:src="baseUrl + 'items-original/' + chatUser.user_avatar_path"
:alt="chatUser.name"
class="interlocutor__img">
<img v-else
src="/img/avatar.svg"
:alt="chatUser.name"
class="interlocutor__img default_ava">
<div class="interlocutor__title">
{{ chatUser.name }}
</div>
<!--<ul class="interlocutor__info">-->
<!--<li>-->
<!--<span>-->
<!--<img src="/img/marker-icon.svg" alt="">-->
<!--</span>-->
<!--115280, Москва,-->
<!--ул. Ленинская слобода, д. 19-->
<!--</li>-->
<!--</ul>-->
<!--<p class="interlocutor__text">-->
<!--На сайте 5 мин., выставленно-->
<!--10 товаров. Время с момента регистрации 3 месяца.-->
<!--</p>-->
<!--<a href="#" class="btn btn--xl btn--border">-->
<!--Перейти к заказу-->
<!--</a>-->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--<div class="container" v-else>-->
<!--<div class="row">-->
<!--<div class="col">-->
<!--<h3>Сообщений нет</h3>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
</template>
<script>
const DOMAIN = process.env.API_DOMAIN
import socket from '@/plugins/socket.io'
import { mapActions, mapGetters } from 'vuex'
import api from '@/api'
export default {
middleware: 'authenticated',
data () {
return {
chat_mob: false,
contacts: true,
tabs: {
incoming: {
active: true,
title: 'Входящие'
},
systemic: {
active: false,
title: 'Системные'
}
},
virtualUser: false,
baseUrl: DOMAIN,
show: false,
tabUsers: [],
chatUser: null,
message: '',
userId: null,
test: null,
img: '',
check: false
}
},
beforeMount () {
this.getUserMessage()
if (socket) {
let base = this
socket.on(this.userCurrent.id +':new-user-message', (message) => {
base.setSocketMessage({
sender_id: message.message.from_id,
message: message.message.message
})
base.setMessageCount({
user_id: message.message.from_id
}
)
base.setUserUnreadMessage({
count: this.userCurrent.unread_messages + 1
}
)
this.scrollToBottom()
})
}
},
computed: {
...mapGetters({
getContact: 'message/getContact',
idUserMessage: 'message/id',
userMessage: 'message/userMessage',
chatMessage: 'message/chatMessage',
userByIdMessage: 'message/userByIdMessage',
userCurrent: 'user/user'
}),
activeTab () {
let index = null
if (this.idUserMessage !== null && this.userMessage !== [] && this.userMessage.users !== undefined) {
const user = this.userMessage.users.find(users => users.id === this.idUserMessage)
index = this.userMessage.users.indexOf(user)
}
return index
}
},
methods: {
...mapActions({
setUserUnreadMessage: 'user/setUserUnreadMessage',
setUsers: 'message/setUsers',
addUser: 'message/addUser',
setMessageCount: 'message/setMessageCount',
setUnread: 'message/setUnread',
getUserMessage: 'message/getUserMessage',
getChatMessage: 'message/getChatMessage',
createMessage: 'message/createMessage',
setStoreId: 'message/setStoreId',
setSocketMessage: 'message/setSocketMessage'
}),
checkMessage (id) {
if (this.idUserMessage !== null && this.userMessage !== [] && this.userMessage.users !== undefined){
const user = this.userMessage.users.find(users => users.id === id)
let index = this.userMessage.users.indexOf(user)
if(index === this.activeTab || id === this.userCurrent.id)
return true
else
return false
}
},
chatBack () {
this.chat_mob = true
this.contacts = true
console.log(123)
},
changeTab (index) {
console.log(index)
for (let key in this.tabs) {
this.tabs[key].active = false
}
this.tabs[index].active = true
},
readMessage(id) {
this.check = true
const payload = {
user_id: id
}
api.readMessage(payload)
.then(() => {
this.setUnread(payload)
})
},
chengeTab(index, id) {
if(window.innerWidth < 768) {
this.chat_mob = false
}
console.log(index, id)
this.readMessage(id)
for (let key in this.userMessage.users) {
this.tabUsers[key] = false
}
this.chatUser = this.userMessage.users[index]
this.tabUsers[index] = true
this.tabUsers.push()
this.getChatMessage({
user_id: id
})
this.setStoreId(id)
this.userId = id
this.scrollToBottom()
},
linkMessage (message) {
let reg = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/
let link = message.match(reg)
let myMessage = message
if(link){
myMessage = message.replace(link[0], '<a href ="'+link[0]+ '">'+ link[0] + '</a>')
}
return myMessage
},
async onSendMessage() {
if (this.message !== '' && this.userId > 0 || this.img !=='') {
this.message = this.linkMessage(this.message)
this.message = this.message + this.img
const payload = {
message: this.message,
id: this.userId
}
console.log(payload)
this.scrollToBottom()
this.setSocketMessage({
sender_id: this.userCurrent.id,
message: payload.message
})
await this.createMessage(payload)
this.message = ''
this.img = ''
}
},
scrollToBottom() {
this.$nextTick(() => {
let base = this
setTimeout(() => {
base.$refs.chatBody.getElementsByClassName('simplebar-scroll-content')[0].scrollTop = document.getElementById('message-container').scrollHeight
}, 500)
// console.log(document.getElementById('message-container').scrollHeight)
})
},
uploadImg (e) {
var file = e.target.files[0]
const formData = new FormData()
formData.append('image', file)
api.loadImageChat(formData)
.then(res => {
//this.img = '<br>' +'<a href="' + DOMAIN + 'message-files/' + res.body.data +'" target="_blank"><img class="load_img" src="'+ DOMAIN + 'message-files/' + res.body.data +'"></a>'
this.img = '<br>' +'<div class="load_img_wrapper"><img class="load_img" src="'+ DOMAIN + 'message-files/' + res.body.data +'"></div>'
})
},
},
watch: {
userMessage: {
handler (val) {
if(!this.check) {
this.tabUsers = []
if (val !== [] && this.userMessage) {
if (this.activeTab !== null && this.idUserMessage !== null) {
this.chengeTab(this.activeTab, this.idUserMessage)
} else if (this.userMessage.count !== undefined) {
this.chengeTab(0, this.userMessage.users[0].id)
}
if (val.users !== undefined) {
this.virtualUser = true
if(this.getContact){
if(!(val.users.find(user => user.id === this.getContact.id))){
const payload = this.getContact
this.addUser(payload)
// this.userIndex = this.userMessage.users.length - 1
this.chengeTab(this.userMessage.users.length - 1, this.getContact.id)
}
else{
let user = val.users.find(user => user.id === this.getContact.id)
this.userIndex = val.users.indexOf(user)
this.chengeTab(this.userIndex, this.userMessage.users[this.userIndex].id)
}
}
for (let key in val.users) {
let b = parseInt(key) === 0 ? true : false
this.tabUsers.push(b)
}
if(!this.getContact || !this.virtualUser) {
console.log(123)
this.chatUser = val.users[0]
}
else {
this.virtualUser = false
}
}
}
}
},
deep: true
}
}
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
回答1:
Have you checked if some component needs to be wrapped in <no-ssr>
tag?
We had similar issues where we had ssr: false
in the config file for a library component
This worked in dev mode, but not in production.
We had to wrap the component in a <no-ssr>
tag for the error to go away.
来源:https://stackoverflow.com/questions/54341251/render-function-or-template-not-defined-in-component-anonymous