parcel: ES Module type=module cause "parcelRequire is not defined" error
š bug report
Using ES Module in main HTML cause āparcelRequire is not definedā error.
If we use type=āmoduleā, minimal code in Getting Started (Parcel official) make this error.
š Configuration (.babelrc, package.json, cli command)
zero configuration.
š¤ Expected Behavior
If we write super simple code with ES Module like below,
<!-- index.html -->
<html>
<body>
<script src="./index.js" type="module"></script>
</body>
</html>
// index.js
console.log("hello parcel");
I hope it is bundled properly and get āhello parcelā in console without error.
šÆ Current Behavior
In console,
hello parcel. index.js 1
Uncaught ReferenceError: parcelRequire is not defined at test.904c6489.js:10
š Possible Solution
Apparently ES Module cause this error.
When I removed type=āmoduleā from script element, no error observed.
It suggest that we can avoid error by avoiding type=āmoduleā for parcel.
But I think this approach is not good.
ES Module (type=āmoduleā) is generally available (now 2018-05, all popular browsers supported!!), so ES module is straight forward way to import module.
š¦ Context
I do not know what problem is caused by this error.
š Your Environment
Software | Version(s) |
---|---|
Parcel | parcel-bundler@1.8.1 |
Node | (problem happen both) 8.9.3 & 9.11.1 |
npm/Yarn | |
Operating System | Windows10 Pro, build 17134 |
Thank you good library, I hope this project become better and better.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 68
- Comments: 53 (8 by maintainers)
Commits related to this issue
- Add `var` declaration to parcelRequire definition in prelude.js to address ReferenceError (issue #1401) — committed to twome/parcel by twome 5 years ago
- Add declaration to parcelRequire definition in prelude.js to address ReferenceError (issue #1401) — committed to twome/parcel by twome 5 years ago
- fix for running the demo Parcel has some [misunderstandings between script tags declared as es module](https://github.com/parcel-bundler/parcel/issues/1401) and it's cascading into the build as conso... — committed to joelewis/peritext by joelewis 3 years ago
- add parcel-plugin-wrapper https://github.com/parcel-bundler/parcel/issues/1401#issuecomment-437649847 — committed to housing-data-coalition/rtc-eviction-viz by austensen 8 months ago
since you use type=āmoduleā,why use parcel?
Mainly for module resolution.
And for old browser users (ES module not supported, need Bundle.)
Please see my PR above. Itās pretty disappointing that there was no fix or PR for this show-stopper bug that requires literally a 4-character fix, for a 30k star project used by so many people š
This is an issue with the way
parcelRequire
is defined in Strict Mode. ES6 modules are by default executed in strict mode (AFIK), which prohibits implicit variable declerations.Hereās what Parcelās output looks like:
Notice how the global parcelRequire is implicitly declared without let/var!
By editing the output file and naively adding
let
beforeparcelRequire
I was able to eliminate the issue. However, adding let can affect scopingā¦An alternative that works is changing it to
window.parcelRequire
, but that would break in Node; which probably doesnāt really matter since we can avoid doing that in--target node
.I ran into this in the wild in a slightly separate case when attempting to require a library I bundled with Parcel in a Webpack project. The Webpack project had a top level
"use strict"
pragma automatically injected which is what broke everything in the same way as this issue.A good point to use Parcel in this case is the minification and files with hashes
I have the same problem in different context. Iām trying to consume parcel-bundled module from my webpack-bundled app. Since ES6 modules (my app) run in strict context an attempt to consume the module results in assignment to undefined variable and crashes my app.
@devongovett I think stripping
type="module"
from the output script tag is a good solution.My usage of parcel is not quite as intended. I prefer to write completely valid js/css that runs in modern browsers, and dev using a simple static server and modern browser (with no build step). I want to use parcel only for producing production builds (both to compile to ES5 for older browsers, and to concatenate small scripts).
Since parcel doesnāt concatenate multiple script tags from a single html page, you have to
import
them from another js file. But the only way to get that to work in development without a build step is to usetype="module"
(alternatively, if parcel would bundle consecutive<script>
tags in an html file, that would also work - but it seems like a bigger change).I know my use case isnāt as intended, but I think it has a lot of merit, and parcel very nearly supports it.
This is not a bug. Donāt use
<script type="module">
with parcel. Parcel expects its generated scripts not to run in strict mode so it can assign to the global object and such. I donāt see a reason to use<script type="module">
with Parcel since Parcel already compiles modules to ES5.In order to work around this error when users mistakenly specify
<script type="module">
in their HTML, we could strip thetype
attribute in the HTML packager when we write the output bundle.Maybe it makes sense for Parcel to remove
type="module"
for an entry that is being built?@nestarz This will be possible with Parcel 2 (and itās already implemented).
temporary fix for your work environment or localhost - https://twitter.com/dfkaye/status/1044693110700171264
Add a
<script>var parcelRequire;</script>
to the<head>
solve this issue for me. I have to usetype="module"
with Parcel because Iām using TypeScript.yeah Iām having this issue when I use a raw .ts file as my input and I bundle my node_modules with it into a single file e.g.
parcel build ./src/index.ts --target node --bundle-node-modules
when i run it in node Iāll get an error like
ReferenceError: parcelRequire is not defined
when I look at the non-minified version I can see
so my guess is the assumption was that it would globally assign. it appears that it doesnāt.
Obviously if I add
var
in front of it the lexical scoping lookup of JavaScript assigns it to global. but from what I can gather that would break things for other environments i.e. not--target node
I came up with a workaround
parcel build ./src/index.ts --target node --bundle-node-modules --out-dir ./dist --no-minify --out-file main.js && sed -i '' '1s;^;var ;' ./dist/main.js
obviously the bummer here is I canāt use
watch
because how would I append it for my needs.anyway is there an ETA for this fix? the set-up (or lack thereof) is super convenient so Iād like to use Parcel for a recommended way of doing something except this is kind of a blocker.
nicer work around:
yarn add parcel-plugin-wrapper --dev
.assetWarpper.js
With alpha 2 (which should be released in the next couple of days), you can do
and
index.js
will automatically be emitted as an ES module.Or if you want to build a library, specify it via
package.json#targets.name.outputFormat
: package.json(and running something like
parcel build src/index.js
)Adding the Firefox error message so this issue pops up in searches:
Can this issue be resolved without altering the generated output (e.g. assigning to
window.parcelRequire
instead ofparcelRequire
) at the moment?if you strip <script type="module"> you need to add
defer
to get the same behaviour@devongovett ava appears to load tests as esmodules. see https://github.com/parcel-bundler/parcel/issues/2213 - i can certainly prepend my compiled test files with
var parcelRequire = undefined;
, that seems to work, but I think there is a use case here. Iād certainly rather this than having to juggle multiple build systems@kungfooman thereās an example in this thread on how to do this https://github.com/parcel-bundler/parcel/issues/1401#issuecomment-541409113
I used this workaround.
My use is to use native ES modules for dev and then bundler for production for older browsers. I also happen to be using snowpack.
If you say Parcel will not work in this case without rewriting the script include structure between dev and deploy it cannot be used. š¦
While I get the error everyhting seems to work. So does the error matter?
Looks like a duplicate of https://github.com/parcel-bundler/parcel/issues/864
I get this error whether I use
type="module"
or not. And the weird thing is that it only appears when I deploy it to vercel. But it works withnpm start
locally. And it only happens ifindex.js
includes an import statement.EDIT: more testing It simply does not work with
npm run build
. Butnpm start
works.Observation: In addition to that LOL fix from Twitter, this issue can also be hackishly fixed by inserting any regular script tag ( not type=module ) before your type=module entry point. Without it Parcel still generates these errors.
Sooo, am I reading this correctly? Parcel does not allow for a standard ES Module output?
it should not be hard to add
var
orlet
orconst