'import' and 'export' may only appear at the top level

I'm using webpack with vuejs. Webpack does its thing, but when I look at the outputted app.js file, it gives me this error.

'import' and 'export' may only appear at the top level

I'm assuming it's a problem with babel not converting the code? Because I'm getting this in the browser when viewing the application.

Unexpected token import

Here's my entry.js for my vuejs application:

/*jshint esversion: 6 */
import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
require('./css/style.scss');

// Export the vue router
export var router = new VueRouter({
  hashbang: false,
  root: '/'
  // history: true
});

// Set up routing and match routes to components
router.map({
  '/': {
    component: require('./components/home/Home.vue')
  }
});

// Redirect to the home route if any routes are unmatched
router.redirect({
  '*': '/'
});

// Start the app on the #app div
router.start(App, '#app');

Here's my webpack.config.js:

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var path = require('path');

module.exports = {
  entry: './src/entry.js',
  output: {
      filename: './public/js/app.js'
  },
  devtool: 'source-map',
  plugins: [
    new ExtractTextPlugin('./public/css/style.css')
  ],
  module: {
    preLoaders: [{
        test: /\.js$/, 
        exclude: /node_modules/,
        loader: 'jshint-loader'
    }],
    loaders: [{
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract(
            'style',
            'css!sass'
        ),
    },
    {
        test: /\.vue$/,
        loader: 'vue'
    },
    {
        test: /\.js$/,
        exclude: /node_modules/,
        include: [
          path.resolve(__dirname, "src/services"),
        ],
        loader: 'babel-loader',
        query: {
          presets: ['es2015']
        }
    }]
  }
};

Here's my packages.json file:

{
  "name": "test-webpack",
  "version": "1.0.0",
  "description": "Myapp",
  "main": "entry.js",
  "scripts": {
    "watch": "webpack-dev-server  --host $IP --port $PORT  --hot --inline --config webpack.config.js",
    "dev": "webpack",
    "build": ""
  },
  "author": "Dev",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.9.1",
    "babel-loader": "^6.2.4",
    "babel-plugin-transform-class-properties": "^6.10.2",
    "babel-plugin-transform-runtime": "^6.9.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-runtime": "^6.9.2",
    "css-loader": "^0.23.1",
    "extract-text-webpack-plugin": "^1.0.1",
    "jshint": "^2.9.2",
    "jshint-loader": "^0.8.3",
    "node-sass": "^3.8.0",
    "path": "^0.12.7",
    "sass-loader": "^3.2.0",
    "style-loader": "^0.13.1",
    "vue-hot-reload-api": "^1.3.2",
    "vue-html-loader": "^1.2.2",
    "vue-loader": "^8.5.2",
    "vue-style-loader": "^1.0.0",
    "webpack": "^1.13.1",
    "webpack-dev-server": "^1.14.1"
  },
  "dependencies": {
    "vue": "^1.0.25",
    "vue-router": "^0.7.13"
  }
}

'import' and 'export' may only appear at the top level

This means that webpack is bundling the non-transpiled ES6 code, which is why these import/export statements are being found. babel-loader must therefore not be transpiling what you expect.

If you simply remove the include and exclude rules from its loader config, the default behavior of transpiling everything besides what's in node_modules will kick in. For some reason or another, the current rules are causing some/all files to be skipped.

module.exports = {
  entry: './src/entry.js',
  output: {
    filename: './public/js/app.js'
  },
  devtool: 'source-map',
  plugins: [
    new ExtractTextPlugin('./public/css/style.css')
  ],
  module: {
    preLoaders: [{
      test: /\.js$/, 
      exclude: /node_modules/,
      loader: 'jshint-loader'
    }],
    loaders: [{
      test: /\.scss$/,
      loader: ExtractTextPlugin.extract(
        'style',
        'css!sass'
      ),
    },
    {
      test: /\.vue$/,
      loader: 'vue'
    },
    {
      test: /\.js$/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015']
      }
    }]
  }
};

I got this error when I was missing a closing bracket.

Simplified recreation:

const foo = () => {
  return (
    'bar'
  );
}; <== this bracket was missing

export default foo;

Make sure you have a .babelrc file that declares what Babel is supposed to be transpiling. I spent like 30 minutes trying to figure this exact error. After I copied a bunch of files over to a new folder and found out I didn't copy the .babelrc file because it was hidden.

{
  "presets": "es2015"
}

or something along those lines is what you are looking for inside your .babelrc file

Using webpack 4.14.0 and babel-cli 6.26 I had to install this Babel plugin to fix the SyntaxError: 'import' and 'export' may only appear at the top level error: babel-plugin-syntax-dynamic-import

It was linked through from the Webpack Code Splitting Docs.

Look out for a double opening bracket syntax error as well {{ which can cause this error message to appear

Comments
  • I see you have include set to a specific directory for babel-loader; can you just remove that and let webpack include anything that's not excluded?
  • You're a life saver, that was exactly the problem. Thank you!
  • @Jacob you should add it as an answer so that OP can accept it.
  • stackoverflow.com/questions/39158552/…
  • I have installed the babel loader and the config is as following: ` module.loaders = [{ test : /\.(js|jsx)$/, exclude : /node_modules/, loader : 'babel', query : { cacheDirectory : true, plugins : ['transform-runtime', 'transform-async-to-generator'], presets : ['latest', 'react', 'stage-0'] } }] ` And Still it does not compile a file correctly throwing the same mentioned here error. What else might be wrong ?
  • I'm not familiar with latest or stage-0, but have you tried adding es2015 to presets?
  • This answer is probably the right one in 90% of cases. Check your opening closing brackets!
  • Thank you, I was going crazy.
  • this is hilarious... thanks for the insight
  • According to github.com/webpack/webpack/issues/… it is fixed in "webpack": "4.36.0",
  • I used similar configuration as yours, the code got compiled but in IE11 I am getting SCRIPT28 and SCRIPT2343 errors
  • According to github.com/webpack/webpack/issues/… it is fixed in "webpack": "4.36.0"