使 webpack 的库输出与 babel6 兼容
Make webpack's library output compatible with babel6
Babel 的第 6 版改变了 export default
的功能,特别是它与 commonjs 的关系 require
.
总而言之,在 babel5 之前,require('module')
提供模块的默认导出,现在它总是 returns 包含模块所有导出的模块对象。
如果只想要默认值,he/she 必须使用 require('module').default
。
这个问题的目的不是破坏或破解这种行为。
但是,如果一个人正在构建一个库,he/she 通常不想分发一个模块,而是分发他的库的导出值(例如,一个函数,无论内部使用什么模块系统)。
webpack and the output.library
configuration when using commonjs or AMD 很好地解决了这个问题。因为以前的 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;
但是我觉得这个解决方案很差。人们应该能够在编译级别解决它,而无需更改源代码。
有什么想法吗?
您可以使用此解决方案(这更像是解决方法,但它可以让您避免更改源):
有一个名为 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';
}
}
};
我自己就是这么做的。无论人们喜欢称之为解决方法还是解决方案,似乎都有一个 Babel 插件 "solve it".
使用插件babel-plugin-add-module-exports as referenced in
示例配置
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
。
Webpack 2 now supports es6 modules which partially solves this issue. Migrating from webpack 1 to webpack 2 is relatively painless. One just need to remember to 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")
}
]
}
};
Babel 的第 6 版改变了 export default
的功能,特别是它与 commonjs 的关系 require
.
总而言之,在 babel5 之前,require('module')
提供模块的默认导出,现在它总是 returns 包含模块所有导出的模块对象。
如果只想要默认值,he/she 必须使用 require('module').default
。
但是,如果一个人正在构建一个库,he/she 通常不想分发一个模块,而是分发他的库的导出值(例如,一个函数,无论内部使用什么模块系统)。
webpack and the output.library
configuration when using commonjs or AMD 很好地解决了这个问题。因为以前的 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;
但是我觉得这个解决方案很差。人们应该能够在编译级别解决它,而无需更改源代码。 有什么想法吗?
您可以使用此解决方案(这更像是解决方法,但它可以让您避免更改源):
有一个名为 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';
}
}
};
我自己就是这么做的。无论人们喜欢称之为解决方法还是解决方案,似乎都有一个 Babel 插件 "solve it".
使用插件babel-plugin-add-module-exports as referenced in
示例配置
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
。
Webpack 2 now supports es6 modules which partially solves this issue. Migrating from webpack 1 to webpack 2 is relatively painless. One just need to remember to 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")
}
]
}
};