Vue-loader: Vue Loader doesn't seem to use Babel ES2015 defaults

Created on 15 Oct 2016  ยท  13Comments  ยท  Source: vuejs/vue-loader

I'm using the following components:

npm list | grep vue
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”‚ โ”œโ”€โ”€ [email protected]
โ”‚ โ”œโ”€โ”€ [email protected]
โ”‚ โ”œโ”€โ”ฌ [email protected]
โ”‚ โ””โ”€โ”€ [email protected]
โ”œโ”€โ”ฌ [email protected]
โ”œโ”€โ”€ [email protected]

If I use a webpack config like this

module.exports = {
    context: __dirname + "/JsSrc",
    entry: "./main.js",
    output: {
        path: __dirname + "/Content",
        filename: "bundle.js"
    },
    resolve: {
        extensions: ['', '.vue']
    },
    module: {
        loaders: [
            // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
            {
                test: /\.vue$/,
                loader: 'vue',
                exclude: /(node_modules|bower_components)/,
                query: {
                    presets: ['es2015']
                }
            },
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel',
                query: {
                    presets: ['es2015']
                }
            }
        ]
    }
};

The module resolution works fine in normal js files (since they have the es2015 preset), but any import'ed modules in a .Vue file will throw an Unexpected token import error, namely because the import token in the .Vue files isn't being converted to require. If I add this into my webpack config:

    vue: {
        loaders: {
            js: 'babel?presets[]=es2015'
        }
    }

This error is gone. Surely we should be using es2015 by default? Or failing this, provide a more accessible and better documented mechanism for setting the babel defaults for the vue loader?

Most helpful comment

Here is working code for Webpack 3 (or even 2):

...
{
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
        loaders: {
            js: {
               loader: 'babel-loader',
               options: {
                   presets: ['es2015']
               }
            },
        }
    }
}
...

All 13 comments

Poking around in the source code seems to suggest that we don't set the defaults anywhere: https://github.com/vuejs/vue-loader/blob/70ca3ff64c1ae69bb4b93a142e937fccd2f06c89/lib/loader.js#L62

Is the solution to this as simple as adding the ?presets[]=es2015 query string?

Surely we should be using es2015 by default?

No. Maybe the user wants to use Typescript? Or something else? We don't want to assume such things.

However, we will use the .babelrc config of a project by default. If your project doesn't have one, you have to tell vue-loader to use it, just like you have to tell it to webpack for normal .js files.

See the documentation.

Yes, being unopinionated is a nice principle, but we've already violated that principle by automatically loading babel.

The real problem though is that that documentation page you linked talks all about the new ES6, features, but doesn't mention that you have to explicitly enable them, which can be very confusing:

When vue-loader detects the presence of babel-loader or buble-loader in the same project, it will use them to process the <script> parts of all *.vue files, allowing us to use ES2015 in our Vue components. If you haven't picked up the new language features yet, you definitely should

@TMiguelT the last paragraph says:

babel-loader respects .babelrc, so it is the recommended approach to configure the Babel presets and plugins.

Yes that's good but please highlight the need to specify the ES2015 presets in order for the es6 features you're promoting to work at all. We want Vue to be easy to people new to the ecosystem I assume. I'm not, and I was still confused by the way this was presented.

@TMiguelT if you are new to all this then you should be using vue-cli. The vue-loader documentation assumes the user is familiar with Webpack and Babel and wants to manually setup everything.

Good point, although I still believe being more explicit here would be helpful. It is however your decision.

Are there any ways to explicitly pass the option? For some reason my babel does not respects .babelrc because of crossing directory. It should be rather easy to add an option for it.

As I said above:

    vue: {
        loaders: {
            js: 'babel?presets[]=es2015'
        }
    }

with .babelrc is good for packaging when the src folder and webpack dev folder are the same.
However, if i want to split the packaging folder and src folder, with babel I can set

{    
        test: /\.js$/,     
        loader: 'babel',    
        exclude: /node_modules/,    
        query: {    
          presets: [   
            require.resolve('babel-preset-es2015'),   
            require.resolve('babel-preset-stage-2'),   
          ]   
        }   
      }

How can I do the same thing with vue-loader?

Here is working code for Webpack 3 (or even 2):

...
{
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
        loaders: {
            js: {
               loader: 'babel-loader',
               options: {
                   presets: ['es2015']
               }
            },
        }
    }
}
...

@yyx990803 Might not be the perfect issue to discuss this, but I was wondering why javascript that comes from a vue file needs to have its own loader in the vue-loader object and it doesn't read an already setup babel-loader that tests javascript files.
This comes handy especially when I don't want to use the babelrc file.

like for example

[
  {
    test: /\.js$/,
    loader: 'babel-loader',
    options: {
      babelrc: false,
      presets: ['env', 'stage-2']
    }
  },
  {
    test: /\.vue$/,
    loader: 'vue-loader'
  }
]

in this case babel-loader will take care of js files and vue-loader of vue files.
this is just very straight forward to me, instead we need to add the options.loaders.js pattern and repeat the babel-loader again with every presets and options.

Thanks for the time

@MatteoGabriele has a good point, should we create a new issue or request since this one is closed?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yozman picture yozman  ยท  4Comments

githoniel picture githoniel  ยท  3Comments

amorphine picture amorphine  ยท  3Comments

NextSeason picture NextSeason  ยท  3Comments

snoopdouglas picture snoopdouglas  ยท  3Comments