edtf.js icon indicating copy to clipboard operation
edtf.js copied to clipboard

global is not defined

Open justinlittman opened this issue 4 years ago • 6 comments
trafficstars

My apologies, but I cannot tell if this is a problem with the configuration of my React application or the packaging of edtf.js.

Using version 4.1.0 and 4.0.0, I get when running the application in a browser:

Uncaught ReferenceError: global is not defined
    js date.js:17

However, with 3.1.0 no error is received and edtf.js works as expected.

The webpack config is:

// Copyright 2019 Stanford University see LICENSE for license

/* eslint node/no-unpublished-require: ["off"] */
const path = require("path")
const webpack = require("webpack")
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
  entry: "./src/index.js",
  module: {
    noParse: /bad_json/,
    rules: [
      {
        test: /\.(js|jsx)$/,
        include: path.resolve(__dirname, "./src"),
        exclude: /node_modules/,
        use: ["babel-loader"],
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(scss)$/,
        use: [
          {
            // inject CSS to page
            loader: "style-loader",
          },
          {
            // translates CSS into CommonJS modules
            loader: "css-loader",
          },
          {
            // Run postcss actions
            loader: "postcss-loader",
            options: {
              // `postcssOptions` is needed for postcss 8.x;
              // if you use postcss 7.x skip the key
              postcssOptions: {
                // postcss plugins, can be exported to postcss.config.js
                plugins() {
                  return [require("autoprefixer")]
                },
              },
            },
          },
          {
            // compiles Sass to CSS
            loader: "sass-loader",
          },
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
        // More information here https://webpack.js.org/guides/asset-modules/
        type: "asset",
      },
    ],
  },
  resolve: {
    extensions: ["*", ".js", ".jsx"],
    fallback: {
      fs: false,
      stream: require.resolve("stream-browserify"),
      crypto: require.resolve("crypto-browserify"),
    },
  },
  output: {
    path: path.join(__dirname, "/dist"),
    publicPath: "/dist/",
    filename: "bundle.js",
  },
  plugins: [
    new webpack.ProvidePlugin({
      Buffer: ["buffer", "Buffer"],
      process: "process/browser",
    }),
    new HtmlWebpackPlugin({
      template: "index.html",
      filename: "index.html",
      hash: true,
    }),
    new webpack.EnvironmentPlugin({
      USE_FIXTURES: null,
      SINOPIA_API_BASE_URL: null,
      SINOPIA_GROUP: null,
      SINOPIA_ENV: null,
      SINOPIA_URI: null,
      AWS_COGNITO_DOMAIN: null,
      COGNITO_CLIENT_ID: null,
      COGNITO_USER_POOL_ID: null,
      INDEX_URL: null,
      SEARCH_HOST: null,
      EXPORT_BUCKET_URL: null,
      HONEYBADGER_API_KEY: null,
      HONEYBADGER_REVISION: null,
    }),
  ],
  devtool: "source-map",
  devServer: {
    static: "./dist",
    historyApiFallback: true,
    hot: true,
    port: 8888,
    proxy: {
      "/api/search": "http://localhost:8000",
    },
  },
}

Thanks in advance for your assistance.

justinlittman avatar Nov 22 '21 12:11 justinlittman

I would guess it's a packaging problem. We use global to access the global namespace namespace in a couple of places; I'm not using Webpack myself, but I'm sure there is some convention how to convert it (presumably, either renaming global to window or by defining var global = window as a global variable).

inukshuk avatar Nov 22 '21 14:11 inukshuk

My understanding is that webpack is supposed to do that automagically: https://webpack.js.org/guides/ecma-script-modules/

Other ESM modules that the app uses are transpiled correctly, but I don't know if they use global in the same way.

justinlittman avatar Nov 22 '21 14:11 justinlittman

I don't think this is about ESM modules at all. Both browsers and Node.js support ESM nowadays, but this is still an ESM module written for Node.js: it depends on Node.js modules and the Node.js API, where there is a global variable global to access the global namespace; in the Browser window would be the equivalent. When transpiing for use in the browser, you need a solution for this. As this is very common, I suspect Webpack will have a solution for this if enabled in the config; otherwise you should be able to work around it easily by defining global = window yourself before EDTF is loaded.

inukshuk avatar Nov 22 '21 14:11 inukshuk

Did anyone come up with a nice solution to this?

I can't add const global = window about import without my linter screaming. I haven't been able to add a new plugin which maps global.Date to a safe Date it can use.

mixmix avatar Mar 28 '22 03:03 mixmix

Would modifying src/date.js like this work:

const Parent = (typeof window === 'undefined' ? global.Date : window.Date)

export class Date extends Parent {

mixmix avatar Mar 28 '22 03:03 mixmix

Is this still about Webpack? In the docs it says that Webpack polyfills global by default so I wonder if this is Webpack issue?

That said, yes, it should be trivial to work around this by temporarily storing the original Date object in an extra variable.

inukshuk avatar Mar 28 '22 09:03 inukshuk

we also ran into this issue. Why not use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis ? it should work for everyone

eroux avatar Oct 27 '22 14:10 eroux

webpack5 doesn't provide polyfills for Node by default: https://stackoverflow.com/questions/64557638/how-to-polyfill-node-core-modules-in-webpack-5

eroux avatar Oct 27 '22 15:10 eroux

Using globalThis should be fine yes.

inukshuk avatar Oct 28 '22 08:10 inukshuk

thanks a lot!

eroux avatar Oct 28 '22 09:10 eroux