inukshuk / edtf.js

Extended Date Time Format (ISO 8601-2 / EDTF) Parser for JavaScript
BSD 2-Clause "Simplified" License
66 stars 12 forks source link

global is not defined #35

Closed justinlittman closed 2 years ago

justinlittman commented 2 years ago

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.

inukshuk commented 2 years ago

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).

justinlittman commented 2 years ago

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.

inukshuk commented 2 years ago

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.

mixmix commented 2 years ago

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 commented 2 years ago

Would modifying src/date.js like this work:

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

export class Date extends Parent {
inukshuk commented 2 years ago

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.

eroux commented 2 years ago

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 commented 2 years ago

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

inukshuk commented 2 years ago

Using globalThis should be fine yes.

eroux commented 2 years ago

thanks a lot!