带有 babel-loader 的 Webpack 不发出有效的 es5
Webpack with babel-loader not emitting valid es5
我有一个基于 https://github.com/vuejs-templates/webpack-simple/blob/master/template/webpack.config.js 的 webpack 配置
它使用 vue-loader 和 babel-loader。问题是我无法让它生成 ES5 代码,以便它可以在最广泛的客户端中工作。
如果我使用 ES2015 预设,webpack.optimize.UglifyJsPlugin
无法缩小输出,因为 Uglify 只能处理 ES5(不包括和声分支)。错误类似于:Unexpected token: punc (()
并且出现在多个文件中。
我可以通过使用 babili-webpack-plugin
来解决这个问题,这将缩小 ES6 代码,但速度非常慢。然而,当我部署这段代码时,我看到错误被报告为 Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
所以我知道他们是老客户在 ES6 代码上窒息。
如何从 babel-loader 获得正确的 ES5 代码输出?我尝试了多个预设,有或没有 transform-runtime
插件。配置如下:
const webpack = require('webpack');
const globEntries = require('webpack-glob-entries');
const _ = require('lodash');
const path = require('path');
const BabiliPlugin = require("babili-webpack-plugin");
const env = process.env.NODE_ENV;
let entries;
if (env === 'production') {
entries = globEntries('./src/**/vue/*.js');
} else {
entries = _.mapValues(globEntries('./src/**/vue/*.js'), entry => [entry, 'webpack-hot-middleware/client?reload=true']);
}
module.exports = {
entry: entries,
output: {
path: '/', ///no real path is required, just pass "/"
publicPath: '/vue',
filename: '[name].js',
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader',
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
},
// other vue-loader options go here
},
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
query: {
presets: ['es2015'],
plugins: ['transform-runtime'],
},
},
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
],
},
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js',
},
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // Enable HMR
new webpack.NoEmitOnErrorsPlugin(),
],
performance: {
hints: false,
},
devtool: '#eval-source-map',
};
if (env === 'staging' || env === 'production') {
//module.exports.devtool = env === 'staging' ? '#source-map' : false;
module.exports.devtool = '#source-map';
module.exports.output.path = path.resolve(__dirname, './src/v1/parse/cloud/public/vue');
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: `"${env}"`,
},
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false,
},
}),
// new BabiliPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true,
}),
]);
}
vue-loader
将使用 babel-loader
(如果检测到)和 uses .babelrc
by default.
处理您的 js
在您当前的设置中,当 vue-loader
使用 Babel 时,您 不会 将任何选项传递给它(这意味着 Babel 对您的 Vue 文件不使用任何规则)。
创建 .babelrc
或自行为 .vue
文件指定 js
加载程序,以为其提供选项:
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
js: 'babel?presets[]=es2015' // Pass parameters as options
}
}
}
将完全编译为ES5的env
preset for Babel has an uglify
option。此预设是使您的环境保持最新的推荐做法。
// .babelrc
{
"presets": [
[ "env", { "uglify": true } ],
"stage-1" // Or other presets not included with 'env' preset.
],
"plugins": ["transform-runtime"]
}
除了使用预设 es2015
,您还可以添加 es2016
和 es2017
,以及 stage-4
、stage-3
等以确保您的所有代码都已转换,而不仅仅是 ES2015 部分。
这里的答案已经没有问题,但这里有一个不需要 .babelrc 文件的解决方案。此答案适用于独立的 webpack.config.js 文件。我通过查看 laravel-mix 库的底层得到了这个答案。
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders:{
js: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
['env', {
'modules': false,
'targets': {
'browsers': ['> 2%'],
uglify: true
}
}]
],
plugins: [
'transform-object-rest-spread',
['transform-runtime', {
'polyfill': false,
'helpers': false
}]
]
}
},
}
}
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
我花了一天的大部分时间阅读所有这些无用的博客,忽略了 babel-loader 必须附加到 vue-loader 的核心概念。
我有一个基于 https://github.com/vuejs-templates/webpack-simple/blob/master/template/webpack.config.js 的 webpack 配置 它使用 vue-loader 和 babel-loader。问题是我无法让它生成 ES5 代码,以便它可以在最广泛的客户端中工作。
如果我使用 ES2015 预设,webpack.optimize.UglifyJsPlugin
无法缩小输出,因为 Uglify 只能处理 ES5(不包括和声分支)。错误类似于:Unexpected token: punc (()
并且出现在多个文件中。
我可以通过使用 babili-webpack-plugin
来解决这个问题,这将缩小 ES6 代码,但速度非常慢。然而,当我部署这段代码时,我看到错误被报告为 Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
所以我知道他们是老客户在 ES6 代码上窒息。
如何从 babel-loader 获得正确的 ES5 代码输出?我尝试了多个预设,有或没有 transform-runtime
插件。配置如下:
const webpack = require('webpack');
const globEntries = require('webpack-glob-entries');
const _ = require('lodash');
const path = require('path');
const BabiliPlugin = require("babili-webpack-plugin");
const env = process.env.NODE_ENV;
let entries;
if (env === 'production') {
entries = globEntries('./src/**/vue/*.js');
} else {
entries = _.mapValues(globEntries('./src/**/vue/*.js'), entry => [entry, 'webpack-hot-middleware/client?reload=true']);
}
module.exports = {
entry: entries,
output: {
path: '/', ///no real path is required, just pass "/"
publicPath: '/vue',
filename: '[name].js',
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader',
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
},
// other vue-loader options go here
},
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
query: {
presets: ['es2015'],
plugins: ['transform-runtime'],
},
},
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
],
},
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js',
},
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // Enable HMR
new webpack.NoEmitOnErrorsPlugin(),
],
performance: {
hints: false,
},
devtool: '#eval-source-map',
};
if (env === 'staging' || env === 'production') {
//module.exports.devtool = env === 'staging' ? '#source-map' : false;
module.exports.devtool = '#source-map';
module.exports.output.path = path.resolve(__dirname, './src/v1/parse/cloud/public/vue');
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: `"${env}"`,
},
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false,
},
}),
// new BabiliPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true,
}),
]);
}
vue-loader
将使用 babel-loader
(如果检测到)和 uses .babelrc
by default.
js
在您当前的设置中,当 vue-loader
使用 Babel 时,您 不会 将任何选项传递给它(这意味着 Babel 对您的 Vue 文件不使用任何规则)。
创建 .babelrc
或自行为 .vue
文件指定 js
加载程序,以为其提供选项:
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
js: 'babel?presets[]=es2015' // Pass parameters as options
}
}
}
将完全编译为ES5的env
preset for Babel has an uglify
option。此预设是使您的环境保持最新的推荐做法。
// .babelrc
{
"presets": [
[ "env", { "uglify": true } ],
"stage-1" // Or other presets not included with 'env' preset.
],
"plugins": ["transform-runtime"]
}
除了使用预设 es2015
,您还可以添加 es2016
和 es2017
,以及 stage-4
、stage-3
等以确保您的所有代码都已转换,而不仅仅是 ES2015 部分。
这里的答案已经没有问题,但这里有一个不需要 .babelrc 文件的解决方案。此答案适用于独立的 webpack.config.js 文件。我通过查看 laravel-mix 库的底层得到了这个答案。
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders:{
js: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
['env', {
'modules': false,
'targets': {
'browsers': ['> 2%'],
uglify: true
}
}]
],
plugins: [
'transform-object-rest-spread',
['transform-runtime', {
'polyfill': false,
'helpers': false
}]
]
}
},
}
}
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
我花了一天的大部分时间阅读所有这些无用的博客,忽略了 babel-loader 必须附加到 vue-loader 的核心概念。