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.
zero configuration.
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");
md5-a3efa0b3622eb4ff18322186b74c8946
hello parcel. index.js 1
Uncaught ReferenceError: parcelRequire is not defined at test.904c6489.js:10
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.
I do not know what problem is caused by this error.
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | [email protected] |
| 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.
since you use type="module",why use parcel?
Mainly for module resolution.
And for old browser users (ES module not supported, need Bundle.)
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.
~Seems like this is no longer reproducible in v1.9.4.~
Edit: disregard this, still reproducible.
Maybe it makes sense for Parcel to remove type="module"
for an entry that is being built?
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:
parcelRequire = (function (modules, cache, entry, globalName) {
// Save the require from previous bundle to this closure if any
var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
var nodeRequire = typeof require === 'function' && require;
function newRequire(name, jumped) {
Notice how the global parcelRequire is implicitly declared without let/var!
By editing the output file and naively adding let
before parcelRequire
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.
Looks like a duplicate of https://github.com/parcel-bundler/parcel/issues/864
Adding the Firefox error message so this issue pops up in searches:
ReferenceError: assignment to undeclared variable parcelRequire
Can this issue be resolved without altering the generated output (e.g. assigning to window.parcelRequire
instead of parcelRequire
) at the moment?
it should not be hard to add var
or let
or const
(duplicate of https://github.com/parcel-bundler/parcel/issues/864#issuecomment-422642478)
Since require may be used inside of the modules, defining it with let/const/var causes a ReferenceError: require is not defined
temporary fix for your work environment or localhost - https://twitter.com/dfkaye/status/1044693110700171264
nicer work around:
yarn add parcel-plugin-wrapper --dev
.assetWarpper.js
const path = require('path')
const CWD = process.cwd()
const PACKAGE = require(path.join(CWD, 'package.json'))
const varRequire = async ({name, bundler}) => {
// name = app.ere76r5e76r5e76r.js
if (name.split('.').pop() === 'js' && bundler.options.production) {
return {
header: `var parcelRequire = undefined;`,
footer: ``
}
}
}
module.exports = varRequire;
We're having same issue!
Note that simply removing type="module"
didn't work, even after re-launching parcel. I had to also delete the .cache
directory.
Sooo, am I reading this correctly? Parcel does not allow for a standard ES Module output?
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
// eslint-disable-next-line no-global-assign
parcelRequire = (function (modules, cache, entry, globalName) {
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.
We ran into another issue specific to our app, so we had to come up with a post-bundling process file that uses the parcel-bundler API directly (see https://parceljs.org/api.html) in order to solve that as well as the "parcelRequire is not defined" issue.
https://gist.github.com/dfkaye/f43dbdfbcdee427dbe4339870ed979d0
Have the same issue here!
"ReferenceError: parcelRequire is not defined"
While working in:
index.js, imports fileA
fileA.js, imports fileB
fileB.js
Command:
parcel build ./src/index.js --target browser
Can fix if manually add let,const before parcelRequire= in the dist/output file
A workaround for Gulp / stream-based build system users, using gulp-insert to prepend the parcelRequire
global declaration. Thanks for the idea @idanilt!
const gInsert = require('gulp-insert')
let parcelPatchTask = ()=>{
return gulp.src(p(paths.dist, '**/*.js'))
.pipe(gInsert.prepend(';var parcelRequire;\n'))
.pipe(gulp.dest(paths.dist))
}
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 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 the type
attribute in the HTML packager when we write the output bundle.
Thanks for clarifying the situation.
I understand this is not bug, but in design.
I think that instruction of βnot to use type=Moduleβ in README.md make this behavior clear for future users, and it will reduce further duplicated issues (type=Module will become common day by day.)
Yeah no. Check out https://central.eu It is a site I built using parcel and lit-element. The moment I remove type="module" I get weird errors all over the place.
@devongovett Stripping type="module" from <script type="module">
will break a lot of things.
@philkunz what errors? what things? We need details if we are to help you.
@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
@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 use type="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.
@a-p-f Yep, auto-stripping type="module"
is ready in PR #2872; just waiting for an unrelated fix #2842 which will stop the CI giving (probably) false negatives for all current PRs.
In the long term I still think it'd be handy for future-proofing to let Parcel's output require
scaffolding execute in an ES6 / ES module context [#2809], especially for your use-case where the source code should be totally valid/correct before introducing Parcel for production, but at least this should kick the can pretty far down the road.
How should I pack my library using Parcel for an ESM compatible loading ?
I want to do:
parcel index.js
then from an other project that is build-step-less do:
<script type="module>
import { Foo } from 'libraryBuildWithParcel.js';
</script>
without having this error ?
Uncaught ReferenceError: parcelRequire is not defined
or Uncaught SyntaxError: The requested module '/libraryBuildWithParcel.js' does not provide an export named 'Foo'
In the meantime I will use rollup with
rollup index.js --file libraryBuildWithParcel.js --format esm
@nestarz This will be possible with Parcel 2 (and it's already implemented).
Thanks, but what is the command then using parcel@v2 to build to an esm format ?
With alpha 2 (which should be released in the next couple of days), you can do
<script type="module" src="index.js">
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
{
"main": "dist/index.js",
"targets": {
"main": {
"outputFormat": "esmodule"
}
}
}
(and running something like parcel build src/index.js
)
Do you know why when I use the new alpha version to buld my module using the exact configuration you gave above and running parcel build src/index.js
I only get this into my index.es.js file :
function e(e){return e&&e.__esModule?e.default:e}e("/ComposableMap.b82f9cb5.vue"),e("/Geographies.14547339.vue"),e("/Geography.e35469fc.vue"),e("/Graticule.0838882e.vue"),e("/Sphere.d770e515.vue"),e("/Marker.d965d479.vue"),e("/Line.328080d5.vue"),e("/Annotation.01188279.vue");
@nestarz Vue support wasn't yet ported to Parcel 2: https://github.com/parcel-bundler/parcel/issues/3364
Can this issue and issue #4389 be merged?
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?
if you strip
Most helpful comment
Mainly for module resolution.
And for old browser users (ES module not supported, need Bundle.)