关于babel-core 编译插件的使用,想请教一下这里编译后的代码为何会把index-browser.js 编译进去?

如题,我想使用babel-core插件实现一个简单的编译es6代码的demo,代码如下:

src/main.js

var babel = require("@babel/core");
let code = `
    let a = 1;
    let b = 2
    let add = (a, b) => {
        return a + b
    } 
    var list = [1, 2, 3, 4, 5];
    for (item of list) {
        add(item, a)
    }
`
var babelOptions = {
    "presets": ["env"]
}
let result = babel.transform(code, babelOptions, function(err, result) {
    console.log('tranform result:', result, err)
});
console.log(result)

此main.js会由webpack进行打包编译,webpack的配置如下:
webpack.config.js

var HtmlWebpackPlugin = require('html-webpack-plugin')
var VueLoaderPlugin = require('vue-loader/lib/plugin');

var path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin')

var rootPath = path.resolve(__dirname, './')
module.exports = {
    entry: {
        main: './src/main.js'
    },
    output: {
        path: rootPath + '/dist/',
        filename: '[name].js?[chunkhash]'
    },
    resolve: {
        extensions: ['.js', '.json', '.less', '.ejs'],
        alias: {
            '@bootstrap': path.resolve(rootPath, './node_modules/bootstrap/dist'),
        }
    },
    node: {
        fs: 'empty'
    },
    plugins: [
        new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
            filename: 'main.html',
            template: './template/index.html',
            inject: 'body',
            hash: false,
            minify: {
                removeComments: true,
                collapseWhitespace: false
            },
            chunksSortMode: 'dependency'
        })
    ],
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
                loader: 'babel-loader'
            }
        },
        {
            test: /\.vue$/,
            use: ['vue-loader']
        },
        {
            test: /\.ejs$/,
            use: 'ejs-loader'
        },
        {
            test: /\.css$/,
            use: ["style-loader", {loader: 'css-loader', options: {minimize: true}}, 'postcss-loader']
        },
        {
            test: /\.less$/,
            use: ["style-loader", {loader: 'css-loader', options: {minimize: true}}, 'postcss-loader', 'less-loader']
        },
        {
            test: /\.(png|jpg|gif)$/,
            use: 'url-loader?limit=500000'
        },
        {
            test: /\.(ttf|svg|eot|woff|woff2)$/,
            use: ['file-loader']
        }
        ]
    }
}

打包过程一切顺利,奈何当脚本放到浏览器运行后收到错误信息:

Error: Cannot load preset @babel/preset-env relative to / in a browser

经过一番彻查后发现错误信息是这个方法抛出的:
@babel/core/config/files/index-browser.js

function loadPreset(name, dirname) {
  throw new Error(`Cannot load preset ${name} relative to ${dirname} in a browser`);
}

此时的函数调用栈是:

loadPreset (@babel/core/config/files/index-browser.js) // 抛异常
createDescriptor (@babel/core/lib/config/config-descriptors.js)

但是问题就出在这个index-browser.js文件里,查看config-descriptors.js文件源代码后发现,对loadPreset方法的引用是基于require("./files")这部操作

@babel/core/lib/config/config-descriptors.js

    ...
    ...
var _files = require("./files");
    ...
    ...
const resolver = type === "plugin" ? _files.loadPlugin : _files.loadPreset;

显然按照常理应该调用的是@babel/core/config/files/index.js 中暴露出的的loadPreset方法才对。
而通过查看webpack编译后的代码发现,var _files = require("./files")这部操作webpack实际是把@babel/core/config/files/index-browser.js给引入进来了

clipboard.png
为了找到原因,我把@babel/core的package.json查了一下,发现有如下配置项:
@babel/core/package.json

"browser": {
    "./lib/config/files/index.js": "./lib/config/files/index-browser.js",
    "./lib/transform-file.js": "./lib/transform-file-browser.js"
  },

顺带网上搜了一下package.json的browser字段的含义

browser指定该模板供浏览器使用的版本。Browserify这样的浏览器打包工具,通过它就知道该打包那个文件。

可是个人还是十分困惑,自己的main.js是通过webpack进行编译的,编译过程是在node环境中进行的,可怎么就和browser扯上了呢?导致本该导入files/index.js,结果被替换为files/index-browser.js?
为了验证自己的看法我把main.js 单独用node main.js进行运行,发现仍然报这个错误,为什么就会把index-browser给导入进来了呢?

执行node main.js结果:
clipboard.png

阅读 2.7k
2 个回答
var babel = require("@babel/core");
require("@babel/preset-env");
let code = `
    let a = 1;
    let b = 2
    let add = (a, b) => {
        return a + b
    } 
    var list = [1, 2, 3, 4, 5];
    for (item of list) {
        add(item, a)
    }
`;
var babelOptions = {
  presets: ["@babel/env"]
};
let result = babel.transform(code, babelOptions, function(err, result) {
  console.log("tranform result:", result, err);
});
console.log(result);

https://codesandbox.io/s/407o...
我这边用上面的代码测试下来是没问题的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题