使用Webpack打包后,窗口未定义

14

我正在开发一个ReactJS应用程序,同时我正在使用WebPack 4.29.6。我面临的问题是,当我运行npm run dev命令时,在本地一切都很完美,但当我想要部署到服务器上时,我不知道该怎么做。我使用build:production命令构建应用程序,然后它生成了/dist文件夹以及所有文件。现在,当我尝试运行bundle.js时,它会给出错误:ReferenceError:window未定义

这些是我用来启动我的应用程序的命令:

"scripts": {
    "dev": "cross-env webpack-dev-server --config ./webpack.config.dev.js --mode development",
"build:production": "cross-env webpack --config webpack.config.production.js --mode production"
}

这是我的webpack.config.common.js文件

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

const outputPath = path.join(__dirname, '/dist');

const port = process.env.PORT || 4000;

module.exports = {
  context: __dirname,
  entry: './src/index.jsx',
  resolve: {
    extensions: ['*', '.js', '.jsx'],
  },
  output: {
    path: outputPath,
    publicPath: '/',
    filename: 'bundle.js',
    sourceMapFilename: 'bundle.map',
  },
  devServer: {
    port,
    historyApiFallback: true,
    compress: true,
    contentBase: './dist',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader', 'eslint-loader'],
      },
      {
        test: /\.less$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'less-loader',
          },
        ],
      },
      {
        test: /\.css$/,
        use: ['css-loader'],
      },
      {
        test: /\.svg$/,
        loader: 'svg-inline-loader',
      },
      {
        test: /\.(png|jpg|gif|woff(2)?|ttf|eot|svg)$/,
        exclude: [
          /\.(js|jsx|mjs)$/,
          /\.html$/,
          /\.json$/,
          /\.(less|config|variables|overrides)$/,
        ],
        use: [
          {
            loader: 'file-loader',
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.ProvidePlugin({
      Promise: 'es6-promise-promise',
    }),
  ],
};

这是我的webpack.config.dev.js文件

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

const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpackCommonConfig = require('./webpack.config.common');

module.exports = merge(webpackCommonConfig, {
  mode: 'development',
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, '/index.html'),
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }),
  ],
  devtool: 'inline-source-map',
  devServer: {
    hot: true,
    open: true,
  },
  externals: {
    // global app config object
    config: JSON.stringify({
      apiUrl: 'http://localhost:3000',
    }),
  },
});

这是我的webpack.config.production.js

const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

const webpackCommonConfig = require('./webpack.config.common');

module.exports = merge(webpackCommonConfig, {
  mode: 'production',
  plugins: [new webpack.EnvironmentPlugin({ NODE_ENV: 'production' })],
  optimization: {
    minimizer: [
      // we specify a custom UglifyJsPlugin here to get source maps in production
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        uglifyOptions: {
          compress: false,
          ecma: 6,
          mangle: true,
        },
        sourceMap: true,
      }),
    ],
  },
  devtool: 'source-map',
  devServer: {
    compress: true,
  },
});

3个回答

12

可能回答晚了,但它可能会对其他人有所帮助。我也遇到了Webpack 4中的ReferenceError: window is not defined.问题,并发现在webpack配置文件的output部分添加globalObject: 'this'行可以解决我的问题:

  output: {
    globalObject: "this",
    filename: "[name].js",
    path: path.join(__dirname, "build/package"),
    publicPath: "/resources/",
  }
你可以看到这个问题在这里讨论过:here,以及关于globalObject设置的Webpack文档在这里:here

1

使用global对我起作用了。

const window = global.window
if (window && window.localStorage) {
  const storageLogLevel = window.localStorage.getItem(LOG_LEVEL_KEY)
  switch (storageLogLevel) {
    case LogLevel.DEBUG:
      logLevel = 0
      break
    case LogLevel.INFO:
      logLevel = 1
      break
    case LogLevel.WARNING:
      logLevel = 2
      break
    case LogLevel.CRITICAL:
      logLevel = 3
      break
    default:
      logLevel = 1
  }
}

0
在尝试构建docusaurus文档时,我遇到了一个相同的错误。为了解决这个问题而不修改内部代码,我建议在位于`src/theme/Root.js`的Root.js文件中进行简单的检查(如果不存在,可以创建它)。您可以添加以下代码片段:
...
export default function Root({ children }) {
  if (typeof window !== "undefined") {
    return (
      <>
        {children} 
      </>
    );
  }
  return null;
}

通过实施这个检查,你可以确保在应用程序运行之前,窗口对象已经被定义,从而防止错误的发生。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接