使webpack的库输出与babel6兼容

时间:2015-11-12 18:40:05

标签: javascript ecmascript-6 webpack babeljs

Babel的第6个版本更改了export default的功能,特别是它与commonjs require的关系。

总结一下,直到babel5,require('module')给出模块的默认导出,它现在总是返回包含模块所有导出的模块对象。 如果只想要默认值,他/她必须使用require('module').defaultAs explained here, there is very good reasons behind this这个问题的目的不是打破或破解这种行为。

但是,如果正在构建库,他/她通常不希望分发模块,而是分发其库的导出值(例如,函数,内部使用的模块系统)。 使用webpackcommonjs时,AMDoutput.library配置可以很好地解决这个问题。因为先前的babel版本允许使用commonjs进行默认导出,所以babel也与此机制兼容。但事实并非如此:库现在总是提供es6模块对象。

这是一个例子。

的src / main.js

export default "my lib content";

webpack.config.js

var path = require("path");
var webpack = require("webpack");

module.exports = {
  entry: {
    lib: [ path.resolve(__dirname, "src/main.js") ],
  },
  output: {
    path: path.join(__dirname, "dist"),
    filename: "mylib-build.js",
    library: 'myLib'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: "babel",
        include: path.join(__dirname, "src"),
        query: { presets: ['es2015'] }
      }
    ]
  }
};

的test.html

<html>
<head></head>
<body>
<script src="dist/mylib-build.js"></script>
<!-- `myLib` will be attached to `window` -->
<script>
  console.log(JSON.stringify(myLib)); // { default: "my lib content" }
</script>
</body>
</html>

这是一个非常简单的示例,但我显然希望将mylib导出为字符串"my lib content"而不是{ default: "my lib content" }

一种解决方案可能是在commonjs中创建导出源文件以执行转换:

module.exports = require('./main').default;

但是我觉得这个解决方案很差。一个人应该能够在编译级别解决它,而无需更改源代码。 有什么想法吗?

3 个答案:

答案 0 :(得分:6)

就是我的自我。无论是喜欢称之为变通方法还是解决方案,似乎都有一个Babel插件可以解决它#34;。

使用babel-plugin-add-module-exports

中引用的插件https://stackoverflow.com/a/34778391/1592572

示例配置

var webpackOptions = {
    entry: {
        Lib1: './src/Lib1.js',
        Lib2: './src/Lib2.js'
    },
    output: {
        filename: "Master.[name].js",
        library: ["Master","[name]"],
        libraryTarget: "var"
    },
    module: {
        loaders: [
            {
                loader: 'babel',
                query: {
                    presets: ['es2015'],
                    plugins: ["add-module-exports"]
                }
            }
        ]
    }
};

这会使Master.Lib1成为lib1而不是Master.Lib1.default

答案 1 :(得分:3)

Webpack 2现在支持es6模块,它们可以部分解决这个问题。 Migrating from webpack 1 to webpack 2相对无痛。只需要记住disable babel's es6 module to commonjs conversion来完成这项工作:

<强> .babelrc

{
  "presets": [
    ["es2015", {"modules": false}]
  ]
}

然而,遗憾的是,它在导出默认值时无效(但是an issue is opened,希望最终会发布解决方案。)

修改

好消息! Webpack 3支持output.libraryExport选项,可用于直接公开默认导出:

var path = require("path");
var webpack = require("webpack");

module.exports = {
  entry: {
    lib: [ path.resolve(__dirname, "src/main.js") ],
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "mylib-build.js",
    library: "myLib",
    // Expose the default export.
    libraryExport: "default"
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: "babel",
        include: path.resolve(__dirname, "src")
      }
    ]
  }
};

答案 2 :(得分:-1)

您可以使用此解决方案(这更像是一种解决方法,但它可以让您避免更改源代码):

有一个名为callback-loader的加载程序。它允许您通过调用回调来更改构建时的源,并将结果放在其中而不是它。换句话说,您可以在构建时自动将require('module')变为require('module').default

以下是您的配置:

var webpackConfig = {
    module: {
        loaders: [
            { test: /\.js$/, exclude: /node_modules/, loader: 'callback' },
            ...
        ]
    },
    ...
    callbackLoader: {
        require: function() {
            return 'require("' + Array.prototype.join.call(arguments, ',') + '").default';
        }
    }
};