I have am attempting to compile my Javascript (es6) for use server side, the environment I'm targeting involves:
node 8.9.1
npm 6.0.0
webpack 4.8.1
The first part of the code I'm attempting to compile using webpack is the file index.js and it starts like this.
import express from 'express';
import https from 'https';
// Import socket.io
let io = require('socket.io').Server;
// Now import some basic middleware for express
import * as session from 'express-session';
import * as bodyParser from 'body-parser';
import * as favicon from 'serve-favicon';
// Import useful file IO
import * as path from 'path';
let fs = require('fs');
...
However when I run webpack I get the following error:
$ webpack
Webpack is watching the files…
Hash: 1bd3f903f9c5ccdc3456
Version: webpack 4.8.1
Time: 684ms
Built at: 2018-05-10 14:51:08
Asset Size Chunks Chunk Names
server.js 3.97 KiB main [emitted] main
server.js.map 2.52 KiB main [emitted] main
../dist/keys/it-test-crt.crt 1.16 KiB [emitted]
../dist/images/favicon.ico 1.19 KiB [emitted]
../dist/keys/it-test-csr.pem 1.02 KiB [emitted]
../dist/keys/it-test-key.pem 1.64 KiB [emitted]
Entrypoint main = server.js server.js.map
[./index.js] 1.2 KiB {main} [built] [failed] [1 error]
ERROR in ./index.js
Module build failed: Error: Parse Error: Line 1: Illegal import declaration
...
BTW I am using Javascript in it's es6 incarnation so do need Bable and it is in my configs (q.v.). Even if I was not using es6 the Webpack documentation suggests that import should be respected regardless, see here, where the Webpack documentations says:
Version 2 of webpack supports ES6 module syntax natively, meaning you can use import and export without a tool like babel to handle this for you.
So my question is why do I see the above error? My current assumption is I have made an error somewhere in my configuration of Webpack, see below:
var nodeExternals = require('webpack-node-externals');
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
context: __dirname,
mode: 'development',
entry: './index.js',
output: {
filename: 'server.js',
path: __dirname + '/../dist/'
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '.json'],
modules: ['./', 'node_modules']
},
module: {
rules:[
{
test: /\.js?$/,
use: {
loader: 'babel-loader?presets[]=env',
}
},
{
test: /\.jsx?$/,
use: {
loader: 'jsx-loader?harmony'
}
},
{
enforce: 'pre',
test: /\.js$/,
loader: 'source-map-loader'
}
]
},
target: 'node',
node: {
__dirname: false,
__filename: false
},
externals: [nodeExternals()],
watch: true,
watchOptions: {
ignored: /node_modules/
},
plugins: [
new CopyWebpackPlugin([
{from: 'images', to: '../dist/images'},
{from: 'keys', to: '../dist/keys'}
])
]
};
I have not set up a .babelrc file as I was appending the presets[]=env query to the babel-loader. Just in case it's helpful to know any other version numbers my package.json looks like this:
{
"name": "web-app",
"version": "1.0.0",
"description": "A web application using react, etc. ",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/nigel-daniels/web-app.git"
},
"keywords": [
"web",
"app",
"react",
"redux"
],
"author": "Nigel Daniels",
"license": "MIT",
"bugs": {
"url": "https://github.com/nigel-daniels/web-app/issues"
},
"homepage": "https://github.com/nigel-daniels/web-app#readme",
"dependencies": {
"async": "^2.6.0",
"bcrypt-nodejs": "0.0.3",
"body-parser": "^1.18.2",
"cookie-parser": "^1.4.3",
"debug": "^3.1.0",
"express": "^4.16.2",
"express-session": "^1.15.6",
"express-socket.io-session": "^1.3.2",
"fs": "0.0.1-security",
"immutable": "^3.8.2",
"mongoose": "^5.0.6",
"nodemailer": "^4.4.0",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
"react": "^16.1.1",
"react-dom": "^16.1.1",
"redux": "^3.7.2",
"serve-favicon": "^2.4.5",
"socket.io": "^2.0.4"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"chai": "^3.5.0",
"chai-immutable": "^1.6.0",
"copy-webpack-plugin": "^4.2.3",
"jsx-loader": "^0.13.2",
"mocha": "^5.0.1",
"source-map-loader": "^0.2.3",
"webpack": "^4.8.1",
"webpack-node-externals": "^1.7.2"
},
"engines": {
"node": "^8.1.0",
"npm": "6.0.0"
}
}
Thanks for any advice!
You shouldn't need jsx-loader for a nodejs backend build. You can remove it and if necessary, let babel-loader handle .jsx extensions for you:
{
test: /\.jsx?$/, // notice the little 'x'
use: {
loader: 'babel-loader?presets[]=env',
}
},
I think the problem is that it the express module exports with module.exports, while you import with es2015 import. I don't think webpack supports the conversion natively. I would just use require instead when importing npm modules, but otherwise you this babel plugin might solve it for you: https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs.
Related
I have been struggling with an issue with hot reloading where making edits in certain files would reload the app without those changes.
My initial solution was to update webpack and related modules. The first module I updated was webpack-dev-server. I went from v3 to v4 which immediately broke the app. All images and json files were getting 404'd when running the dev server.
Here is the original package.json:
{
...
"scripts": {
"dev": "set NODE_ENV=development && webpack serve --config config/webpack.dev.js --open",
"build": "set NODE_ENV=production && webpack --config config/webpack.prod.js",
"beatmarkers": "babel-node fetchAndFormatData/fetchAndFormatBeatMarkers.js"
},
"devDependencies": {
"#babel/cli": "^7.14.3",
"#babel/core": "^7.14.3",
"#babel/node": "^7.14.2",
"#babel/preset-env": "^7.14.4",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"css-loader": "^5.2.6",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.1",
"lodash.clonedeep": "^4.5.0",
"node-fetch": "^2.6.1",
"node-sass": "^6.0.0",
"sass-loader": "^11.1.1",
"style-loader": "^2.0.0",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
},
"dependencies": {
"bezier-easing": "^2.1.0",
"howler": "^2.2.3",
"pixi.js": "^6.2.0"
}
}
Here are the original webpack config files:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../src/template.html')
})
],
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg|ico|pvr|mp3|fnt)$/,
type: 'asset/resource'
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
}
};
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
devServer: {
historyApiFallback: true,
},
output: {
publicPath: '/'
},
devtool: "source-map"
});
This configuration produces a sources structure in chrome that looks like this:
localhost:8080
main.js
(index)
assets/images
animations
fonts
interface
When I updated webpack-dev-server to the latest version, 4.11.1, the assets/images folder no longer exists. I haven't be able to figure out how to get it back. Any help would be deeply appreciated.
Below is the repo, I used to load a React Application
https://github.com/kannanagasamy/react-app-without-cra
Is there a way to change the way, webpack uses ./index.js to some path like './src/index.js'?
I tried using Entry point and pointed it to './src/index.js', but it's not working and webpack is still considering index.js on root folder instead of ./src/index.js
Can somebody help me, where I am going wrong in letting webpack consider index.js inside src folder as base file.
My Current Package.Json
"scripts": {
"build": "Webpack ."
},
"devDependencies": {
"#babel/cli": "^7.18.10",
"#babel/core": "^7.19.1",
"#babel/eslint-parser": "^7.19.1",
"#babel/plugin-transform-runtime": "^7.19.1",
"#babel/preset-env": "^7.19.1",
"#babel/preset-react": "^7.18.6",
"#babel/runtime": "^7.19.0",
"babel-loader": "^8.2.5",
"eslint": "^8.23.1",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^27.0.4",
"path": "^0.12.7",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"path": "^0.12.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"#babel/cli": "^7.17.0"
}
My Current Webpack.config.file
module.exports={
mode: "development",
entry: "./index.js",
output: {
path: path.resolve(__dirname, "public"),
filename: "main.js"
},
target: "web",
resolve: {
extensions: ['.js','.jsx','.json']
},
module:{
rules: [
{
test: /\.(js|jsx)$/, //kind of file extension this rule should look for and apply in test
exclude: /node_modules/, //folder to be excluded
use: 'babel-loader' //loader which we are going to use
}
]
}
}
After updating entry point as mentioned below also, I couldn't able to move webpack to drive based on src/index.js
Codes Used
entry: path.resolve(__dirname, "src/index"),
entry: "src/index",
entry: path.resolve(__dirname, "src/index.js"),
entry: "src/index.js"
Thanks in Advance..
It seems like the issue around the command build you use which is webpack ., the option . is likely to mention the entry point at current dir ./index.js and then override the one in the configuration file so what you need to move index.js back to src/index.js and resolve the import accordingly again. Finally update the entry as you did ./src/index.js and remove . on as webpack cli.
{
build: 'webpack' // don't need to take any more extra arg
}
Its been a while since I've pushed my React app to a prod environment after a bunch of changes (dumb, I know) and now when I try to build it for prod the build is failing and I'm getting the following error:
ERROR in ./src/app.js
Module build failed: SyntaxError: Unexpected token (9:16)
7 |
8 |
> 9 | ReactDOM.render(<AppRouter />, document.getElementById('app'));
| ^
10 |
11 |
# multi #babel/polyfill ./src/app.js
error Command failed with exit code 2.
Here's my webpack.config.js file:
const path = require('path');
module.exports = (env) => {
const isProduction = env === 'production';
console.log(env);
return {
entry: ["#babel/polyfill", "./src/app.js"],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
}]
},
devtool: isProduction ? 'source-map' : 'cheap-module-eval-source-map',
devServer: {
contentBase: path.join(__dirname, 'public'),
historyApiFallback: true
}
};
};
And here's my package.json file:
{
"name": "SheSaysGo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"serve": "live-server public/",
"build:dev": "webpack",
"build:prod": "webpack -p --env production",
"dev-server": "webpack-dev-server",
"start": "node server/server.js"
},
"dependencies": {
"#babel/polyfill": "^7.4.4",
"babel-cli": "6.24.1",
"babel-core": "6.25.0",
"babel-loader": "7.1.1",
"babel-preset-env": "1.5.2",
"babel-preset-react": "6.24.1",
"chaituvr-react-graphjs-test": "^0.0.3",
"cosmicjs": "^3.2.17",
"express": "4.15.4",
"google-maps-react": "^2.0.2",
"live-server": "^1.2.1",
"lodash": "^4.17.11",
"react": "16.0.0",
"react-dom": "16.0.0",
"react-leaf-carousel": "^1.2.2",
"react-router-dom": "4.2.2",
"validator": "8.0.0",
"webpack": "3.1.0",
"webpack-dev-server": "2.5.1"
}
}
It builds when I run it locally as a dev build with "yarn run dev-server" but not when I run "yarn run build:prod".
EDIT: Sorry I had written .babel.rc, it's .babelrc
Getting babel-loader to use preset-react
It looks like Babel is interpreting your file as regular JavaScript, as opposed to React JSX (or whatever it's called).
I see in your package.json that you're using #babel/preset-react, so it should work if well configured.
In .babelrc
Check your .babelrc file, it should contain something like this:
{
"presets": ["#babel/preset-react"]
}
You can also change the extension of the file to .jsx, it find it to be clearer, but that's up to your personal preference.
In webpack.config.js
Alternatively, you can define this in the webpack config. Replace this:
loader: 'babel-loader',
with this (in your webpack.config.js):
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
},
Check the package's name
Looking closer at your package.json, it contains:
"babel-preset-env": "1.5.2",
"babel-preset-react": "6.24.1",
But you're using #babel/preset-env and #babel/preset-react. So npm install --save those and remove the old ones from your package.json.
Run babel --presets #babel/preset-react ./src/app.js, to see if the preset is there and works:
Running it should print to the console:
ReactDOM.render(React.createElement(AppRouter, null), document.getElementById('app'));
^ this is babel successfully converting JSX to JS.
Update:
Code pushed to https://github.com/gsouvik/react_spa_experiment
Initial Post:
I know there are hundreds of threads out there, some had typos in webpack config, some used the loaders in a wrong way, some got it solved, some still open. But after numerous tries I still cannot get this working, a simple "Hello World" using Webpack 4, React js.
What I did
I was following this video tutorial line by line:
React & Webpack 4 from scratch
My package.json
{
"name": "my_react_experiment_2",
"version": "1.0.0",
"description": "Basic react with webpack ",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --mode development --hot",
"build": "webpack --mode production"
},
"author": "Souvik Ghosh",
"license": "ISC",
"dependencies": {
"react": "^16.4.2",
"react-dom": "^16.4.2"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}
My webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
entry: './src/index.js',
output: {
path: path.join(__dirname, '/build'),
filename: 'index_bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/templates/index.html'
})
]
};
My .babelrc
{
"presets": ["env", "react"]
}
My directory structure
Expected behaviour
I fire up the dev server npm run dev. Expected to see my shiny new React js page saying "My first React Webpack project" (from the component /components/App.js)
Actual Behavior
ERROR in ./src/index.js 5:16
Module parse failed: Unexpected token (5:16)
You may need an appropriate loader to handle this file type.
| import App from "./components/App";
|
ReactDOM.render(, document.getElementById('root'));
| //ReactDOM.render('Hello User ', document.getElementById('root'));
# multi (webpack)-dev-server/client?http://localhost:8080 (webpack)/hot/dev-server.js ./src main2
If required I can share the codebase via a git repo. Any help is greatly appreciated.
The issue is with typo in your webpack config file.
You have module.export which is not correct. It should be module.exports
Working example
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, '/build'),
filename: 'index_bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/templates/index.html'
})
]
};
I am having difficulty in getting CSS loading using css-loader on my JSX files. I was following the example from:
https://christianalfoni.github.io/react-webpack-cookbook/Loading-CSS.html
This is my JSX
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.css';
class Hello extends React.Component {
render() {
return <div>Hello world!</div>
}
}
var el = document.getElementById('content')
var data = JSON.parse(el.getAttribute('data-attr'))
ReactDOM.render(<Hello data={data} />, el);`
This is my package.json
"devDependencies": {
"babel-core": "^6.3.26",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"css-loader": "^0.23.1",
"exports-loader": "~0.6.2",
"expose-loader": "~0.6.0",
"grunt": "^0.4.5",
"grunt-babel": "^6.0.0",
"grunt-cli": "^0.1.13",
"grunt-contrib-watch": "^0.6.1",
"grunt-webpack": "^1.0.11",
"history": "^1.17.0",
"imports-loader": "~0.6.3",
"jquery": "^2.1.4",
"lodash": "~3.0.0",
"react": "^0.14.5",
"react-dom": "^0.14.5",
"react-router": "^1.0.3",
"style-loader": "^0.13.0",
"webpack": "^1.12.9",
"webpack-dev-server": "^1.14.0"
},
"dependencies": {
"chunk-manifest-webpack-plugin": "0.0.1",
"grunt-react": "^0.12.3"
}
This is my 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/frontend/javascripts/entry.js',
stats: {
// Configure the console output
colors: true,
modules: true,
reasons: true
},
progress: true,
keepalive: true,
module: {
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader', // 'babel-loader' is also a legal name to reference
query: { presets: ['es2015', 'react'] }
},
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
},
output: {
// this is our app/assets/javascripts directory, which is part of the Sprockets pipeline
path: path.join(__dirname, 'app', 'assets', 'javascripts'),
// the filename of the compiled bundle, e.g. app/assets/javascripts/bundle.js
filename: 'bundle.js',
// if the webpack code-splitting feature is enabled, this is the path it'll use to download bundles
publicPath: '/assets',
devtoolModuleFilenameTemplate: '[resourcePath]',
devtoolFallbackModuleFilenameTemplate: '[resourcePath]?[hash]',
},
resolve: {
// tell webpack which extensions to auto search when it resolves modules. With this,
// you'll be able to do `require('./utils')` instead of `require('./utils.js')`
extensions: ['', '.js'],
// by default, webpack will search in `web_modules` and `node_modules`. Because we're using
// Bower, we want it to look in there too
modulesDirectories: [ 'node_modules', 'bower_components' ],
},
plugins: [
// we need this plugin to teach webpack how to find module entry points for bower files,
// as these may not have a package.json file
new webpack.ResolverPlugin([
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin('.bower.json', ['main'])
]),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
//new webpack.optimize.CommonsChunkPlugin('common-bundle.js'),
//new webpack.optimize.CommonsChunkPlugin('public-bundle.js')
]
};
This is my styles.css
#div {
background-color: red;
}
The output I get from running my grunt task to run 'webpack' attached:
You can see where it says the build failed for the CSS.
cjs require fbjs/lib/mapObject [154] ./~/react/lib/ReactDOMFactories.js 18:16-45
[157] ./~/react/lib/onlyChild.js 1.21 kB {0} [built]
cjs require ./onlyChild [153] ./~/react/lib/ReactIsomorphic.js 24:16-38
[158] ./~/react/lib/deprecated.js 1.77 kB {0} [built]
cjs require ./deprecated [3] ./~/react/lib/React.js 19:17-40
[159] ./~/react-dom/index.js 63 bytes {0} [built]
cjs require react-dom [0] ./app/frontend/javascripts/entry.js 11:16-36
ERROR in ./app/frontend/javascripts/styles.css
Module parse failed: /Users/Booboo/Projects/Xeon/app/frontend/javascripts/styles.css Line 1: Unexpected token {
You may need an appropriate loader to handle this file type.
| div {
| background-color: red;
| }
# ./app/frontend/javascripts/entry.js 5:0-23
Warning: Task "webpack:dev" failed. Use --force to continue.
Aborted due to warnings.
Booboo$ grunt react && grunt webpack && grunt watch
I encounter this problem too.
But in my case, I found my loader was written as
{test: '/\.css$/', loader: 'style!css'}
which should be correctly written as
{test: /\.css$/, loader: 'style!css'}
note the '' around the /.css$/
I wise this would be helpful for you.
When you say
import styles from './styles.css';
you're trying to import a module that's not being exported as a module.
Try
import './styles.css';
instead to make it a simple file import.