Skip to content
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

wip: set esbuild minify iife format #10495

Closed
wants to merge 1 commit into from

Conversation

fz6m
Copy link
Contributor

@fz6m fz6m commented Feb 13, 2023

在这个 issue privatenumber/esbuild-loader#139 中,为了解决 esbuild minify 污染全局变量问题,调整 format 为 iife ,我们也同步一下。

@vercel
Copy link

vercel bot commented Feb 13, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated
umi ⬜️ Ignored (Inspect) Feb 13, 2023 at 0:26AM (UTC)

@codecov
Copy link

codecov bot commented Feb 13, 2023

Codecov Report

Base: 29.59% // Head: 29.59% // No change to project coverage 👍

Coverage data is based on head (9a3a2d3) compared to base (3c5409b).
Patch has no changes to coverable lines.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #10495   +/-   ##
=======================================
  Coverage   29.59%   29.59%           
=======================================
  Files         446      446           
  Lines       13048    13048           
  Branches     3078     3078           
=======================================
  Hits         3862     3862           
  Misses       8543     8543           
  Partials      643      643           
Impacted Files Coverage Δ
...kages/bundler-webpack/src/config/compressPlugin.ts 31.91% <ø> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@sorrycc
Copy link
Member

sorrycc commented Feb 13, 2023

e2e breaks, 可能影响到哪里了。

@stormslowly
Copy link
Member

e2e breaks, 可能影响到哪里了。

mf 包默认构建类型是 global 的, 代码里面有 var mfName 这样的代码,原来预期是在全局变量。
现在加了 iife,就在闭包里面了。所以 mf 加载不到了。

可以绕过,lib 配置成 window 即可 , ref https://umijs.org/docs/max/mf#%E5%AF%BC%E5%87%BA%E8%BF%9C%E7%AB%AF%E6%A8%A1%E5%9D%97%E9%85%8D%E7%BD%AE

mf: {
    name: remoteMFName,
 
    // 可选,远端模块库类型, 如果模块需要在乾坤子应用中使用建议配置示例的值,
    // 注意这里的 name 必须和最终 MF 模块的 name 一致
    library: { type: "window", name: remoteMFName },
  },

@stormslowly
Copy link
Member

@fz6m 可能需要测试下是否和 external 的配置有冲突

externals: {
react: 'React'
}

@fz6m fz6m changed the title chore(minify): set esbuild minify iife format wip: set esbuild minify iife format Feb 13, 2023
@fz6m
Copy link
Contributor Author

fz6m commented Feb 15, 2023

因为 externals 存在 edge case ,mf 需要写额外的代码,先关闭了,后续有强烈诉求再讨论。

如果需要避免冲突,可手动配置:

jsMinifierOptions: {
  format: 'iife'
}

@fz6m fz6m closed this Feb 15, 2023
@stormslowly
Copy link
Member

我觉得 可以换个方式做,在 esbuild 压缩后手动的添加 iife。

mf 需要修改代码 我觉得问题不大,library type 默认到 window 我觉得也是一个合理的值。
或者 mf 插件自己提醒,如果是 esbuild 压缩 warning 需要用 window type。

命名冲突的危害比这这个小插件需要改配置的问题更大。

@stormslowly
Copy link
Member

stormslowly commented Feb 15, 2023

@xierenyuan show 下你之前的方案 抛玉引玉下

@xierenyuan
Copy link
Member

@xierenyuan show 下你之前的方案 抛玉引玉下

import {
  Compiler,
  ModuleFilenameHelpers,
  Compilation,
  sources,
  Asset,
} from '@umijs/bundler-webpack/compiled/webpack';
import MagicString from 'magic-string';

export class EsbuildMinifyFix {
  private name: string;
  constructor() {
    this.name = `EsbuildMinifyFix`;
  }

  apply(compiler: Compiler): void {
    compiler.hooks.compilation.tap(this.name, (compilation) => {
      compilation.hooks.processAssets.tapPromise(
        {
          name: this.name,
          stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
          additionalAssets: true,
        },
        (assets) => this.minifyFix(compiler, compilation, assets),
      );
    });
  }

  async minifyFix(
    compiler: Compiler,
    compilation: Compilation,
    assets: Record<string, sources.Source>,
  ) {
    const matchObject = ModuleFilenameHelpers.matchObject.bind(undefined, {
      include: [/\.(js|mjs|cjs)$/],
    });
    const cache = compilation.getCache('EsbuildMinifyFix');

    const { output } = compiler.options;

    // 只对默认情况情况, 非默认情况不处理这种情况
    if (typeof output.library?.type !== 'undefined') {
      return;
    }

    const assetsForMinify = await Promise.all(
      Object.keys(assets)
        .filter((name) => {
          if (!matchObject(name)) {
            return false;
          }

          const { info } = compilation.getAsset(name) || {};
          if (!info?.minimized) {
            return false;
          }

          return true;
        })
        .map(async (name) => {
          const { info, source } = compilation.getAsset(name) as Asset;

          const eTag = cache.getLazyHashedEtag(source);
          const cacheItem = cache.getItemCache(name, eTag);
          const output = await cacheItem.getPromise();

          return { name, info, inputSource: source, output, cacheItem };
        }),
    );

    if (assetsForMinify.length === 0) {
      return;
    }

    const { SourceMapSource, RawSource } = compiler.webpack.sources;

    console.log(compilation.entrypoints);

    for (const asset of assetsForMinify) {
      const { name, inputSource } = asset;
      const { source, map } = inputSource.sourceAndMap();

      let code = source;
      if (Buffer.isBuffer(code)) {
        code = code.toString();
      }

      console.time('MagicString start');
      const bundle = new MagicString(code);

      bundle.indent().prepend('!(function () {\n').append('}());');

      code = bundle.toString();

      console.timeEnd('MagicString start');

      const output: any = {};

      if (map) {
        output.source = new SourceMapSource(
          code,
          name,
          output.map,
          source,
          output.map,
          true,
        );
      } else {
        output.source = new RawSource(code);
      }

      compilation.updateAsset(name, output.source, {
        EsbuildMinifyFix: true,
      });
    }
  }
}

@stormslowly
Copy link
Member

nice!

可以观察下 压缩过 chunk 的特征,如果 chunk 没有被插 esbuild 的 polyfill 这个追加的操作就可以不做。

@lvisei
Copy link

lvisei commented Jul 14, 2023

遇到 esbuild minify 污染全局变量问题了,目前手动配置开启 format: 'iife',观望问题彻底解决~

@fz6m
Copy link
Contributor Author

fz6m commented Jul 14, 2023

可以升级到最新版本。由于 umi 4 默认用 esbuild 压缩代码,此时打开 esbuildMinifyIIFE: true 可以自动检测异步产物的变量冲突问题。

如果还有冲突情况无法解决,可以换其他的压缩器 jsMinifier

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants