swc icon indicating copy to clipboard operation
swc copied to clipboard

minifier: `toplevel = false` should prevent operations related to `unused`

Open morriq opened this issue 3 years ago • 10 comments

Describe the bug

I'm using webpack 5.65.0 with such part:

    output: {
      filename: '[name].[contenthash].bundle.js',
      library: 'application',
      publicPath: 'auto',
    },

before 1.2.169 it works well calling window.application in index.html but in 1.2.169 it prints

application is not defined

window has content of application var but in ... a variable. so it stopped respecting library: 'application', and keep content of it in window.a

Input code

No response

Config

{
  "jsc": {
    "parser": {
      "tsx": true,
      "syntax": "typescript",
      "dynamicImport": true
    },
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    }
  }
}

Playground link

No response

Expected behavior

swc/core respects webpack's library: 'application',

Actual behavior

1.2.169 stopped respecting library: 'application', and keep content of it in window.a

Version

1.2.169

Additional context

No response

morriq avatar Apr 20 '22 22:04 morriq

Can you some basic information which can be used to reproduce?

kdy1 avatar Apr 21 '22 01:04 kdy1

FYI, swc has nothing to do with library: 'application' I didn't know the option before looking at the issue

kdy1 avatar Apr 21 '22 11:04 kdy1

@kdy1

https://github.com/morriq/swc-4386

this way is fine? I put instruction in README

morriq avatar Apr 21 '22 19:04 morriq

try

// webpack.config.js
        new TerserPlugin({
          minify: TerserPlugin.swcMinify,
          terserOptions: {
            compress: {
              arrows: false,
              conditionals: false,
              evaluate: false,
            },
            mangle: {
              topLevel: false
            },
          },
        }),

I think is caused by #4366, which we make mangle.toplevel defaults to true (and didn't update doc).

import { minify } from "@swc/core";
minify(
  `
var application;
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "bootstrap": () => (/* binding */ bootstrap)
/* harmony export */ });
function bootstrap() {
    alert();
}

application = __webpack_exports__;
/******/ })()
;
`,
  {
    compress: {
      arrows: false,
      conditionals: false,
      evaluate: false,
    },
    ecma: 2015,
    mangle: true,
    module: false,
    sourceMap: undefined,
  }
).then((o) => console.log(o));

in 1.2.168, it output

 var application;(()=>{"use strict";var a={};a.d=(d,c)=>{for(var b in c)a.o(c,b)&&!a.o(d,b)&&Object.defineProperty(d,b,{enumerable:!0,get:c[b]})},a.o=(a,b)=>Object.prototype.hasOwnProperty.call(a,b),a.r=a=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})};var b={};function c(){alert()}a.r(b),a.d(b,{bootstrap:()=>c}),application=b})()

in 1.2.169

var a;(()=>{"use strict";var b={};b.d=(d,c)=>{for(var a in c)b.o(c,a)&&!b.o(d,a)&&Object.defineProperty(d,a,{enumerable:!0,get:c[a]})},b.o=(a,b)=>Object.prototype.hasOwnProperty.call(a,b),b.r=a=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})};var c={};function d(){alert()}b.r(c),b.d(c,{bootstrap:()=>d}),a=c})()

RiESAEX avatar Apr 30 '22 08:04 RiESAEX

Sounds reasonable I'll update the doc

kdy1 avatar Apr 30 '22 12:04 kdy1

thanks @RiESAEX . this is it.

morriq avatar May 06 '22 17:05 morriq

Hello :),

In 247 it's the same issue. I was using 246 so it's caused between two patches. but checking commit history I'm not sure what's causing it.

https://github.com/swc-project/swc/compare/v1.2.246...v1.2.247

morriq avatar Sep 05 '22 19:09 morriq

@kdy1 @RiESAEX I bumped PoC repo: https://github.com/morriq/swc-4386

morriq avatar Sep 05 '22 19:09 morriq

make compress.unused = false, can solve the problem, But I don't think it is correct answer.

import { minify } from "@swc/core";
minify(
  `var application;
/******/ (() => { // webpackBootstrap/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "bootstrap": () => (/* binding */ bootstrap)
/* harmony export */ });
function bootstrap() {
    alert();
}

application = __webpack_exports__;
/******/ })()
;` 
  ,
    {
      compress: {
        arrows: false,
        conditionals: false,
        evaluate: false,
      },
      ecma: 2015,
      mangle: false,
      module: false,
      sourceMap: undefined,
    }
  ).then((o) => console.log(o.code));

output

var application;
(() => {
  "use strict";
  var __webpack_require__ = {};
  (__webpack_require__.d = (exports, definition) => {
    for (var key in definition)
      __webpack_require__.o(definition, key) &&
        !__webpack_require__.o(exports, key) &&
        Object.defineProperty(exports, key, {
          enumerable: !0,
          get: definition[key],
        });
  }),
    (__webpack_require__.o = (obj, prop) =>
      Object.prototype.hasOwnProperty.call(obj, prop)),
    (__webpack_require__.r = (exports) => {
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }),
        Object.defineProperty(exports, "__esModule", { value: !0 });
    });
  var __webpack_exports__ = {};
  function bootstrap() {
    alert();
  }
  __webpack_require__.r(__webpack_exports__),
    __webpack_require__.d(__webpack_exports__, { bootstrap: () => bootstrap });
})();

application = __webpack_exports__; is removed, I think we should keep it if compress.toplevel = false.

RiESAEX avatar Sep 06 '22 02:09 RiESAEX

Yeah I agree, so this is a bug of minifier?

kdy1 avatar Sep 06 '22 02:09 kdy1

I reread the docs. Since all files are treated as module, I think the var application; and application = __webpack_exports__;should be dropped. terser will drop them if module: true.

RiESAEX avatar Oct 01 '22 13:10 RiESAEX

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

swc-bot avatar Feb 10 '23 12:02 swc-bot