如何在运行webpack部署配置时解析“窗口未定义”?

时间:2017-09-20 16:04:52

标签: javascript node.js reactjs google-maps-api-3 webpack

我正在尝试将react +服务器应用程序部署到Heroku。总体目标是使用Heroku dyno作为通用服务器来提供静态资产,并充当我的React应用程序的API端点。我正在编写部署配置以缩小并遇到错误。

它缩小但在node dist/bundle.js上它会出现以下错误。

ReferenceError: window is not defined

要使用googlemaps api,我有一个Map组件,它将全局窗口对象上的一个函数设置为initMap(),在Map组件中定义。

并在loadJS()引用window.document两次。

正在开发中,它运作良好 我用这篇文章来帮助Making Google Maps work with React

我怀疑窗口对象是未定义的,因为还没有浏览器提供窗口对象。

你能证实我的怀疑吗?需要解决什么问题?

我的package.json文件中的

脚本

  "scripts": {
      "start": "npm build && node dist/bundle.js",
      "dev-start": "babel-node server/buildScripts/server.js",
      "build":"webpack --config ./webpack.deployment.config.js",
      "test": "echo \"Error: no test specified\" && exit 1"
  },

webpack.deployment.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
    devtool: 'source-map',

    entry: [
        './client/index.js'
    ],
  output: {
      path: path.join(__dirname, 'dist'),
      filename: 'bundle.js',
      publicPath: './dist/'
  },
  plugins: [
      new webpack.optimize.UglifyJsPlugin({
          minimize: true,
          compress: {
          warnings: false
      },
      sourceMap: true
    })
  ],
  module: {
      loaders: [{
          test: /.jsx?$/,
          loader: 'babel-loader',
          include: path.join(__dirname, 'client'),
          exclude: /node_modules/,
          query: {
              presets: ['es2015', 'react']
        }
    },
     { test: /\.css$/, loader: "style-loader!css-loader" },
     { test: /\.(jpg|png|svg)$/, use: 'file-loader'}
    ]
},
};

客户端/组件/ Googlemaps.js

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { getGoogleGeoLocation } from '../actions/index.js'

class Map extends React.Component {
    constructor(props) {
        super(props);

    this.initMap = this.initMap.bind(this)
  }

  initMap() {
    if(!this.props.location.lat  ) {
         let map = new google.maps.Map(this.refs.map, { center: { lat: 36.1699, lng: -115.1398 }, zoom: 12 });
    } else {
      let lat = parseFloat(this.props.location.lat)
      let lng = parseFloat(this.props.location.lng)
      let map = new google.maps.Map(this.refs.map, { center: { lat, lng }, zoom: 12 });
    }
 }

  componentDidMount() {
      window.initMap = this.initMap;
      loadJS('https://maps.googleapis.com/maps/api/js?key=AIzaSyAvn1WOC1uXO7jw820pYZsSzZUNh5g7cTs&callback=initMap')
      this.props.fetchLocation()
  }


  componentDidUpdate() {
    loadJS('https://maps.googleapis.com/maps/api/js?key=AIzaSyAvn1WOC1uXO7jw820pYZsSzZUNh5g7cTs&callback=initMap')
  }


  render() {
    const mapStyle = {
        width: 1000,
        height: 500,
    };
    if (this.props.hasErrored) {
        return <p>Sorry! There was an error loading the items</p>;
    }

    if (this.props.isLoading) {
        return (
            <div>
                <h4>loading...</h4>
                <div ref="map" style={mapStyle}></div>
           </div>
      );
    } else {  
        return (
            <div id='map' ref="map"></div>
        );
      }
    }
}

function loadJS(src) {
    var ref = window.document.getElementsByTagName("script")[0];
    var script = window.document.createElement("script");
    script.src = src;
    script.async = true;
    ref.parentNode.insertBefore(script, ref);
}


const mapStateToProps = (state) => {
    return {
        location: state.location,
        hasErrored: state.locationHasErrored,
        isLoading: state.locationIsLoading
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
      fetchLocation: (url) => dispatch(getGoogleGeoLocation())
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(Map)

1 个答案:

答案 0 :(得分:0)

听起来你需要使用npm模块jsdom,它在浏览器环境之外提供了一个window / window.document对象。