为什么我的 Babel-Loader 不能将我的供应商代码转换为对 IE8+ 有效?

Why isn't my Babel-Loader converting my vendor code to be valid for IE8+?

我在我的 Vue.js 应用程序中使用最新的 Webpack、Babel 和 Babel-Loader。

我试图在 IE 8、9 和 10 上使用我的代码 运行,但它没有。

问题是 IE10 及以下版本抱怨 const 是无效语法。我可以看到这是来自我的 vendors~index.bundle.js 文件。此文件包含不属于我的代码。

特别是,我可以看到 const 来自我正在使用的 Vue 插件 vue-snotify

为什么 babel 不能将我的供应商代码转换为对 IE10 及以下版本有效?

.babelrc

{
    "presets": [
        [
            "@babel/preset-env", {
                "useBuiltIns": "entry",
                "shippedProposals": true
            }
        ]
    ]
}

.browserslistrc

ie >= 8

.webpack.config.js

const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    mode: 'production',
    devtool: false,
    performance: {
        hints: false
    },
    entry: {
        index: './src/ui/index.js',
        style:'./src/ui/app.sass'
    },
    output: {
        path: path.resolve(__dirname, 'build/public/static'),
        filename: 'js/[name].bundle.js',
        chunkFilename: 'js/[name].bundle.js',
        publicPath: 'static/'
    },
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            },
            {
                test: /\.vue$/,
                exclude: '/node_modules/',
                loader: 'vue-loader'
            },
            {
                test: /\.pug$/,
                loader: 'pug-plain-loader'
            },
            {
                test: /\.sass$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            indentedSyntax: true
                        }
                    }
                ]
            },
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                loader: 'file-loader',
                options: {
                    name: '[hash].[ext]',
                    outputPath: 'assets/'
                }
            },
            {
                test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
                use: 'url-loader?limit=10000'
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        new CopyWebpackPlugin([
            { from: 'src/server/app', to: '../../app' },
            { from: 'src/server/public', to: '../' },
            { from: 'src/server/vendor', to: '../../vendor' }
        ])
    ],
    resolve: {
        alias: {
            '@components': path.resolve(__dirname, 'src/ui/components'),
            '@store': path.resolve(__dirname, 'src/ui/Store'),
            '@assets': path.resolve(__dirname, 'src/ui/assets')
        },
        extensions: ['.js', '.vue']
    }
}

我最近遇到了类似的问题。 This 文档可能会有用。

  1. 由于您在 presets 中使用 "useBuiltIns": "entry",请尝试在您的条目文件中使用 import '@babel/polyfill',例如main.js。但是,请注意这可能会添加未使用的 polyfill 并增加您的包大小。

This will import ALL polyfills based on your browserslist targets so that you don't need to worry about dependency polyfills anymore, but will likely increase your final bundle size with some unused polyfills

  1. 尝试 useBuiltIns: "usage" 并指定缺少的 polyfill,如下所示:

    module.exports = { presets: [ ['@vue/app', { useBuiltIns: "usage", polyfills: [ "es6.promise", "es6.symbol" ] }] ] };

  1. 尝试useBuiltIns: "usage"

automatically detects the polyfills needed based on the language features used in your source code. This ensures only the minimum amount of polyfills are included in your final bundle. However, this also means if one of your dependencies has specific requirements on polyfills, by default Babel won't be able to detect it.

这就是让我着迷的那个。因此,如果依赖项是用目标环境不支持的 ES 版本编写的,请将该依赖项添加到 vue.config.js 中的 transpileDependencies 选项。所以 vue.config.js 会有这个

module.exports = {
  transpileDependencies: [
    "vue-snotify"
  ]
}

至于 IE8,据我所知 vue github page

不支持

通常,鼓励包维护者打包不需要额外转译步骤或使用工具的源代码。 Babel 通过不转译位于 node_modules/ 子路径下的模块来强制执行此操作(也是为了避免引入支持或意外转译与 Babel 相关的源代码)。

这不是一个有效的解决方案,但它应该让您朝着正确的方向前进:

{
    test: /\.m?js$/,
    include: [
      path.resolve(__dirname, 'src'),    // Include your sources.
      require.resolve('vue-snotify')     // Include `vue-snotify` main module.
    ],
    loader: 'babel-loader',
    options: {
        // Babel has it's own defaults, so these have to be edited as well.
        include: [
            require.resolve('vue-snotify')
        ]
    }
}

您始终可以调试 Babel 并获取有关它跳过转译的源的信息,因为它们匹配忽略模式通过配置 debug when 运行:

DEBUG=babel* webpack

鉴于您现在的设置,如果您进行调试,Babel 永远不会收到 vue-snotify 的请求。所以第一步是实际看到 Babel 正在接收一个转译请求 vue-snotify 然后进一步配置 babel-loader 不忽略它的路径。