Reputation: 595
Trying to add ag-grid in the nuxt app.
I followed the steps from https://www.ag-grid.com/vue-getting-started/ and How to use ag-grid in a Nuxt app
Note: Please do not try to run the snippets since I only used them to share the source I have.
My nuxt.config.js file
require('dotenv').config()
import pkg from './package'
export default {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: pkg.name,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
{ src: '~assets/bulma-modifications.scss', lang: 'scss' },
{ src: 'font-awesome/scss/font-awesome.scss', lang: 'scss' },
{ src: '~/node_modules/ag-grid-community/dist/styles/ag-grid.css', lang: 'css' },
{ src: '~/node_modules/ag-grid-community/dist/styles/ag-theme-dark.css', lang: 'css' }
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{
src: '~/plugins/plugin-ag-grid.js',
ssr: false
},
{
src: '~plugins/plugin-vue-chartjs.js',
ssr: false
}
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
// Doc: https://buefy.github.io/#/documentation
'nuxt-buefy',
'@nuxtjs/pwa',
'@nuxtjs/dotenv'
],
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
config.resolve.alias['vue'] = 'vue/dist/vue.common'
// Run ESLint on save
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
config.node = {
fs: 'empty'
}
}
},
env: {
baseUrl: process.env.BASE_URL || 'http://localhost:3000'
}
}
My Plugin plugin-ag-grid.js:
import * as agGridEnterpise from 'ag-grid-enterprise/main'
require('dotenv').config()
agGridEnterpise.LicenseManager.setLicenseKey([process.env.AG_LICENSE_KEY])
My Component AgGridDemo.vue:
<template>
<ag-grid-vue
style="width: 500px; height: 500px;"
class="ag-theme-balham"
:columnDefs="columnDefs"
:rowData="rowData"
></ag-grid-vue>
</template>
<script>
import { AgGridVue } from 'ag-grid-vue'
export default {
name: 'AgGridDemo',
data() {
return {
columnDefs: null,
rowData: null
}
},
components: {
AgGridVue
},
beforeMount() {
this.columnDefs = [
{ headerName: 'Make', field: 'make' },
{ headerName: 'Model', field: 'model' },
{ headerName: 'Price', field: 'price' }
]
this.rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 }
]
}
}
</script>
Finally My Page:
<template>
<section class="section">
Welcome to test page
<aggriddemo></aggriddemo>
</section>
</template>
<script>
import AgGridDemo from '~/components/AgGridDemo'
export default {
name: 'IndexPage',
components: {
AgGridDemo
}
}
</script>
I am getting Error on the Screen but not on my console, console says Compiled successfully but on screen I get:
SyntaxError Missing
stack frames
Any Ideas on why is this happening and how to fix this ?
Upvotes: 4
Views: 22864
Reputation: 431
It is because the ag-grid is used to work in spa mode. If you want to work in SSR mode you should isolate the ag-gird page like this:
make a file selectiveSSR.js in folder serverMiddleware
add this line to your nuxt.confing.js serverMiddleware: ['~/serverMiddleware/selectiveSSR.js'],
in the file '/serverMiddleware/selectiveSSR.js' put this code:
export default function(req, res, next) {
const paths = ['/hear is the name of the page'] // hear is the name of the page
// A very simple check
if (paths.includes(req.originalUrl)) {
// Will trigger the "traditional SPA mode"
res.spa = true
}
// Don't forget to call next in all cases!
// Otherwise, your app will be stuck forever :|
next()
}
It works for specific URL as spa mode and the ag-grid can come up in spa mode.
https://www.ag-grid.com/vue-data-grid/getting-started/
Upvotes: 0
Reputation: 3579
Firstly, although would likely not cause this error, the component in your template should be kebab case. <ag-grid-demo/>
. From vue docs
The error you are getting is probably an ssr issue, and although you have specified ssr: false
in your nuxt.config.js this doesn't always get the point across.
Could you try this:
<template>
<section class="section">
Welcome to test page
<no-ssr>
<ag-grid-demo></ag-grid-demo>
</no-ssr>
</section>
</template>
<script>
let AgGridDemo = {}
if (process.browser) {
AgGridDemo = require('~/components/AgGridDemo')
}
export default {
components: {
'ag-grid-demo': AgGridDemo
}
}
</script>
Also, as an aside, the modern way to import plugins in nuxt.config.js is as follows.
plugins: [
'~/plugins/plugin-ag-grid.client.js'
//Note the .client.js This is shorthand for the following which you can also use
src: { '~/plugins/plugin-ag-grid.js', mode: client }
]
The use of ssr: false
will be deprecated in the next major release. See docs
Edit
If this is still causing errors you may need to add the plugin to build-transpile
in nuxt.config.js. Like so:
build: {
...
transpile: [
'/plugins',
],
}
This will transpile all your plugins but see how you go. Unfortunately the docs don't give us a lot about this.
If you can't get that to work the old fashioned approach was to add the component to a whitelist like this:
//nuxt.config.js
const nodeExternals = require('webpack-node-externals')
module.exports = {
/**
* All other config code
*/
build: {
extend(config, ctx) {
if (ctx.isServer) {
config.externals = [
nodeExternals({
whitelist: [/^@components\\AgGridDemo.vue/]
// or however you regex a windows path
})
]
}
}
}
}
Upvotes: 2
Reputation: 66
After trying every solution given here (Thanks for posting), I managed to render the ag-grid on a nuxt project using < no-ssr > tag and dynamic import (minute 7:40 is explained how to do it, if you are not familiar with codesplitting I deeply recommend to watch the whole video) dynamic import video.
How did I get there? Well, Since Andrew wrote that the problem may have something to do with ssr,I switched my nuxt project into mode: 'spa' and BOOM! ag-grid-vue showed up. Now the problem was, many of my features are heavely based on ssr stuff. So I had to make it work for srr mode, but now I know ag-grid-vue is fully available on the client side, so I switched back to mode: ssr and made the following:
Note: Please do not try to run the snippets since I only used them to share the source I have.
My agGridDemo.vue
<template>
<ag-grid-vue
style="width: 500px; height: 500px;"
class="ag-theme-balham"
:columnDefs="columnDefs"
:rowData="rowData"
></ag-grid-vue>
</template>
<script>
import { AgGridVue } from 'ag-grid-vue'
export default {
name: 'ag-grid-demo',
data() {
return {
columnDefs: null,
rowData: null
}
},
components: {
AgGridVue
},
beforeMount() {
this.columnDefs = [
{ headerName: 'Make', field: 'make' },
{ headerName: 'Model', field: 'model' },
{ headerName: 'Price', field: 'price' }
]
this.rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000 },
{ make: 'Ford', model: 'Mondeo', price: 32000 },
{ make: 'Porsche', model: 'Boxter', price: 72000 }
]
}
}
</script>
<style lang="scss">
@import "~/node_modules/ag-grid-community/dist/styles/ag-grid.css";
@import "~/node_modules/ag-grid-community/dist/styles/ag-theme-balham.css";
</style>
Nothing new here, I guess, just that importing the stylesheets in nuxt.config.js file, made the stylesheets unreachable (at leat in my case). So I added the < style > tag and import the stylsheets as is specified in the ag-grid docs
Here's where magic happened, dynamic imports (as you can see in the video I recomended) avoid to import the component code in the the first load, and import it only when is called, this often useful to optimize page load. So in my first attemp i wrote some this:
<template>
<section>
<comAgGridDemo v-if="mostrarGrid " ></comAgGridDemo>
</section>
</template>
<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator";
// import comAgGridDemo from '~/components/comAgGridDemo.vue'
const comAgGridDemo = () => import('~/components/comAgGridDemo.vue');
@Component({
components: {
comAgGridDemo
}
})
export default class extends Vue {
mostrarGrid: boolean = false;
mounted() {
this.mostrarGrid = true
}
}
</script>
So comAgGridDemo will be rendered only when mostrarGrid is true, then in mounted hook (because mounted is available in client side) I made mostrarGrid = true. And It's done.
I went a little futher because, i was not happy using mounted hook for this matter, so I wrapped the component comAgGridDemo on a < srr > tag, remove the v-if, and ag-grid remained rendered just fine. So the index.vue file ended up like this:
My index.vue
<template>
<section>
<no-ssr>
<comAgGridDemo ></comAgGridDemo>
</no-ssr>
</section>
</template>
<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator";
// import comAgGridDemo from '~/components/comAgGridDemo.vue'
const comAgGridDemo = () => import('~/components/comAgGridDemo.vue');
@Component({
components: {
comAgGridDemo
}
})
export default class extends Vue {
}
</script>
And that's it.
Note that if you. If you use, < no-ssr > tag with regular import, ag-grid will fail. If you use dymamic import without < no-ssr > tag, ag-grid will fail. If you use the "v-if way" no need to use < no-ssr > tag.
Something is weird on the ssr using ag-grid. But this is how managed to solve it. If there's a better solution, please advise.
I've made a github repo: https://github.com/warheartvik/nuxt-ag-grid
Upvotes: 4