I have a webpack config that is based off https://github.com/vuejs-templates/webpack-simple/blob/master/template/webpack.config.js It uses vue-loader and babel-loader. The issue is I cannot get it to generate ES5 code so that it will work in the most broad range of clients.
If I use the ES2015 preset, webpack.optimize.UglifyJsPlugin
fails to minify the output because Uglify can only handle ES5 (not counting the harmony branch). The errors are similar to: Unexpected token: punc (()
and occur in multiple files.
I can work around this by using babili-webpack-plugin
which will minify the ES6 code but is very slow. However, when I deploy this code, I see errors being reported back saying Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
so I know they are older clients choking on ES6 code.
How can I get proper ES5 code output from babel-loader? I have tried multiple presets, with or without the transform-runtime
plugin. Config below:
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
will process yourjs
withbabel-loader
(if it's detected), and uses.babelrc
by default.In your current setup you are not passing any options to Babel when it is used by
vue-loader
(meaning Babel uses no rules for your Vue files).Either create
.babelrc
or specify thejs
loader by yourself for the.vue
files to provide it with options:The
env
preset for Babel has anuglify
option that will fully compile to ES5. This preset is recommended practice to keep your environment up to date.Instead of using preset
es2015
only, you might addes2016
andes2017
, as well asstage-4
,stage-3
, etc. to assure all your code is transformed, and not just the ES2015 parts.Nothing wrong with answer here already, but here is a solution that does not require a .babelrc file. This answer works for a standalone webpack.config.js file. I got this answer from taking a look under the hood of the laravel-mix library.
I spent the better part of a day reading up all these useless blogs omit the core concept that babel-loader has to be attached to the vue-loader.