11

Webpack builds successfully and I can browse to my webpage. However, the Javascript fails, saying: 'import declarations may only appear at top level of a module'

Below is my outputted app.js that contains the import statements.

How do I change my webpack config file to get rid of the import statements when it builds?

webpackJsonp([0],{

/***/ 0:
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__(1);
    __webpack_require__(74);
    module.exports = __webpack_require__(76);


/***/ },

/***/ 76:
/***/ function(module, exports) {

    "use strict";

    import 'app/tools/typescriptImports.ts';
    import * as mainScreenHelper from 'app/tools/mainScreenHelper';
    import React from 'react';
    import * as reactDom from 'react-dom';
    import Router from 'react-router';
    import createBrowserHistory from 'history/lib/createBrowserHistory';
    import routes from 'app/tools/routes';
    import 'style/app.scss';
    import 'font-awesome/scss/font-awesome.scss';

    mainScreenHelper.removeLoadingScreen();
    mainScreenHelper.createReactApp();

/***/ }

});
//# sourceMappingURL=app.js.map

Here is my current config file:

'use strict';

//https://webpack.github.io/docs/configuration.html

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
var rootPath = __dirname; //ekaya
var srcPath = path.join(rootPath, 'src/client'); //ekaya/src/client
var distPath = path.join(rootPath, 'dist/client'); //ekaya/dist/client

