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

globalThis is not defined #114

Open
cklwblove opened this issue Jan 6, 2023 · 0 comments
Open

globalThis is not defined #114

cklwblove opened this issue Jan 6, 2023 · 0 comments

Comments

@cklwblove
Copy link
Owner

cklwblove commented Jan 6, 2023

问题现象

在使用 vite 工具打包应用程序的时候,出现了 glolbaThis is not defined 的错误。

image

出现问题的设备信息如下:
image

问题原因

经查相关资料,globalThis 的特性是 chrome 71 版本后才支持的。
image
因此,如果需要支持低于 71 版本的浏览器,需要添加对应的垫片处理。

解决方案

方案1

html 文件头部添加

<head>
    <script>
        this.globalThis || (this.globalThis = this);
       // or
       // if (globalThis === undefined) {
       //       var globalThis = window;
       //     }
    </script>
    ...
</head>
(function() {
  if (typeof globalThis === "object") return;
  Object.defineProperty(Object.prototype, "__magic__", {
    get: function() {
      return this;
    },
    configurable: true // This makes it possible to `delete` the getter later.
  });
  __magic__.globalThis = __magic__; // lolwat
  delete Object.prototype.__magic__;
})();

// Your code can use `globalThis` now.

console.log(globalThis);

弊端在于:修改Object,Object.defineProperty或Object.prototype .__ defineGetter__可能会破坏 polyfill。

方案2

安装 globalThis 的 npm 包

npm install globalthis

main.js 文件里添加以下代码

import 'globalthis/auto';

方案3

在 vite 的插件 @vitejs/plugin-legacy 里添加配置

// vite.config.js
import legacy from https://github.com/vitejs/vite/tree/master/packages/plugin-legacy;

export default defineConfig({
  // For production build environments only
  build: {
    target: 'es2015',
  },
  plugins: [
    // For production build environments only
    legacy({
      targets: ['chrome >= 64', 'edge >= 79', 'safari >= 11.1', 'firefox >= 67'],
      ignoreBrowserslistConfig: true,
      renderLegacyChunks: false,
      /**
       * Polyfills required by modern browsers
       *
       * Since some low-version modern browsers do not support the new syntax
       * You need to load polyfills corresponding to the syntax to be compatible
       * At build, all required polyfills are packaged according to the target browser version range
       * But when the page is accessed, only the required part is loaded depending on the browser version
       *
       * Two configuration methods:
       *
       * 1. true
       *  - Automatically load all required polyfills based on the target browser version range
       *  - Demerit: will introduce polyfills that are not needed by modern browsers in higher versions,
       *    as well as more aggressive polyfills.
       *
       * 2、string[]
       *  - Add low-version browser polyfills as needed
       *  - Demerit: It needs to be added manually, which is inflexible;
       *    it will be discovered after the production is deployed, resulting in production failure! ! !
       */
      modernPolyfills: ['es/global-this'],
      //  or
      // modernPolyfills: true,
    }),
  ],
});

推荐 3 解决方案。


vite 构建打包的底层是依赖于 rollup 的,rollup 针对 top-level this 的赋值时有个配置项 context,默认值是 undefined。但 vite build 的包却是 globalThis。原因找到了,可以看链接。vite 重新赋值为 globalThis 了。
因此还有一种解决方案,其实不用添加针对 globalThis 的垫片。

// vite.config.js
export default defineConfig({
  plugins: [
    vue(),
    legacy({
      targets: ['chrome 78'],
      ignoreBrowserslistConfig: false
    }),
  ],
  build: {
    minify: false,
   // 重新赋值为 undefined 即可。
    rollupOptions: {
      context: 'undefined'
    }
  },
})
// input
var __assign = (this && this.__assign) || function () {
  __assign = Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
      s = arguments[i];
      for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
        t[p] = s[p];
    }
    return t;
  };
  return __assign.apply(this, arguments);
};
// output
var __assign = function() {
  __assign = Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
      s = arguments[i];
      for (var p2 in s)
        if (Object.prototype.hasOwnProperty.call(s, p2))
          t[p2] = s[p2];
    }
    return t;
  };
  return __assign.apply(this, arguments);
};

参考

  1. https://blog.fundebug.com/2020/02/17/detail_about_globalthis/
  2. https://juejin.cn/post/7028740836842012702
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

No branches or pull requests

1 participant