Skip to content

nuxt generate --spa duplicating some items #438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
amritk opened this issue Aug 23, 2019 · 9 comments
Closed

nuxt generate --spa duplicating some items #438

amritk opened this issue Aug 23, 2019 · 9 comments

Comments

@amritk
Copy link

amritk commented Aug 23, 2019

I'm using nuxt generate --spa and I've been trying to figure out if I was doing something wrong or if this was a bug. Some of the meta tags and scripts are being duplicated with data-n-head="1" and data-n-head="2" I have posted a screenshot. Now only the "1's" are appearing when I view the source, the "2's" seem to be added via javascript somewhere?
Developer tools:
2019-08-22:20:48:42
Source:
2019-08-22:20:49:37

@pimlie
Copy link
Collaborator

pimlie commented Aug 23, 2019

The 1 and 2 are indicators to support multiple Vue-apps on a page, its very basic as in the first Vue-app thats created is 1, the second 2 etc. If you see this happening then it means multiple Vue-apps are running on the page and you should make sure that the Nuxt Vue-app is the one thats runs first

See the original issue & pr about supporting multiple vue-apps for more info: #372 and #373

Please keep me updated why this happens on your page, am very interested to understand when/why this happens!

@amritk
Copy link
Author

amritk commented Aug 23, 2019

Hey @pimlie could you point me in the right direction on how to begin figuring out where this second app is created? Do you think it could be something to do with Vuetify? I'm pretty new to nuxt and have no idea where a second app would be triggering, or how to even trigger the first app to be honest. Here's my nuxt.config.ts if that helps, its got a bunch of extra stuff I'm testing out right now to get this SPA working on Cordova.

import Sass from 'sass'
import dotenv from 'dotenv'
import clientKeys from '@hockeycommunity/shared/src/libs/client-keys'
import { NuxtConfigurationModule } from '@nuxt/types/config/module'
import { LinkPropertyBase } from 'vue-meta/types/vue-meta'
import vuetifyLoader from './src/plugins/vuetify-loader'

dotenv.config()

// Generate apple favicons
const appleSizes = [ 57, 60, 72, 76, 114, 120, 144, 152, 180 ]
const appleFavicons = appleSizes.map(size => ({
    rel: 'apple-touch-icon',
    href: `/favicons/apple-icon-${size}x${size}.png`,
    sizes: `${size}x${size}`
}))

const modules: NuxtConfigurationModule[] = [
    '@nuxtjs/axios',
    '@nuxtjs/dotenv',
    '@nuxtjs/sentry',
    'nuxt-babel',
    [ 'cookie-universal-nuxt', { alias: 'nuxtCookies' } ]
]
let link: LinkPropertyBase[]

if (process.env.CORDOVA) {
    // Cordova
    link = [
        {
            rel: 'stylesheet',
            href: '/css/material-icons.css'
        },
        {
            rel: 'stylesheet',
            href: '/css/roboto.css'
        }
    ]
}
// Web only
else {
    // Adsense
    modules.push(
        [ '@nuxtjs/google-adsense', {
            id: clientKeys.googleAdSense,
            analyticsUacct: clientKeys.googleAnalytics,
            analyticsDomainName: 'hockeycommunity.com'
        }]
    )
    // Favicons
    link = [
        {
            rel: 'stylesheet',
            href: 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons&display=auto'
        },
        ...appleFavicons,
        {
            rel: 'icon', type: 'image/png', sizes: '192x192', href: '/favicons/android-icon-192x192.png'
        },
        {
            rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicons/favicon-16x16.png'
        },
        {
            rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicons/favicon-32x32.png'
        },
        {
            rel: 'icon', type: 'image/png', sizes: '96x96', href: '/favicons/favicon-96x96.png'
        },
        {
            rel: 'icon', type: 'image/x-icon', href: '/favicon.ico'
        },
        { rel: 'manifest', href: '/favicons/manifest.json' }
    ]
}

const config = {
    mode: process.env.CORDOVA ? 'spa' : 'universal',
    debug: !(process.env.NODE_ENV === 'production'),
    env: {
        api: process.env.api,
        NODE_ENV: process.env.NODE_ENV,
        os: process.env.CORDOVA
    },

    // Custom Routes
    router: {
        extendRoutes (routes) {
            // Messages
            routes.push({
                name: 'messages-conversation',
                path: '/messages/:username',
                component: '@/pages/messages.vue'
            })

            // Explore
            routes.push({
                name: 'explore-map',
                path: '/explore/map',
                props: {
                    view: 'map'
                },
                component: '@/pages/explore/map-list.vue'
            })
            routes.push({
                name: 'explore-list',
                path: '/explore/list',
                props: {
                    view: 'list'
                },
                component: '@/pages/explore/map-list.vue'
            })
            routes.push({
                name: 'explore-place',
                path: '/explore/:category/:permalink',
                props: true,
                component: '@/pages/explore/place-category-permalink.vue'
            })

            // Team Finder
            routes.push({
                name: 'team-finder-request',
                path: '/team-finder/:kind/:uuid',
                props: true,
                component: '@/pages/team-finder/request-kind-uuid.vue'
            })
            routes.push({
                name: 'team-finder',
                path: '/team-finder/:kind',
                props: true,
                component: '@/pages/team-finder/feeds-index.vue'
            })
        },
        middleware: [ 'redirect' ],
        mode: 'hash'
    },

    // Head and meta tags
    head: {
        title: 'Hockey Community',
        meta: [
            { charset: 'utf-8' },
            { name: 'viewport', content: 'width=device-width, initial-scale=1, minimal-ui' },
            { name: 'apple-mobile-web-app-capable', content: 'yes' },
            { name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' },
            { name: 'msapplication-TileColor', content: '#ffffff' },
            { name: 'msapplication-TileImage', content: '/favicons/ms-icon-144x144.png' },
            { name: 'theme-color', content: '#ffffff' },
            {
                hid: 'description',
                name: 'description',
                content: 'Join thousands of players worldwide who share the same passion of making hockey happen.' +
                    'Find shinny, teams, goalies, players, hockey gear, leagues and tournaments all ' +
                    'though Hockey Community'
            },
            {
                hid: 'og:type', property: 'og:type', content: 'website'
            },
            {
                hid: 'og:image',
                property: 'og:image',
                content: 'https://s3-us-west-2.amazonaws.com/static.hc/images/logos/circle.png'
            },
            { hid: 'og:image:height', content: '150' },
            { hid: 'og:image:width', content: '150' },
            {
                hid: 'fb:app_id',
                content: '114995941981612'
            }
        ],
        // Set above
        link,

        // Scripts
        script: [
            {
                src: 'https://maps.googleapis.com/maps/api/js?key=x-xx&libraries=places',
                type: 'text/javascript'
            }
        ]
    },

    // Loading bar color
    loading: {
        color: '#fff'
    },

    // Global css
    css: [
        '@/assets/styles/index.sass',
        '@hockeycommunity/shared/src/assets/fonts/icomoon/icomoon.css',
        'iv-viewer/dist/iv-viewer.css'
    ],

    // Change src directory
    srcDir: 'src/',

    // Plugins to load
    plugins: [
        { src: '@/plugins/filters/index' },
        { src: '@/plugins/vuetify' },
        { src: '@/plugins/i18n' },
        { src: '@/plugins/google-analytics' },
        { src: '@/plugins/index' },
        { src: '@/plugins/image-upload', mode: 'client' },
        { src: '@/plugins/infinite-loading', mode: 'client' }
    ],

    // Nuxt.js modules
    modules,

    // Build modules
    buildModules: ['@nuxt/typescript-build'],

    // Sentry error reporting
    sentry: {
        dsn: 'https://[email protected]/x',
        disabled: !(process.env.NODE_ENV === 'production')
    },

    // Where to generate cordova
    generate: {
        dir: 'cordova'
    },

    // Max age for static assets
    render: {
        static: {
            maxAge: 1000 * 60 * 60 * 24 * 7
        }
    },

    // Typescript
    typescript: {
        typeCheck: true
    },

    // Server Middleware
    // serverMiddleware: [
    //     './server-middleware/redirect.ts'
    // ],

    // Build Config
    build: {
        // Different build path for Cordova
        publicPath: process.env.CORDOVA ? '/front-end' : '/_nuxt/',

        // Built asset filenames
        filenames: {
            app: ({ isDev }) => isDev ? '[name].js' : '[name]-[hash].js',
            chunk: ({ isDev }) => isDev ? '[name].js' : '[name]-[hash].js'
        },

        // Extend webpack config
        extend: (config, ctx) => {
            config.devtool = ctx.isClient ? 'eval-source-map' : 'inline-source-map'

            if (ctx.isDev && ctx.isClient && config && config.module) {
                config.module.rules.push({
                    enforce: 'pre',
                    test: /\.(ts|vue)$/,
                    loader: 'eslint-loader',
                    exclude: /(node_modules)/
                })
            }
        },

        loaders: {
            sass: {
                implementation: Sass,
                data: '@import "@/assets/styles/_helpers.sass"'
            }
        },

        // Vuetify Loader - To auto load your components
        transpile: [ /^vuetify/, /^@hockeycommunity\/shared/ ],
        plugins: [
            vuetifyLoader
        ],

        // Extract css into files instead of in head
        extractCSS: {
            allChunks: !!process.env.CORDOVA
        }
    }
}

console.log(config.head.script)

export default config

@pimlie
Copy link
Collaborator

pimlie commented Aug 24, 2019

Thanks for the info. It seems you are not using the official Vuetify module for Nuxt, was there a reason for that? That probably causes Vuetify to load before Nuxt does hence the app id issue.
Vuetify 2.0 was the main reason why support for multiple apps was added, so that's most likely the cause. Do you have any overlays in your app on load?

@aldarund @kevinmarrec Pinging you just as an fyi, seems using the nuxt module really is a must when using Vuetify with Nuxt

@kevinmarrec
Copy link

There is an issue around Vuetify code that makes SPA projects using vue-meta broken around theming. There's a fix pending here : vuetifyjs/vuetify#8566

See the related Nuxt Vuetify module issues for more info.

@amritk
Copy link
Author

amritk commented Aug 26, 2019

@pimlie I didn't use the nuxt module because I could not figure out how to use it with custom vueitfy loader options. Is there a way? I was using it to load my components as well, make's life much easier:

import fs from 'fs'
import recursiveReaddir from 'recursive-readdir'
import VuetifyLoaderPlugin from 'vuetify-loader/lib/plugin'

// Grab all of our local components for auto loading
const localComponents: {
    [key: string]: string
} = {}
recursiveReaddir('src/components', (err, items) => {
    if (err) {
        console.error('There was an error reading your component directory', err)
    }
    else {
        for (const item of items) {
            localComponents[item.replace(/^(.*[\\/])/, '').slice(0, -4)] = item.replace('src', '')
        }
    }
})

// Same for shared
const sharedComponents: string[] = []
fs.readdir('node_modules/@hockeycommunity/shared/src/components', (err, items) => {
    if (err) {
        console.error('There was an error reading shared components', err)
    }
    else {
        for (const item of items) {
            sharedComponents.push(item.slice(0, -4))
        }
    }
})

export default new VuetifyLoaderPlugin({
    match: (_originalTag: string, { kebabTag, camelTag }: { kebabTag: string; camelTag: string }) => {
        const comp = localComponents[kebabTag]
        if (comp) {
            return [camelTag, `import ${camelTag} from '@${comp}'`]
        }
        if (sharedComponents.includes(kebabTag)) {
            return [camelTag, `import ${camelTag} from '@hockeycommunity/shared/src/components/${kebabTag}.vue'`]
        }
    }
})

@pimlie
Copy link
Collaborator

pimlie commented Aug 27, 2019

@amritk Thanks for the info but that question is more suited to be asked on the vuetify-module repo ;)

@kevinmarrec
Copy link

kevinmarrec commented Aug 27, 2019

@amritk you're right, you can't for now, it's something that came to my mind yesterday, it's totally worth the feature request on vuetify-module repo. (I already planned to work on it but please open a feature request 😁)

@stale
Copy link

stale bot commented Sep 17, 2019

Thanks for your contribution to vue-meta! This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you would like this issue to remain open:

  1. Verify that you can still reproduce the issue in the latest version of vue-meta
  2. Comment the steps to reproduce it
    Issues that are labeled as pending will not be automatically marked as stale.

@stale stale bot added the stale label Sep 17, 2019
@amritk
Copy link
Author

amritk commented Sep 20, 2019

I ended up switching to the vuetify module and that seems to have fixed it.

@amritk amritk closed this as completed Sep 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants