-
-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug: minifier used to transpile pollutes global scope with helper methods #139
Comments
I don't know the exact issue but I want to say that esbuild minification under the hook isn't completely stable right now, and your problem might be fixed if this package updates to the latest esbuild compiler. But I would recommend that if you find a version of esbuild-loader that works for you do not upgraded until esbuild reaches a stable version 1.0.0 |
I had to install I created an <!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/jquery@3.6.0/dist/jquery.js"></script>
<script src="./js/index.js"></script>
</head>
<body>
</body>
</html> and spun it up with Can you double check? And if it's still happening, please provide more reproduction steps and paste the error stack. |
I can confirm that this is a problem, it can show up when ESBuildMinifyPlugin is run on multiple bundles somehow (chunk splitting, multiple entry points, whatever). The problem isn't really that it interferes with jQuery—that's a byproduct—it's that ESBuild writes helpers with This is fine for modules, but for scripts (bundles) that scope is the global scope. ESBuild's transform API is only meant to run on modules. Anyone shipping only one bundle will be unaffected by this global scope pollution, but anyone using multiple bundles can run into a situation where the helper variables in each asset conflict, and since they are declared with Example: // bundle 1
var et = Object.defineProperty;
var ke = Object.prototype.hasOwnProperty;
var Fe = Object.getOwnPropertySymbols,
$e = Object.prototype.propertyIsEnumerable;
var qe = (s, o, e) => (o in s ? et(s, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : (s[o] = e)),
V = (s, o) => {
for (var e in o || (o = {})) ke.call(o, e) && qe(s, e, o[e]);
if (Fe) for (var e of Fe(o)) $e.call(o, e) && qe(s, e, o[e]);
return s;
};
/* ... */
// bundle 2
var _t = Object.defineProperty;
var He = Object.prototype.hasOwnProperty;
var ue = Object.getOwnPropertySymbols,
Fe = Object.prototype.propertyIsEnumerable;
var Xe = (n, r, e) => (r in n ? _t(n, r, { enumerable: !0, configurable: !0, writable: !0, value: e }) : (n[r] = e)),
ee = (n, r) => {
for (var e in r || (r = {})) He.call(r, e) && Xe(n, e, r[e]);
if (ue) for (var e of ue(r)) Fe.call(r, e) && Xe(n, e, r[e]);
return n;
};
/* ... */ Notice how My recommendation for script assets is to wrap ESBuild's full transform output in an IIFE. We'll have to use I'm willing to help contribute a PR for this. I'd love to get a fixed merged quickly so I can keep using this plugin. Thanks for all your work on it. |
Yes, please provide a minimal reproduction. The above reproduction seems to be working fine for me. |
Sorry, I meant "PR", not "MR". I will spin up a repository to try to reproduce, but keep in mind it's only a problem when ESBuild generates helper variables with the same name that are assigned different values, and while that should be deterministic it may be hard to reproduce on purpose. |
Good news, I found a simple workaround! Using new ESBuildMinifyPlugin({
...otherOptions,
format: 'iife'
}) wraps ESBuild's helpers in an IIFE to prevent these global variable conflicts. I personally would vouch for this to be the default, as it is ESBuild's default format when bundling for the web, but will leave that decision to the maintainers. |
@joshwilsonvu I can confirm that solved my problem. |
I was finally able to reproduce this. This happens in situations where the minifier is used to transpile instead of the loader. The helpers are injected top-level outside of the module closures. In this example, two output chunks declare the same variable Inputwebpack.config.js const path = require('path');
const { ESBuildMinifyPlugin } = require('esbuild-loader');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
clean: true,
path: path.resolve(__dirname, `./dist/`),
},
optimization: {
minimizer: [
new ESBuildMinifyPlugin({
target: 'es2015',
}),
],
},
}; src/a.js export default async () => {}; src/b.js console.log(1 ** 1);
(async () => {});
const y = {};
const {...z} = {...y};
try {
throw new Error();
} catch {}
console.log(y?.d, y?.d ?? ''); Outputmain.js (()=>{var b={},g={};function r(e){var i=g[e];if(i!==void 0)return i.exports;var t=g[e]={exports:{}};return b[e](t,t.exports,r),t.exports}r.m=b,(()=>{var e=Object.getPrototypeOf?t=>Object.getPrototypeOf(t):t=>t.__proto__,i;r.t=function(t,o){if(o&1&&(t=this(t)),o&8||typeof t=="object"&&t&&(o&4&&t.__esModule||o&16&&typeof t.then=="function"))return t;var c=Object.create(null);r.r(c);var a={};i=i||[null,e({}),e([]),e(e)];for(var n=o&2&&t;typeof n=="object"&&!~i.indexOf(n);n=e(n))Object.getOwnPropertyNames(n).forEach(l=>a[l]=()=>t[l]);return a.default=()=>t,r.d(c,a),c}})(),(()=>{r.d=(e,i)=>{for(var t in i)r.o(i,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:i[t]})}})(),(()=>{r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((i,t)=>(r.f[t](e,i),i),[]))})(),(()=>{r.u=e=>""+e+".js"})(),(()=>{r.g=function(){if(typeof globalThis=="object")return globalThis;try{return this||new Function("return this")()}catch(e){if(typeof window=="object")return window}}()})(),(()=>{r.o=(e,i)=>Object.prototype.hasOwnProperty.call(e,i)})(),(()=>{var e={},i="minification-bug:";r.l=(t,o,c,a)=>{if(e[t]){e[t].push(o);return}var n,l;if(c!==void 0)for(var u=document.getElementsByTagName("script"),p=0;p<u.length;p++){var f=u[p];if(f.getAttribute("src")==t||f.getAttribute("data-webpack")==i+c){n=f;break}}n||(l=!0,n=document.createElement("script"),n.charset="utf-8",n.timeout=120,r.nc&&n.setAttribute("nonce",r.nc),n.setAttribute("data-webpack",i+c),n.src=t),e[t]=[o];var s=(h,m)=>{n.onerror=n.onload=null,clearTimeout(d);var _=e[t];if(delete e[t],n.parentNode&&n.parentNode.removeChild(n),_&&_.forEach(v=>v(m)),h)return h(m)},d=setTimeout(s.bind(null,void 0,{type:"timeout",target:n}),12e4);n.onerror=s.bind(null,n.onerror),n.onload=s.bind(null,n.onload),l&&document.head.appendChild(n)}})(),(()=>{r.r=e=>{typeof Symbol!="undefined"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}})(),(()=>{var e;r.g.importScripts&&(e=r.g.location+"");var i=r.g.document;if(!e&&i&&(i.currentScript&&(e=i.currentScript.src),!e)){var t=i.getElementsByTagName("script");t.length&&(e=t[t.length-1].src)}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r.p=e})(),(()=>{var e={179:0};r.f.j=(o,c)=>{var a=r.o(e,o)?e[o]:void 0;if(a!==0)if(a)c.push(a[2]);else{var n=new Promise((f,s)=>a=e[o]=[f,s]);c.push(a[2]=n);var l=r.p+r.u(o),u=new Error,p=f=>{if(r.o(e,o)&&(a=e[o],a!==0&&(e[o]=void 0),a)){var s=f&&(f.type==="load"?"missing":f.type),d=f&&f.target&&f.target.src;u.message="Loading chunk "+o+` failed.
(`+s+": "+d+")",u.name="ChunkLoadError",u.type=s,u.request=d,a[1](u)}};r.l(l,p,"chunk-"+o,o)}};var i=(o,c)=>{var[a,n,l]=c,u,p,f=0;for(u in n)r.o(n,u)&&(r.m[u]=n[u]);if(l)var s=l(r);for(o&&o(c);f<a.length;f++)p=a[f],r.o(e,p)&&e[p]&&e[p][0](),e[a[f]]=0},t=self.webpackChunkminification_bug=self.webpackChunkminification_bug||[];t.forEach(i.bind(null,0)),t.push=i.bind(null,t.push.bind(t))})();var w={};r.e(85).then(r.bind(r,85)),r.e(326).then(r.t.bind(r,326,23))})(); 85.js var d=(f,i,n)=>new Promise((s,t)=>{var e=u=>{try{c(n.next(u))}catch(a){t(a)}},l=u=>{try{c(n.throw(u))}catch(a){t(a)}},c=u=>u.done?s(u.value):Promise.resolve(u.value).then(e,l);c((n=n.apply(f,i)).next())});(self.webpackChunkminification_bug=self.webpackChunkminification_bug||[]).push([[85],{85:(f,i,n)=>{"use strict";n.r(i),n.d(i,{default:()=>s});const s=()=>d(this,null,function*(){})}}]); 326.js var d=Object.defineProperty;var h=Object.prototype.hasOwnProperty;var e=Object.getOwnPropertySymbols,r=Object.prototype.propertyIsEnumerable,u=Math.pow,b=(n,c,o)=>c in n?d(n,c,{enumerable:!0,configurable:!0,writable:!0,value:o}):n[c]=o,f=(n,c)=>{for(var o in c||(c={}))h.call(c,o)&&b(n,o,c[o]);if(e)for(var o of e(c))r.call(c,o)&&b(n,o,c[o]);return n};var g=(n,c)=>{var o={};for(var i in n)h.call(n,i)&&c.indexOf(i)<0&&(o[i]=n[i]);if(n!=null&&e)for(var i of e(n))c.indexOf(i)<0&&r.call(n,i)&&(o[i]=n[i]);return o};var k=(n,c,o)=>new Promise((i,l)=>{var w=s=>{try{t(o.next(s))}catch(a){l(a)}},p=s=>{try{t(o.throw(s))}catch(a){l(a)}},t=s=>s.done?i(s.value):Promise.resolve(s.value).then(w,p);t((o=o.apply(n,c)).next())});(self.webpackChunkminification_bug=self.webpackChunkminification_bug||[]).push([[326],{326:()=>{var o;console.log(u(1,1));const n={},c=g(f({},n),[]);try{throw new Error}catch(i){}console.log(n==null?void 0:n.d,(o=n==null?void 0:n.d)!=null?o:"")}}]); |
@privatenumber will you fix it? It's horrible, I've got intersection with Generated minified code (by var _ = (r,p)=>{
var n = {};
for (var o in r)
L.call(r, o) && p.indexOf(o) < 0 && (n[o] = r[o]);
if (r != null && f)
for (var o of f(r))
p.indexOf(o) < 0 && W.call(r, o) && (n[o] = r[o]);
return n
}
; How it used: // ...
s = _(i, ["children"]) // { children, ...props } Spent about 2 hours to get what's going on. Fixed by ejecting {
test: /\.jsx?$/,
parser: { amd: false },
}, So... UPD: Sorry, I've missed this comment (#139 (comment)) |
@joshwilsonvu Our saviour, this had us pulling our hair out - thanks so much! Would certainly be in favour of this being the default for the library to save the next poor souls 👻 |
I've got another problem with |
Bug description
Hi!
I am using esbuild-loader for my project with jQuery (jQuery is an external) and bootstrap 4.
While webpack is creating chunks for dynamic imports with production build, it crates weird variable assign.
I am importing bootstrap dropdown dynamically on action. In minified chunk file it creates assing
var $=Object.getOwnPropertySymbols
with global scope. Which brakes my jQuery after file being imported.I made minification with
TerserWebpackPlugin
and everything works fine.Reproduction steps
I made repository with simple webpack config to reproduce the problem. https://github.com/Oksydan/esbuild-loader-bug
Chunk with id 3 is made from bootstrap dropdown. You can find there that
var $=Object.getOwnPropertySymbols
.Environment
The text was updated successfully, but these errors were encountered: