Parcel: Uncaught ReferenceError: require is not defined when <script type="module"....>

Created on 20 Feb 2018  路  10Comments  路  Source: parcel-bundler/parcel

馃悰 bug report

An app with <script type="module"... /> its index.html is properly parsed and served by Chrome, but after being built with ParcelJS causes Uncaught ReferenceError: require is not defined. This however doesn't make the app malfunctioning.

Configuration

package.json

{
  "name": "index",
  "version": "0.0.1",
  "description": "Test building ES6 app with ParcelJS",
  "main": "./src/index.html",
  "repository": "https://github.com/OleksiyRudenko/test-parcel-es6.git",
  "author": "Oleksiy Rudenko <[email protected]>",
  "license": "MIT",
  "scripts": {
    "start": "parcel ./src/index.html --public-url ./",
    "watch": "parcel watch ./src/index.html --public-url ./",
    "build-dev": "parcel build ./src/index.html --no-minify --public-url ./",
    "build": "parcel build ./src/index.html --public-url ./"
  }
}

Expected Behavior

The app comprising features supported by a given browser and served raw to the browser producing no errors wouldn't produce any errors being built with ParcelJS with basic settings.

馃槸 Current Behavior

The built app runs while browser reports Uncaught ReferenceError: require is not defined

I believe it happens since ES6 modules are strict-mode code and resulting JS bundle starts with require = (function (modules, cache, entry)... .

馃拋 Possible Solution

Replacing type='module' with e.g. defer in a <script> tag produces a fatal error (Uncaught SyntaxError: Unexpected identifier) at the very first import....

My qualifications are insufficient to suggest any workarounds. I am sorry about that.
Would appreciate any advice to overcome the issue.

馃敠 Context

Building an application while enjoying ES6 modules.

馃捇 Code Sample

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test ES6 build with ParcelJS</title>
    <script type="module" src="./index.js"></script>
</head>
<body>
    <h2>See dev console</h2>
</body>
</html>

index.js

import App from './App.js';
new App();

App.js

export default class App {
  constructor() {
    console.log('App instance created.')
  }
}

The above is to illustrate some sensible code. Building the app with empty index.js (and therefore ineffective App.js) still results in Uncaught ReferenceError: require is not defined.

The produced JS bundle reads:

// modules are defined as an array
// [ module function, map of requires ]
//
// map of requires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the require for previous bundles

// eslint-disable-next-line no-global-assign
require = (function (modules, cache, entry) {
  // Save the require from previous bundle to this closure if any
  var previousRequire = typeof require === "function" && require;

  function newRequire(name, jumped) {
    if (!cache[name]) {
      if (!modules[name]) {
        // if we cannot find the module within our internal map or
        // cache jump to the current global require ie. the last bundle
        // that was added to the page.
        var currentRequire = typeof require === "function" && require;
        if (!jumped && currentRequire) {
          return currentRequire(name, true);
        }

        // If there are other bundles on this page the require from the
        // previous one is saved to 'previousRequire'. Repeat this as
        // many times as there are bundles until the module is found or
        // we exhaust the require chain.
        if (previousRequire) {
          return previousRequire(name, true);
        }

        var err = new Error('Cannot find module \'' + name + '\'');
        err.code = 'MODULE_NOT_FOUND';
        throw err;
      }

      localRequire.resolve = resolve;

      var module = cache[name] = new newRequire.Module(name);

      modules[name][0].call(module.exports, localRequire, module, module.exports);
    }

    return cache[name].exports;

    function localRequire(x){
      return newRequire(localRequire.resolve(x));
    }

    function resolve(x){
      return modules[name][1][x] || x;
    }
  }

  function Module(moduleName) {
    this.id = moduleName;
    this.bundle = newRequire;
    this.exports = {};
  }

  newRequire.isParcelRequire = true;
  newRequire.Module = Module;
  newRequire.modules = modules;
  newRequire.cache = cache;
  newRequire.parent = previousRequire;

  for (var i = 0; i < entry.length; i++) {
    newRequire(entry[i]);
  }

  // Override the current require with this new one
  return newRequire;
})({2:[function(require,module,exports) {
},{}]},{},[2])

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.6.2 |
| Node | 8.9.4. |
| Yarn | 1.3.2 |
| Operating System | MS Windows 8.1 / 10 |
|Browser | Version 63.0.3239.132 (Official Build) (64-bit) |

Similar behaviour under both Windows flavours.

Bug

All 10 comments

Same for me but with Node 9.5.0.

the variable _require_ cannot be used directly without explicit declaration in es6 modules. parcel should add _const_ or _let_ to support es6

Since require can be used inside of the modules, defining it with let/const/var causes a ReferenceError: require is not defined. I'm trying to get parcel to work inside of an eval JS statement.

@outkine Have you tried replacing parcelRequire with window.parcelRequire (or require -> window.require)?

I've realized that the issue is my mistake. The var solution does work - what I was doing wrong was trying to call one of the modules instead of using the root require function. Sorry about that.

Just curious - why _is_ require set without any sort of declaration? Adding a var in front of the code seems hacky.

temporary fix for your work environment or localhost - https://twitter.com/dfkaye/status/1044693110700171264

@devongovett: any chance to move forward with this, by stripping type="module", or by incorporating the fix suggested by @dfkaye?

Or at least by closing #1401 as a dupe. Thanks!

This issue was obviously opened earlier than #1401 which means that #1401 _is_ a duplicate.

@alexeyraspopov You're right, but I opted to close this issue because #1401 has more discussion (might be more useful to fix this/for people who need a workaround).

Was this page helpful?
0 / 5 - 0 ratings