module.exports =
{
    bail: true,
    cache: true,
    context: rootPath,
    debug: true,
    devtool: 'source-map', //inline-source-map, https://webpack.github.io/docs/configuration.html#devtool
    target: 'web', //node, web
    devServer:
    {
        contentBase: distPath,
        historyApiFallback: true,
        outputPath: path.join(distPath, 'devServer')
    },
    entry:
    {
        app: path.join(srcPath, 'app/home.jsx'),
        lib: ['react', 'react-router', 'react-dom', 'jquery', 'lodash', 'history']
    },
    output:
    {
        path: distPath,
        publicPath: '',
        filename: '[name].js',
        pathInfo: true
    },
    resolve:
    {
        root: srcPath,
        extensions: ['', '.js', '.jsx', '.ts', '.tsx'],
        modulesDirectories: ['node_modules', srcPath]
    },
    module:
    {
        loaders:
        [
            {test: /\.js$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules)/ },
            {test: /\.jsx$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules)/ },
            {test: /\.ts$/, loader: 'ts-loader?cacheDirectory', exclude: /(node_modules)/ },
            {test: /\.tsx$/, loader: 'ts-loader?cacheDirectory', exclude: /(node_modules)/ },
            {test: /\.scss$/, loaders: ['style', 'css', 'sass']},
            {test: /\.png$/, loader: 'file-loader'},
            {test: /\.jpg$/, loader: 'file-loader'},
            {test: /\.jpeg$/, loader: 'file-loader'},
            {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
            {test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
            {test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
            {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
            {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"}
        ]
    },
    plugins:
    [
        new CopyWebpackPlugin
        ([
            { from: path.join(srcPath, 'images'), to: 'images' }
        ]),
        new webpack.optimize.CommonsChunkPlugin('lib', 'lib.js'),
        new HtmlWebpackPlugin
        ({
            inject: true,
            template: path.join(srcPath, 'index.html')
        }),
        new webpack.NoErrorsPlugin()
    ]
};

My tsconfig.json

{
    "buildOnSave": false,
    "compileOnSave": false,
    "compilerOptions":
    {
        "allowJs": true,
        "jsx": "react",
        "noImplicitAny": true,
        "module": "commonjs",
        "outDir": "dist/client/ts",
        "removeComments": true,
        "sourceMap": false,
        "target": "es5"
    },
    "exclude":
    [
        "node_modules",
        "dist"
    ]
}
Richard
  • 14,798
  • 21
  • 70
  • 103

4 Answers4

12

I had the same problem. You installed ES6. The import fails w/o it.

Babel file is copied without being transformed

EDIT:

By default, Babel 6.x does not perform any transformations. You need to tell it what transformations to run:

npm install babel-preset-es2015

and run

babel --presets es2015 proxy.js --out-file proxified.js

or create a .babelrc file containing

{
    "presets": [
        "es2015"
    ]
}
Community
  • 1
  • 1
  • @armatita you do realize a minimal reply that actually provides new information is way better than nothing, right? Because I was the only one who replied. And it wasn't a link only answer. – DoktorDooLittle Jun 01 '16 at 15:10
  • DoktorDooLittle I did not downvote your answer (if that is what you assumed). At the time I made the review (and noticed that it appeared in review likely because someone flagged it as low quality) your answer did not fit SO criteria. Thus the comment suggestion (which is a pre-formatted text). I'll be happy to remove my review comment given the additional information. In any case it seems @Richard found a solution. – armatita Jun 01 '16 at 15:17
  • @armatita No matter. I did assume that, sorry about that. Yes, he did unwittingly stumble upon the solution. I replied entirely with the next one googling the same problem in mind. – DoktorDooLittle Jun 01 '16 at 15:40
  • No harm done. As rule of thumb always assume "link" answers tend to be flagged as low quality by someone. From there until deletion (if the user does not make an effort to improve the answer) is a matter of time. Also notice this is even more relevant if you consider that most people doing reviewing are not specialists in the tags they are reviewing (such is the case with me). The criteria for reviewing implies much more format than correctness (which I'm unable to evaluate). In any case thanks for the effort (+1). – armatita Jun 01 '16 at 16:02
  • I was following [this tutorial that demo'ed using webpack & babel](http://blog.xebia.com/unlocking-es2015-features-with-webpack-and-babel/) but it didn't work. The problem: the tutorial used babel v5.x but I was now using v6. The npm install of babel-loader already told me I also needed babel-core but your answer here gave me everything else I needed to get the tutorial code to work. I had already known about needing babel presets and .babelrc but there are lots of other babelXXX packages out there and your answer clarified the minimal additions I needed. Thanks. – Andrew Willems Aug 04 '16 at 17:43
  • 1
    Definitely a good answer, or at least something that bears checking out. I found problems of this type are easily caused by missing hidden `.` `rc` files. I had been very carefully copying the setup from github examples and making sure my final webpack config objects matched, but I had forgotten about those hidden files (2nd time I got caught out). – JL Peyret Feb 09 '17 at 00:38
6

I ran into the same issue and found out that my file structure was the problem:

Modules can only imported from the same or lower level as the entry point configured in webpack.config.js in module.exports.entry, i.e.:

module.exports = {
  entry: path.resolve(__dirname, 'javascripts', 'main.js')
}

I was trying to import locales from a higher level:

├── javascripts
│   └── main.js
└── locales
    ├── de.js
    └── en.js

After moving the locales directory, the import worked:

└── javascripts
    ├── locales
    │   ├── de.js
    │   └── en.js
    └── main.js
Tsunamis
  • 5,870
  • 1
  • 20
  • 22
3

If you're following the guide on https://webpack.js.org , you might not realise that site is only documenting Webpack version 2 or later, not Webpack 1. One of the new features of Webpack 2 is that it has native ES6 import, export and System.import.

You need to install Webpack 2 first:

npm install --save-dev webpack@2.2.0-rc.1

If you want to see a list of all Webpack releases, run:

npm show webpack versions --json
Flimm
  • 136,138
  • 45
  • 251
  • 267
1

Ok, I got this to work somehow, not really sure which part did it, but here are all my config files for anyone facing the same problem in the future;

webpack:

'use strict';

//https://webpack.github.io/docs/configuration.html

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
var rootPath = __dirname; 
var srcPath = path.join(rootPath, 'src/client');
var distPath = path.join(rootPath, 'dist/client'); 

module.exports =
{
    bail: true,
    cache: false,
    context: rootPath,
    debug: true,
    devtool: 'source-map', //inline-source-map, https://webpack.github.io/docs/configuration.html#devtool
    target: 'web', //node, web
    devServer:
    {
        contentBase: distPath,
        historyApiFallback: true,
        outputPath: path.join(distPath, 'devServer')
    },
    entry:
    {
        app: path.join(srcPath, 'app/home.jsx'),
        lib: ['react', 'react-router', 'react-dom', 'jquery', 'lodash', 'history']
    },
    output:
    {
        path: distPath,
        publicPath: '',
        filename: '[name].js',
        pathInfo: true
    },
    resolve:
    {
        root: srcPath,
        extensions: ['', '.js', '.jsx', '.ts', '.tsx'],
        modulesDirectories: ['node_modules', srcPath, 'typings']
    },
    module:
    {
        loaders:
        [
            {test: /\.js$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules|typings)/ },
            {test: /\.jsx$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules|typings)/ },
            {test: /\.ts$/, loader: 'ts-loader?cacheDirectory', exclude: /(node_modules|typings)/ },
            {test: /\.tsx$/, loader: 'ts-loader?cacheDirectory', exclude: /(node_modules|typings)/ },
            {test: /\.scss$/, loaders: ['style', 'css', 'sass']},
            {test: /\.png$/, loader: 'file-loader'},
            {test: /\.jpg$/, loader: 'file-loader'},
            {test: /\.jpeg$/, loader: 'file-loader'},
            {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
            {test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
            {test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
            {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
            {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"}
        ]
    },
    plugins:
    [
        new CopyWebpackPlugin
        ([
            { from: path.join(srcPath, 'images'), to: 'images' }
        ]),
        new webpack.optimize.CommonsChunkPlugin('lib', 'lib.js'),
        new HtmlWebpackPlugin
        ({
            inject: true,
            template: path.join(srcPath, 'index.html')
        }),
        new webpack.NoErrorsPlugin()
    ]
};

.babelrc:

{
    "presets": ["es2015", "react"]
}

package.json

{
  "name": "ekaya",
  "private": "true",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies":
  {
      "jquery": "2.2.3",
      "lodash": "4.11.1",
      "font-awesome": "4.6.1",
      "history": "2.1.1",
      "react": "15.0.2",
      "react-dom": "15.0.2",
      "react-router": "2.4.0",

      "compression": "1.0.3",
      "cors": "2.5.2",
      "helmet": "1.3.0",
      "loopback": "2.22.0",
      "loopback-boot": "2.6.5",
      "loopback-component-explorer": "2.4.0",
      "loopback-datasource-juggler": "2.39.0",
      "serve-favicon": "2.0.1"
  },
  "devDependencies":
  {
    "node-sass": "3.7.0",
    "nsp": "2.1.0",
    "babel-core": "6.8.0",
    "babel-loader": "6.2.4",
    "babel-preset-es2015": "6.6.0",
    "babel-preset-react": "6.5.0",
    "css-loader": "0.23.1",
    "file-loader": "0.8.5",
    "jsx-loader": "0.13.2",
    "font-awesome": "4.6.1",
    "copy-webpack-plugin": "2.1.3",
    "html-webpack-plugin": "2.16.1",
    "sass-loader": "3.2.0",
    "style-loader": "0.13.1",
    "ts-loader": "0.8.2",
    "typescript-loader": "1.1.3",
    "typescript": "1.8.10",
    "typings": "0.8.1",
    "webpack": "1.13.0",
    "webpack-dev-server": "1.14.1"
  },
  "scripts":
  {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "./node_modules/.bin/webpack --progress --colors",
    "run": "./node_modules/.bin/webpack-dev-server --hot --inline --progress --colors --watch"
  },
  "repository":
  {
    "type": "git",
    "url": ""
  },
  "config":
  {
    "port": "8080"
  },
  "author": "",
  "license": "private",
  "homepage": ""
}

tsconfig.json:

{
    "buildOnSave": false,
    "compileOnSave": false,
    "compilerOptions":
    {
        "allowJs": true,
        "jsx": "react",
        "noImplicitAny": true,
        "module": "commonjs",
        "outDir": "dist/client/ts",
        "removeComments": true,
        "sourceMap": false,
        "target": "es6"
    },
    "exclude":
    [
        "node_modules",
        "dist",
        "typings"
    ]
}

typings.json

{
  "ambientDependencies": {
    "jquery": "registry:dt/jquery#1.10.0+20160417213236",
    "lodash": "registry:dt/lodash#3.10.0+20160330154726",
    "react": "registry:dt/react#0.14.0+20160423065914",
    "react-dom": "registry:dt/react-dom#0.14.0+20160412154040"
  },
  "dependencies": {}
}

I also recommend deleting your compiled output (my 'dist' folder) and rebuilding, without using the webpack devServer.

And since some of the react-router history typings don't seem to work, write your own:

declare module 'history/lib/createBrowserHistory' {
    const x: any;
    export = x;
}

declare module 'react-router' {
    const x: any;
    export = x;
}
Richard
  • 14,798
  • 21
  • 70
  • 103