Nuxt.js部署生产环境时出现window is not defined错误求助
问题
基于Nuxt.js开发的应用在开发模式下运行正常,但部署到生产服务器后出现**"window is not defined"**错误,怀疑和highcharts-vue.min.js模块加载有关。
报错截图:
相关组件代码:
<template> <highcharts class="hc" :options="chartOptions" ref="chart"> </highcharts> </template> <script> import {Chart} from 'highcharts-vue' export default { name:"ForecastCuaca", components: { highcharts: Chart }, data() { return { data_cuaca:[], chartOptions: { chart: { type: 'spline', backgroundColor: 'transparent', marginTop:100 }, title: { text: 'Prakiraan Cuaca Kota Kupang', style:{ "color": "#ebeefd", "fontSize": "22px" } }, subtitle: { text: 'Source: openweathermap.org', style:{ "color": "#ebeefd", } }, xAxis: { categories: ['Tanggal'], labels:{ style:{ color:"#ebeefd" } } }, yAxis: { title: { text: 'Suhu' }, labels: { formatter: function () { return this.value + '°'; }, style:{ color:"#ebeefd" } }, style:{ "color": "#ebeefd", } }, tooltip: { formatter: function () { return 'Suhu : ' + this.y + '° C<br /><b>' + this.x + '</b>'; } }, plotOptions: { spline: { marker: { radius: 4, lineColor: '#666666', lineWidth: 1 } } }, series: [{ name: 'Kota Kupang', marker: { symbol: 'square' }, data: [ 10 ], style:{ "color": "#ebeefd", } } ], credits:{ enabled:false } }, title: '', } }, methods:{ generate_data(datax){ const self = this; self.data_cuaca = datax self.chartOptions.xAxis.categories = [] self.chartOptions.series[0].data = [] let ganjil = 0; for (let index = 0; index < self.data_cuaca.length; index++) { ganjil++; const element = self.data_cuaca[index]; self.chartOptions.xAxis.categories.push(element.waktu_indonesia) if (ganjil % 2 == 1) { const iconx = element.weather[0].icon+'.png'; const data_series = { y:element.main.temp, marker: { symbol: "url(http://openweathermap.org/img/w/"+iconx+")" } } self.chartOptions.series[0].data.push(data_series) }else{ self.chartOptions.series[0].data.push(element.main.temp) } } } } } </script>
解决方案
这个错误的核心原因是:Nuxt.js默认采用服务端渲染(SSR),而highcharts-vue依赖浏览器环境的window对象,服务端渲染阶段没有window,因此抛出该错误。以下是几种可行的解决方式:
方法1:用client-only标签包裹组件
直接让组件仅在浏览器端渲染,是最快捷的方案:
<template> <client-only> <highcharts class="hc" :options="chartOptions" ref="chart"> </highcharts> </client-only> </template>
方法2:动态导入组件(仅客户端)
修改组件导入逻辑,仅在客户端环境下加载highcharts-vue:
<template> <highcharts v-if="isClient" class="hc" :options="chartOptions" ref="chart"> </highcharts> </template> <script> export default { name:"ForecastCuaca", data() { return { isClient: process.client, data_cuaca:[], chartOptions: { /* 原配置不变 */ } } }, components: {}, async mounted() { if (process.client) { const { Chart } = await import('highcharts-vue') this.$options.components.highcharts = Chart } }, methods: { /* 原方法逻辑不变 */ } } </script>
方法3:配置客户端插件
通过Nuxt插件系统,让highcharts-vue仅在客户端注册:
- 在项目根目录创建
plugins/highcharts.client.js文件:
import Vue from 'vue' import { Chart } from 'highcharts-vue' Vue.component('highcharts', Chart)
- 修改
nuxt.config.js添加插件配置:
export default { plugins: [ { src: '~/plugins/highcharts.client.js', mode: 'client' } ] }
之后组件中可直接使用<highcharts>标签,无需手动导入。
额外注意事项
- 确保
chartOptions中的格式化逻辑不依赖浏览器API,若有相关代码,需限制仅在客户端执行。 - 方法1适合快速解决问题,方法2、3适合需要更精细控制组件加载时机的场景。
内容的提问来源于stack exchange,提问作者Kenny Wks
相关产品推荐
相关产品推荐

