'Inertia.js ssr: ReferenceError: document is not defined

I am using Laravel 8 with Inertia.js version 0.5.4. Can anyone help solve this problem? The app works fine without the ssr. I think the problem is in the Webpack config file.

ReferenceError: document is not defined

package.json

"@inertiajs/inertia": "^0.11.0",
"@inertiajs/inertia-vue": "^0.8.0",
"laravel-mix": "^6.0",
"sass": "~1.32",
"sass-loader": "^12.2.0",
"vue-cli-plugin-vuetify": "~2.3.1",
"vue-loader": "^15.9.6",
"vue-template-compiler": "^2.6.10",
"vuetify-loader": "^1.7.0",
"webpack": "^5.59.1",
"vue": "^2.6.14",
"vue-server-renderer": "^2.6.14",
"vuetify": "^2.5.5",
"vuetifyjs-mix-extension": "0.0.20",
"vuex": "^3.4.0",
"webpack-node-externals": "^3.0.0"

webpack.ssr.mix.js

const path = require('path')
const mix = require('laravel-mix')
const webpackNodeExternals = require('webpack-node-externals');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

mix
    .options({ manifest: false, processCssUrls: false })
    .js('resources/js/ssr.js', 'public/js')
    .vue({
        version: 2, options: { optimizeSSR: true }
    })
    .webpackConfig({
        resolve: {
            alias: {
                '@resources': path.resolve('resources'),
                '{Template}': path.resolve('resources/js/Themes/default'),
                '@themeConfig': path.resolve('themeConfig.js'),
                '@core': path.resolve('resources/@core'),
                '@axios': path.resolve('resources/js/plugins/axios.js'),
                '@user-variables': path.resolve('resources/sass/variables.scss'),
                '@sass': path.resolve('resources/sass/'),
                'apexcharts': path.resolve(__dirname, 'node_modules/apexcharts-clevision'),
                '@': path.resolve('resources/js'),
            },
        },
        plugins: [new MiniCssExtractPlugin(
            {
                filename: "[name].css",
                chunkFilename: "[id].css",
                linkType: false,
            }
        )],
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                    options: {
                        // enable CSS extraction
                        extractCSS: true
                    }
                }
                // ...
            ]
        },
        target: 'node',
        devtool: 'source-map',
        externals: [webpackNodeExternals({
            // this WILL include `jquery` and `webpack/hot/dev-server` in the bundle, as well as `lodash/*`
            allowlist: [/^vuetify/, /^lodash/, 'vue-tel-input-vuetify/lib', /^vue-tel-input-vuetify^/, /^apexcharts^/, /^vue-apexcharts/, /apexcharts/, /apexcharts-clevision/, /^apexcharts-clevision/, /^apexcharts-clevision^/, /^vue-country-flag/, /\.css$/]
        })],
    })

ssr.js

import Vue from 'vue'
import {createRenderer} from 'vue-server-renderer'
import {createInertiaApp} from '@inertiajs/inertia-vue'
import createServer from '@inertiajs/server'
import PortalVue from 'portal-vue';
import store from './store'
import './plugins/acl'
import VueCompositionAPI from '@vue/composition-api'
import VueMeta from 'vue-meta'
import vuetify from '@/plugins/vuetify'
import Layout from '@/Layouts/AdminLayout.vue'
import AppLayout from "@/Layouts/AppLayout.vue"
import UserLayout from "@/Layouts/UserLayout.vue"
import ClientOnly from 'vue-client-only'

const moment = require('moment');


createServer((page) => createInertiaApp({
    page,
    render: createRenderer().renderToString,
    // resolve: name => require(`./Pages/${name}`),
    resolve: (name) => {
        // const page = (await import(`./Pages/${name}`)).default
        const page = require(`./Pages/${name}`);
        if (page.layout === undefined && name.startsWith('Admin/')) {
            page.layout = Layout
        }
        if (page.layout === undefined && name.startsWith('Dashboard/')) {
            page.layout = Layout
        }
        if (page.layout === undefined && name.startsWith('UserDashboard/')) {
            page.layout = UserLayout
        }
        if (page.layout === undefined && !name.startsWith('Admin/') && !name.startsWith('Dashboard/')) {
            page.layout = AppLayout
        }

        return page
    },
    setup({app, props, plugin}) {
        Vue.use(plugin);
        Vue.use(VueCompositionAPI);
        Vue.use(PortalVue);
        Vue.component('client-only', ClientOnly)

        Vue.use(VueMeta, {
            // optional pluginOptions
            refreshOnceOnNavigation: true
        })

        Vue.mixin({methods: {route}});

        return new Vue({
            vuetify: vuetify,
            store,
            render: h => h(app, props),
        })
    },
}))

npx mix --mix-config=webpack.ssr.mix.js
result : webpack compiled successfully 

node public/js/ssr.js

error : var style = document.createElement('style'); ^ ReferenceError: document is not defined at insertStyleElement (C:\laragon\www\test2\public\js\ssr.js:44989:15) at addStyle (C:\laragon\www\test2\public\js\ssr.js:45104:13) at modulesToDom (C:\laragon\www\test2\public\js\ssr.js:44977:18) at module.exports (C:\laragon\www\test2\public\js\ssr.js:45135:25) at Module../resources/sass/overrides.scss (C:\laragon\www\gooreo2\public\js\ssr.js:41942:145) at webpack_require (C:\laragon\www\test2\public\js\ssr.js:130966:42) at Module../resources/js/plugins/vuetify/default-preset/preset/index.js (C:\laragon\www\test2\public\js\ssr.js:38073:1) at webpack_require (C:\laragon\www\test2\public\js\ssr.js:130966:42) at Module../resources/js/plugins/vuetify/index.js (C:\laragon\www\test2\public\js\ssr.js:38099:80) at webpack_require (C:\laragon\www\test2\public\js\ssr.js:130966:42)

public/js/ssr.js

image



Solution 1:[1]

You can fix it is by adding one line to your webpack.mix.js to opt in to using the vue-style-loader

mix
.js('resources/js/ssr.js', 'public/js')
.vue({
    version: 3,
    useVueStyleLoader: true // This should fix it! 
});

Ref: https://aaronfrancis.com/2021/vue-referenceerror-document-is-not-defined-at-insertstyleelement

Solution 2:[2]

The problem was the version of google-cloud-bigquery was too old. I updated to 2.6.0 where support was added for materialized views, as documented here and it worked as expected.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dhamo
Solution 2 Andrew Harry