question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

bug: minifier used to transpile pollutes global scope with helper methods

See original GitHub issue

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

  • esbuild-loader version: 2.9.1
  • Webpack version: 4.46.0
  • Operating System: macOS Catalina 10.15.7
  • Node version: 15.5.1
  • Package manager (npm/yarn/pnpm) and version: npm 7.7.4

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:2
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

9reactions
joshwilsonvucommented, Apr 14, 2021

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.

2reactions
privatenumbercommented, May 1, 2021

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 d to the global scope:

Input

webpack.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 ?? '');
Output

main.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:"")}}]);
Read more comments on GitHub >

github_iconTop Results From Across the Web

azu on Twitter: "見てる: "bug: minifier used to transpile pollutes ...
github.combug : minifier used to transpile pollutes global scope with helper methods · Issue #139 · privaten...Bug description Hi! I am using esbuild-loader ......
Read more >
@esbuild/linux-loong64 | Yarn - Package Manager
This is the Linux LoongArch 64-bit binary for esbuild, a JavaScript bundler and minifier. See https://github.com/evanw/esbuild for details.
Read more >
7.10.0 Released: Class Fields in preset-env, '#private in ...
By using @babel/plugin-transform-runtime , Babel will inject ponyfills (which are "pure" and don't pollute the global scope) for every used ...
Read more >
CoffeeScript
If you plan to use the --transpile option (see Transpilation) you will need to also install @babel/core either globally or locally, depending on...
Read more >
rollup.js
js and webpack, you can use Rollup to compile to UMD or CommonJS format, and then point to that compiled version with the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found