I have a Nuxtjs website hosted on S3 bucket, it has multiple routes/pages. This one particular new route that I have created is throwing "Failed to execute 'appendChild' on 'Node':This node type does not support this method." (check SS below)
It is not happening on local machine and not throwing any error. Apparently, when I deploy to prod, it the app is throwing error as below SS, but cannot debug it as the code is minified and uglified while building.
The weird part is, when I'm visiting this particular route by clicking on <NuxtLink>
it is working fine, but if I'm direclty visiting route or if I click on <NuxtLink>
and reach there and reload the page, only then is this issue is coming.
You can reproduce this by following below steps:
- Visit https://stackinvest.in
- From navbar click on "stack prime", that will lead to https://stackinvest.in/prime-mutual-funds
- Once you're on stack prime page, reload the page. You will see the error.
You can also see this error if you visit https://stackinvest.in/prime-mutual-funds route directly.
The problem is there are other routes too, as you can see on Navbar on [home page]. They all are working fine if I follow above steps. (https://www.stackinvest.in/)
I've a default layout file (created by Nuxt CLI itself) layouts/default.vue
. Code is shown below:
<template>
<div ref="layout">
<app-navbar :isMobile="isMobile" @getstack="showModal = true"/>
<nuxt />
<app-download v-if="showModal" :is-mobile="isMobile" @close="showModal=false"></app-download>
</div>
</template>
<script>
import Navbar from '../components/Navbar';
import Download from '../components/Download';
export default {
name: 'Navbar',
components: {
appNavbar: Navbar,
appDownload: Download
},
data() {
return {
showModal: false,
size: Number
};
},
computed: {
isMobile() {
return this.size < 768;
}
},
mounted() {
this.size = this.$refs.layout.clientWidth;
}
};
</script>
Code components/Navbar.vue
. It does not contain any code for .removeEventListener()
. I did tried to add <client-only></client-only>
wrapper tag around <app-navbar>
tag. Nothing worked!
<template>
<nav class="nav-bar">
<div class="d-flex justify-content-center px-0 px-sm-128">
<div v-if="!isMobile" class="nav-bar-wrapper py-sm-4">
<div class="brand-logo">
<NuxtLink to="/">
<img alt="Stack Finance logo" data-not-lazy height="35px"
src="https://webstatic.stackfinance.co/website/Group 73740.svg"
>
</NuxtLink>
</div>
<div class="d-flex justify-content-center">
<div class="nav-links w-100 mr-sm-4">
<div class="nav-links-item">
<NuxtLink class="fo-link" to="/prime-mutual-funds">
stack prime
<div class="designer-line"></div>
</NuxtLink>
</div>
<div class="nav-links-item">
<NuxtLink class="fo-link gt-nav-faq" to="/faq">
faq
<div class="designer-line"></div>
</NuxtLink>
</div>
<div class="nav-links-item">
<NuxtLink class="fo-link gt-nav-blog" to="/blogs">
blog
<div class="designer-line"></div>
</NuxtLink>
</div>
</div>
<button id="nav-cta" ref="navCta" class="app-btn--sm" @click="focusSection">download stack</button>
</div>
</div>
<div v-else class="nav-bar-wrapper--mob p-3">
<div class="brand-logo">
<NuxtLink to="/">
<img alt="Stack Finance logo" data-not-lazy height="22px"
src="https://webstatic.stackfinance.co/website/Group 73740.svg"
>
</NuxtLink>
</div>
<div class="nav-links--collapsed">
<div class="menu-icon">
<input id="toggle" type="checkbox" @change="toggleMenu">
<label for="toggle"></label>
</div>
</div>
<div v-if="showMenu" class="menu-container">
<div class="nav-links-item">
<NuxtLink class="fo-link" to="/prime-mutual-funds">stack prime</NuxtLink>
</div>
<div class="nav-links-item gt-nav-faq">
<NuxtLink class="fo-link" to="/faq">faq</NuxtLink>
</div>
<div class="nav-links-item">
<NuxtLink class="fo-link gt-nav-blog" to="/blogs">blog</NuxtLink>
</div>
</div>
</div>
</div>
</nav>
</template>
<script>
export default {
name: 'Navbar',
props: {
isMobile: Boolean
},
data() {
return {
showMenu: false
};
},
methods: {
focusSection() {
this.$emit('getstack');
},
toggleMenu() {
this.showMenu = !this.showMenu;
}
}
};
</script>
<style lang="scss">
...
</style>
package.json
{
"name": "stack-web",
"version": "4.0.0",
"description": "",
"author": "XYZ",
"private": true,
"scripts": {
"dev:staging": "gulp set --env=staging && nuxt",
"dev:prod": "gulp set --env=prod && nuxt",
"build:staging": "gulp set --env=staging && nuxt build",
"build:prod": "gulp set --env=prod && nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
},
"dependencies": {
"@nuxtjs/axios": "^5.9.5",
"@nuxtjs/dayjs": "^1.4.0",
"@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/gtm": "^2.4.0",
"@nuxtjs/robots": "^2.5.0",
"@nuxtjs/sitemap": "^2.4.0",
"@tryghost/content-api": "^1.11.0",
"bootstrap-vue": "^2.2.2",
"glob-all": "^3.1.0",
"nuxt": "^2.0.0",
"nuxt-helmet": "^1.2.3",
"nuxt-lazy-load": "^1.2.9",
"purgecss-webpack-plugin": "^2.0.5",
"tinyurl": "^1.1.7",
"vue": "^2.7.14",
"vue-gtag": "^1.16.1",
"vue-loader": "^15.10.0",
"vue-slick-carousel": "^1.0.6",
"vue-social-sharing": "^3.0.9",
"vuelidate": "^0.7.7"
},
"devDependencies": {
"@nuxt/types": "^2.15.7",
"@nuxtjs/eslint-config": "^1.0.1",
"@nuxtjs/eslint-module": "^1.0.0",
"@nuxtjs/stylelint-module": "^3.1.0",
"babel-eslint": "^10.0.1",
"eslint": "^6.1.0",
"eslint-plugin-nuxt": ">=0.4.2",
"gulp": "^4.0.2",
"gulp-clean": "^0.4.0",
"gulp-rename": "^2.0.0",
"nuxt-compress": "^5.0.0",
"sass": "^1.56.1",
"sass-loader": "^10.1.1",
"stylelint": "^10.1.0",
"yargs": "^15.1.0"
}
}
nuxt.config.js
require('dotenv').config();
const keywords = `...`;
export default {
ssr: true,
scrollToTop: true,
server: {
port: process.env.PORT || 5100,
host: '0.0.0.0' // default: localhost
},
router: {
scrollBehavior() {
return { x: 0, y: 0 };
}
},
/*
** Headers of the page
*/
head: {
title: 'Stack: Modern Investment Management',
meta: [ ... ]
},
loading: {
color: '#fff'
},
css: [
'@/assets/scss/app.scss'
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~/plugins/Vuelidate' },
{ src: '~/plugins/hotjar', mode: 'client' },
{ src: '~/plugins/gtag', mode: 'client' },
{ src: '~/utils', mode: 'client' },
{ src: '~/plugins/directives', mode: 'client' }
],
/*
** Nuxt.js dev-modules
*/
buildModules: [
'nuxt-compress'
],
/*
** Nuxt.js modules
*/
modules: [
'bootstrap-vue/nuxt',
'@nuxtjs/axios',
'@nuxtjs/dotenv',
'@nuxtjs/gtm',
'nuxt-lazy-load',
'nuxt-helmet',
'@nuxtjs/robots',
'@nuxtjs/sitemap',
'vue-social-sharing/nuxt',
'@nuxtjs/dayjs'
],
robots: {
UserAgent: '*',
Disallow: ''
},
sitemap: {
gzip: true,
hostname: 'https://stackinvest.in/'
},
gtm: {
id: 'GTM-NZW7782',
pageTracking: true,
pageViewEventName: 'nuxtRoute'
},
dayjs: {
locales: ['en'],
defaultLocale: 'en',
plugins: [
'utc' // import 'dayjs/plugin/utc'
]
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
bootstrapVue: {
bootstrapCSS: false,
bootstrapVueCSS: false
},
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extractCSS: true,
extend(config, { isDev, isClient }) {
config.resolve.symlinks = false;
if (isDev && isClient) {
config.devtool = 'source-map';
}
}
}
};
Code for prime-mutual-funds.vue
<template>
<main ref="page" class="prime-main">
<section class="hero">
...
</section>
<section class="risk-analysis">
<div class="row">
<div v-if="!isMobile" class="col-sm">
...
</div>
<div class="col-sm d-flex align-items-center mb-4 mb-sm-0">
<div>
<a v-if="isMobile" class="text-color text-decoration-done fw-600" :href="getOS() === 'android' ? 'URL1': 'url2'">
</a>
<a v-else class="text-color text-decoration-done fw-600" @click="showModal = true" href="javascript:void(0)">
...
</a>
</div>
</div>
<div v-if="isMobile" class="col-sm">
...
</div>
</div>
</section>
<section class="prime-detail">
<div class="prime-detail-header">
<h2 class="section-heading">Lorem Lorem</h2>
<div class="d-flex mt-3 mt-sm-4">
<a href="#options" class="prime-detail-tab" @click="activeTabIndex = 0" :class="{'active': activeTabIndex === 0}">investment options</a>
<a href="#automate" class="prime-detail-tab" @click="activeTabIndex = 1" :class="{'active': activeTabIndex === 1}">automated investing</a>
<a href="#track" class="prime-detail-tab" @click="activeTabIndex = 2" :class="{'active': activeTabIndex === 2}">actionable insights from experts</a>
</div>
</div>
<section id="options" class="p-4" v-if="isMobile">
...
</section>
<client-only><section v-else class="scroller pb-sm-128">
<div class="scroller-left">
<div id="options" class="scrollable-element">
<div id="1" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
<div class="scrollable-element">
<div id="2" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
<div id="automate" class="scrollable-element">
<div id="3" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
<div class="scrollable-element">
<div id="4" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
<div class="scrollable-element">
<div id="5" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
<div id="track" class="scrollable-element">
<div id="6" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
<div class="scrollable-element">
<div id="7" class="mxw-600" v-intersection="{threshold: .7, cb: updateRightContainer}">
...
</div>
</div>
</div>
<div class="scroller-right">
<div class="sticky-content">
<div class="sticky-content-box" v-if="activateText">
<span class="sticky-content-tag" :style="{backgroundColor: contentIndex[activeContentIndex].bgc}">{{ contentIndex[activeContentIndex].tag }}</span>
<h3 class="sticky-content-title mt-4">
{{ contentIndex[activeContentIndex].title }}
</h3>
</div>
<img v-else height="520px" ref="info" alt="info-img" src="https://webstatic.stackfinance.co/website/goals.webp"/>
</div>
</div>
</section></client-only>
</section>
<section class="rewards">
<h3 v-if="isMobile" class="rewards-heading">good financial habits <br> deserve <span class="text-white">great</span> rewards</h3>
<h3 v-else class="rewards-heading">good financial habits deserve <br> <span class="text-white">great</span> rewards</h3>
<h5 class="rewards-subheading">choose a free US stock with every investment.</h5>
<a :href="getOS() === 'android' ? '<url1>': '<url1>'"
v-if="isMobile" class="app-btn--sm d-block bgi-none bg-white text-color mx-auto my-4" style="width: 190px;">
download stack
</a>
<button v-else class="app-btn--white mt-sm-4" @click="showModal = true">download stack</button>
</section>
<app-grow-wealth :is-mobile="isMobile" @download="showModal = true"></app-grow-wealth>
<app-footer :is-mobile="isMobile"></app-footer>
<div v-if="isMobile" class="store-container py-2 px-4 bg-white position-fixed">
<a href="https://stack.app.link/3yAcChs5emb" rel="noopener">
<img height="40px" src="https://webstatic.stackfinance.co/website/playstore.png" alt="playstore">
</a>
<a href="https://stack.app.link/10JkMU6Xemb" rel="noopener">
<img class="float-right" height="40px" src="https://webstatic.stackfinance.co/website/appstore.png" alt="appstore">
</a>
</div>
<div v-if="showFaq" class="pop-box">
<app-faq-section :squeeze="true"></app-faq-section>
</div>
<button id="popover-button-sync" class="floating-help" @click="showFaq = !showFaq">
<img height="40px" src="https://webstatic.stackfinance.co/website/Chat 4_2x.png" alt="messenger">
</button>
<app-download v-if="showModal" :is-mobile="isMobile" @close="showModal=false"></app-download>
</main>
</template>
<script>
import Footer from '../components/Footer';
import FaqSection from '../components/Faq-Section';
import Download from '../components/Download';
import { fetchOS } from '../utils';
import GrowWealth from '../components/GrowWealth';
export default {
name: 'PrimeMutualFunds',
components: {
appFooter: Footer,
appFaqSection: FaqSection,
appDownload: Download,
appGrowWealth: GrowWealth
},
data() {
return {
size: Number,
showModal: false,
showFaq: false,
activateText: false,
activeTabIndex: 0,
imgIndex: {
1: 'URL',
2: 'URL',
6: 'URL',
7: 'URL'
},
contentIndex: {
3: {
tag: '...',
bgc: '#f9f2ea',
title: '...'
},
4: {
tag: '...',
bgc: '#e1f4f0',
title: '...'
},
5: {
tag: 'investment reminder',
bgc: '#ccebff',
title: '...'
}
},
activeContentIndex: 3
};
},
computed: {
isMobile() {
return this.size < 768;
}
},
mounted() {
this.size = this.$refs.page.clientWidth;
},
methods: {
getOS: () {
// fetchOS code below
if (!process.browser || !process.client) {
return 'android';
}
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/android/i.test(userAgent)) {
return 'android';
}
if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
return 'ios';
}
return 'unknown';
},
updateRightContainer({ isIntersecting, target }) {
if (isIntersecting) {
const x = target.getAttribute('id');
this.activeTabIndex = 0;
if ([5, 6, 7].includes(+x)) {
this.activateText = true;
this.activeContentIndex = x;
this.activeTabIndex = 2;
return;
}
if ([3, 4].includes(+x)) {
this.activeTabIndex = 1;
}
this.activateText = false;
if (this.$refs.info) {
this.$refs.info.setAttribute('src', this.imgIndex[x]);
}
}
}
}
}
};
</script>
Code of direction.js
Vue.directive('intersection', {
bind(el, binding) {
if (process.client) {
const threshold = binding.value.threshold || 0;
const defaultCb = () => {
console.log('No callback passed');
};
const cb = binding.value.cb || defaultCb;
if (isNaN(threshold)) {
return;
}
const observer = new IntersectionObserver((entries) => {
entries.forEach((elem) => {
cb(elem);
});
}, { threshold });
observer.observe(el);
}
}
});
If I comment out the navbar and deploy, the reload works fine without any issue for this URL -https://stackinvest.in/prime-mutual-funds