Laravel Mix:为 IE11 兼容性配置 Babel(转换和 polyfill)

Laravel Mix: Configure Babel for IE11 compatibility (transformations and polyfills)

在使用 Laravel-Mix 4 并使用 Vue 预设的 Laravel 6 应用程序中,我需要编译我的 JavaScript 代码以兼容 IE11。这意味着为缺少的函数添加任何 polyfill,编译出箭头函数,等等。开箱即用,这还不算。

我的测试代码在resources/js/app.js:

//require('./bootstrap');
let test = [1, 2, [3, 4]];
console.log(
    test.flat().map((x) => 2*x)
);

使用默认配置,laravel mix 似乎不会编译 JavaScript 代码,而只会进行一些格式化。注释保留在编译输出中。

npm run dev的结果是:

       Asset      Size   Chunks             Chunk Names
/css/app.css   0 bytes  /js/app  [emitted]  /js/app
  /js/app.js  4.95 KiB  /js/app  [emitted]  /js/app

如何获得 Laravel-Mix 以使用 Babel 创建兼容 IE11 的源代码?

启用 Babel 编译 Laravel 混合使用 Internet Explorer 的 polyfills

第 1 步:安装 Corejs 以获取 polyfills

根据 babel-preset-env 2 的 Babeljs 文档,我们首先需要安装 core-js(包含 polyfill):

$ npm install core-js@3 --save

第 2 步:配置 .babelrc

在项目根目录创建一个.babelrc文件:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": {
                    "version": 3,
                    "proposals": false
                },
                "targets": {
                    "ie": "11"
                }
            }
        ]
    ]
}

现在 运行 npm run dev 你会发现插入了 polyfills,编译了箭头函数等 - 你的代码可能只是 运行 在 IE11 上!

Laravel-Mix、Babel、IE:一些陷阱

node_modules没有经过babel处理

使用默认配置,只有项目本身的源代码——而不是它的依赖项——运行通过 babel 编译步骤。这意味着依赖项中的任何 let 或类似内容都会使旧版浏览器失控 3.

使用“mix.babel”有编译文件两次的风险

laravel 混合文档建议使用 Vanilla JS 部分 1 中的 mix.babel 函数。这似乎是做什么的:

  • 如果没有.babelrc,指定的文件是运行通过babel。
  • 如果 .babelrc 存在,正常的 mix 编译步骤已经使用了 babel。使用 mix.babel 会导致编译步骤 运行 两次。

有趣的是,两次编译的代码在 IE 上没有 运行。一个问题是它将包含无法处理的 polyfill 的 require() 调用:

SCRIPT5009: 'require' is undefined

似乎有些使用 mix.babel(),但我认为与 react 兼容更好。我有类似的问题,我使用 babel-loader@babel/preset-env@babel/polyfill。不得不求助于 polyfill,因为我无法 core-js 3 按照他们的文档进行工作。所以如果有人能够弄清楚如何让它与 core-js 3 一起工作。我很乐意学习。并且只安装我的项目似乎需要的东西

安装:

npm install babel-loader @babel/preset-env @babel/polyfill --save

Webpack.mix.js

module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }

最后,在main/jsapp/js

开头导入
import '@babel/polyfill';

已在 Laravel 7.x | vue 2.6

上测试过

依赖关系:

"@babel/polyfill": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"babel-loader": "^8.1.0",

注意:我决定从根应用程序中完全删除 .babelrc,可能看起来没有效果,但如果我需要它,我更喜欢将它添加到 config.js

这就是我如何让我们的网页在 IE11 上运行。 我列出了所有与 Babel 相关的包,尽管其中一些只需要让 Jest 工作。

package.json

"devDependencies": {
  "@babel/core": "^7.10.5",
  "@babel/plugin-transform-runtime": "^7.10.5",
  "@babel/preset-env": "^7.10.4",
  "@babel/runtime-corejs3": "^7.10.5",
  "babel-core": "^7.0.0-bridge.0",
  "babel-jest": "^24.9.0",
},

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "bugfixes": true,
        "targets": ">0.25%",
        "corejs": {
          "version": 3,
          "proposals": false
        }
      }
    ]
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", { "corejs": 3 }]
  ]
}

最后

app.js

import './bootstrap';
import "core-js";
import Vue from 'vue';
// ...

我必须说我对 useBuiltIns 属性 感到困惑,因为不同的文章指向不同的方向。看起来如果你使用 "useBuiltIns": "usage" 你不需要在 app.js 中导入 core-js,无论如何我已经尝试了不同的组合并且这个工作正常。

根据 readme of core-js you need to import it, but I'm not 100% sure. Other resources that pointed me to the right directions were those two articles: https://www.valentinog.com/blog/preset-env/ and https://web.dev/serve-modern-code-to-modern-browsers/.

完成此设置后,我们只需要更新一些 CSS 应用即可 运行。唯一的缺点是 vendor.js 文件很重。我想为支持模块的浏览器创建一个不同的包,但那是另一回事...