'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

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 |
