I got Illegal import declaration error. when I tried to integrated a react js repo with webpack
I migrated the original source code from https://github.com/dptoot/react-event-calendar/blob/master/example/src/example.js
How could I fix Illegal import declaration error ?
I think the import syntax only works in some js lib ?
Error
ERROR in ./app/main.js
Module build failed: Error: Parse Error: Line 2: Illegal import declaration
at throwError (/Users/poc/sandbox/ha/node_modules/jsx-loader/node_modules/jstransform/node_modules/esprima-fb/esprima.js:2823:21)
main.js
var React = require('react');
const EventCalendar = require('react-event-calendar');
import moment from 'moment';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import Button from 'react-bootstrap/lib/Button';
import ButtonToolbar from 'react-bootstrap/lib/ButtonToolbar';
import Popover from 'react-bootstrap/lib/PopOver';
import Overlay from 'react-bootstrap/lib/Overlay';
webpack.config.js
var path = require('path');
var webpack = require('webpack');
var config = module.exports = {
// the base path which will be used to resolve entry points
context: __dirname,
// the main entry point for our application's frontend JS
entry: './app/main.js',
output: {
filename: 'main.js'
},
resolve: {
extensions: ['', '.js', '.jsx', '.ts']
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony' }
]
}
};
Use Babel via babel-loader to transform import declarations (and other ES2015 if you want). http://babeljs.io/docs/setup/#webpack
As #JMM answered, it seems you need babel-loader. in addition, I was still facing the same problem, and finally get resolved by editing webpack.config.js such like
module: {
loaders: [
- {test: /\.jsx?$/, loader: 'babel-loader'},
- {test: /\.jsx$/, loader: 'jsx-loader'}
+ {test: /\.jsx$/, loader: 'jsx-loader'},
+ {test: /\.jsx?$/, loader: 'babel-loader'}
]
},
or because jsx-loader looks no longer working with this config, it can be deleted.
I hope it would help
Related
I'm trying to implement async routing in my react-project using react-router-async-routing.
The problem is that I get this error during webpack compiling:
'import' and 'export' may only appear at the top level
It happens in my router.js which is equal to the one from the link above.
Replacing the import with System.import compiles without errors and the browser loads the chunk (visible in the network-traffic-view), but the page remains blank (I guess it is not being executed!).
This is my webpack-config:
var { path, resolve } = require("path");
var webpack = require("webpack");
module.exports = {
entry: {
app: "./src/js/user/main.js",
vendor: ["react", "react-dom"]
},
output: {
path: __dirname + "/resources/user/js",
publicPath: "/resources/user/js/",
filename: "[name].bundle.js",
chunkFilename: "[name].bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
filename: "vendor.bundle.js"
})
],
module: {
loaders: [{
test: /.(js|jsx)?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['env', 'react']
}
},
{
test: /\.(less)$/,
loaders: ["style-loader", "css-loader", "less-loader"]
},
{
test: /\.(css)$/,
loaders: ["style-loader", "css-loader"]
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: "file-loader"
},
{
test: /\.(png|jpg|gif)$/,
loader: "url-loader"
}
]
},
resolve: {
alias: {
"global": __dirname + "/src/js/user/module/global"
}
}
};
How can I solve this problem?
EDIT1:
File with error:
import AsyncSetup from "react-router-async-routing";
import routes from "./routes";
const {Route, Link, Preload} = AsyncSetup(routes, path => {
import(`./routes/${path}.jsx`);
});
export {Link, Route, Preload};
EDIT2:
I solved the problem with the import by installing
babel-plugin-syntax-dynamic-import
and adding it to babel :
test : /.(js|jsx)?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: [['es2015'], 'react'],
plugins: ["syntax-dynamic-import"]
}
Now everything is working!
The new Import API is still a little confusing, because of different Node versions, and specially when using transpiling tools such as Babel and Webpack. I strongly recommend you to use require() instead of import() in your dynamic imports (where the file path is not a constant) and let import for constant dependencies, that's what I do in my projects, and I have no issues.
Something like this:
import AsyncSetup from "react-router-async-routing";
import routes from "./routes";
const {Route, Link, Preload} = AsyncSetup(routes, path => {
return require(`./routes/${path}.jsx`);
});
export {Link, Route, Preload};
You can also use absolute paths, this might be safer depending on your environment and code.
import path from 'path';
import AsyncSetup from "react-router-async-routing";
import routes from "./routes";
const {Route, Link, Preload} = AsyncSetup(routes, path => {
return require(path.join(__dirname, `./routes/${path}.jsx`));
});
export {Link, Route, Preload};
If this don't solve your issue, maybe you'll need to do some tweaking in the babel/webpack modules resolver.
Edit: I simply forgot to add typescript and ts-loader dependencies to my project..
I'm trying to import a file called Test.ts from my main.js.
Test.js:
export default class Test {}
main.js:
import Test from './Test' // or `const Test = require('./Test')`
In my webpack.config.js I have the following:
{
resolve: {
extensions: ['.js', '.ts']
},
module: {
rules: [
{
test: /\.(js|ts)$/,
loader: 'babel-loader'
},
{
test: /\.ts$/,
loader: 'ts-loader'
}
]
}
}
On compilation I get the following error:
This relative module was not found:
* ./Test in ./src/main.js
What am I missing?
I want to build a react component library as a node module to then import it into different projects. But if I try to import a component it just returns an empty object.
button.jsx:
import React, {Component} from 'react'
export class Button extends Component {
render() {
return <button className='btn'>Hello Button comp</button>
}
}
export default Button
index.js
var Button = require('./button/button').default;
module.exports = {
Button: Button
}
webpack.config.js
const Path = require('path');
module.exports = {
resolve: {
extensions: ['.js', '.jsx']
},
entry: {
app: './src/components/index.js'
},
output: {
path: __dirname,
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: [
'es2015',
'react'
]
},
exclude: /node_modules/,
include: [
Path.resolve(__dirname, 'src')
]
},
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: [
'es2015',
'react'
]
},
exclude: /node_modules/,
include: [
Path.resolve(__dirname, 'src')
]
}
]
}
}
Main property in package.json is bundle.js
I figured out that when I import Button in a project it is just an empty object. It seems to me as if webpack doesn't bundle the index file properly. Any ideas what could be wrong here?
A webpack bundle does not expose your exports by default, as it assumes that you're building an app and not a library (which is the far more common use of webpack). You can create a library by configuring output.library and output.libraryTarget.
output: {
path: __dirname,
filename: 'bundle.js',
library: 'yourLibName',
libraryTarget: 'commonjs2'
},
output.libraryTarget is the format of the module, which would also allow you to expose the library as a global variable. commonjs2 is the module format that Node uses. See What is commonjs2? for the difference between commonjs and commonjs2.
Since you're using React, you'll expect that the consumer of the library will have React present as a dependency and therefore you don't want to include it in your bundle. To do that you can define it as an External. This is shown in Authoring Libraries, which walks you through a small example.
I have this jsx file.
//react code
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello React!</p>;
}
}
render(<App/>, document.getElementById('app'));
and this is my webpack.confg.js file
//webpack config
module.exports = {
entry: __dirname + '/assets/app/components/test/test.jsx',
output: {
path: __dirname,
filename: '/assets/app/components/test/test.min.js'
},
module: {
loaders: [
{
test: '/\.jsx?/',
exclude: '/node_modules/',
loader: 'babel',
query: {
presets:['es2015', 'react']
}
}
]
}
}
on running the web pack its giving the error as
/assets/app/components/test/test.jsx
Module parse failed: /Users/joseph.antony/workspace/sloop/assets/app/components/test/test.jsx Unexpected token (6:11)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (6:11)
I'm fairly sure that your issue is due to the regex tests not being expressed correctly:
This:
test: '/\.jsx?/',
exclude: '/node_modules/',
Should be:
test: /\.jsx?/,
exclude: /node_modules/,
Regex literals are not wrapped in strings.
Here is my module config I used for all React projects I create. You will need to npm install the packages I have specified below.
module: {
loaders: [
{
// Only run `.js` and `.jsx` files through Babel
test: /\.jsx?$/,
exclude: __dirname + "/node_modules",
loader: require.resolve("babel-loader"),
query: {
presets: [
require.resolve('babel-preset-es2015'),
require.resolve('babel-preset-stage-0'),
require.resolve('babel-preset-react')
]
}
}
]
},
I'm using webpack, and I want to load scss file in my JavaScript. (Or if it can be separate, it also fine).
This is my webpack config:
"use strict";
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');
module.exports = {
context: __dirname + '/src',
entry: './js/index.js',
output: {
path: './build',
filename: 'js/app.bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
}
]
},
resolve: {
root: [
path.resolve('./src/js'),
path.resolve('./src/scss')
],
extensions: ['', '.js']
},
plugins: [
new CopyWebpackPlugin([
{ from: 'html/**', to: `${__dirname}/build/html`, flatten: true },
{ from: 'images/**', to: `${__dirname}/build/image`, flatten: true }
])
]
};
this is my files list:
src/html/index.html -> build/html/index.html (WORKED)
src/images/** -> build/images/** (WORKED)
src/js/index.js -> build/js/app.bundle.js (WORKED)
src/scss/** -> build/css/** (NOT WORKED)
This is my JavaScript code. I just started project, so not much codes:
import "babel-polyfill";
import React from 'react';
import ReactDOM from 'react-dom';
import moduleA from 'moduleA';
import "view/startup.scss";
ReactDOM.render(
<div>
<h1>Helloworld!</h1>
</div>,
document.getElementById('entry')
);
You can see this: import "view/startup.scss";
I want to load scss file into my JavaScript, but when I run webpack command, it says:
ERROR in Loader /Users/.../Desktop/work/my-project/app/node_modules/css/index.js didn't return a function
# ./scss/view/startup.scss 4:14-123
in "resolve" property of webpack config, you can see that I added another root directory for scss, also I loaded sass-loader too, but it doesn't work and I don't know why.
And as I know, with Webpack, including css/scss automatically injects into destination file, so it doesn't matter it needs to be extract as separate file, I just want that this works.
Any help will be very appreciated :)
* UPDATED *
code of ./scss/view/startup.scss
#startup {
background-color: #7087d7;
}
The error points towards the reason (I highlighted the relevant part):
ERROR in Loader /Users/.../Desktop/work/my-project/app/node_modules/css/index.js didn't return a function # ./scss/view/startup.scss 4:14-123
When you declare a loader in Webpack, you can leave off the -loader suffix (so css-loader becomes css) provided that you don't have other modules that may match the suffixless loader name.
This is where it fails in your case, because you also use the css package, which Webpack tries to use as a loader (and fails, because it's not).
To fix this, use the full loader package name:
loaders : [ "style-loader", "css-loader", "sass-loader" ]