So I have a Spring boot and Java based REST API project that required a React frontend. So I used create-react-app to generate a simple react project that I could import. Here's the project folder structure:
FooApplication
├── build.gradle
├── package.json
├── node_modules/
├── src/
├── main/
├── java/
├── resources/
└── webapp/
├── app/
├── App.js
├── index.js
└── serviceWorker.js
└── index.html
└── test
├── webpack/
├── utils.js
└── webpack.config.js
Here's my package.json:
{
"name": "boss-management-service",
"version": "0.1.0",
"private": true,
"dependencies": {
"base-href-webpack-plugin": "2.0.0",
"browser-sync": "2.26.7",
"browser-sync-webpack-plugin": "2.2.2",
"copy-webpack-plugin": "5.0.3",
"html-webpack-plugin": "3.2.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"start": "^5.1.0",
"webpack": "4.37.0",
"webpack-cli": "3.3.6",
"write-file-webpack-plugin": "4.5.0"
},
"scripts": {
"start": "NODE_ENV=development BABEL_ENV=development",
"build": "npm run start && npm run webpack -- --config webpack/webpack.config.js",
"webpack": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
And my webpack.config.json:
const webpack = require('webpack');
const writeFilePlugin = require('write-file-webpack-plugin');
const { BaseHrefWebpackPlugin } = require('base-href-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const utils = require('./utils.js');
module.exports = {
entry: './src/main/webapp/app/index.js',
output: {
path: utils.root('build/resources/main/static/'),
filename: 'app/[name].bundle.js',
chunkFilename: 'app/[id].chunk.js'
},
cache: true,
resolve: {
extensions: [
'.js', '.jsx'
],
modules: ['node_modules'],
alias: {
App: utils.root('src/main/webapp/app/')
}
},
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg|woff2?|ttf|eot)$/i,
loader: 'file-loader',
options: {
digest: 'hex',
hash: 'sha512',
name: 'content/[hash].[ext]'
}
},
{
test: /\.js$/,
exclude: [/node_modules/],
loader: 'babel-loader',
options: {
presets: ["@babel/preset-env", "@babel/preset-react"]
}
},
{
test: /\.css$/,
loader: ['style-loader', 'css-loader']
}
]
},
plugins: [
new BrowserSyncPlugin({
https: true,
host: 'localhost',
port: 9000,
proxy: {
target: `http://localhost:9060`,
proxyOptions: {
changeOrigin: false //pass the Host header to the backend unchanged https://github.com/Browsersync/browser-sync/issues/430
}
},
socket: {
clients: {
heartbeatTimeout: 60000
}
}
}, {
reload: false
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new writeFilePlugin(),
new webpack.WatchIgnorePlugin([
utils.root('src/test'),
]),
new CopyWebpackPlugin([
{ from: './src/main/webapp/static/', to: 'content' },
{ from: './src/main/webapp/favicon.ico', to: 'favicon.ico' },
{ from: './src/main/webapp/manifest.webapp', to: 'manifest.webapp' },
{ from: './src/main/webapp/robots.txt', to: 'robots.txt' }
]),
new HtmlWebpackPlugin({
template: './src/main/webapp/index.html',
chunksSortMode: 'dependency',
inject: 'body'
}),
new BaseHrefWebpackPlugin({ baseHref: '/' })
]
};
But when I do a build I get the following error:
ERROR in ./src/main/webapp/app/index.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /.../src/main/webapp/app/index.js: Unexpected token (7:16)
5 | import * as serviceWorker from 'serviceWorker';
6 |
> 7 | ReactDOM.render(<App />, document.getElementById('root'));
| ^
8 |
9 | // If you want your app to work offline and load faster, you can change
10 | // unregister() to register() below. Note this comes with some pitfalls.
at Parser.raise (/.../node_modules/@babel/parser/lib/index.js:6325:17)
at Parser.unexpected (/.../node_modules/@babel/parser/lib/index.js:7642:16)
at Parser.parseExprAtom (/.../node_modules/@babel/parser/lib/index.js:8841:20)
at Parser.parseExprSubscripts (/.../node_modules/@babel/parser/lib/index.js:8412:23)
at Parser.parseMaybeUnary (/.../node_modules/@babel/parser/lib/index.js:8392:21)
at Parser.parseExprOps (/.../node_modules/@babel/parser/lib/index.js:8267:23)
at Parser.parseMaybeConditional (/.../node_modules/@babel/parser/lib/index.js:8240:23)
at Parser.parseMaybeAssign (/.../node_modules/@babel/parser/lib/index.js:8187:21)
at Parser.parseExprListItem (/.../node_modules/@babel/parser/lib/index.js:9491:18)
at Parser.parseCallExpressionArguments (/.../node_modules/@babel/parser/lib/index.js:8621:22)
at Parser.parseSubscript (/.../node_modules/@babel/parser/lib/index.js:8514:29)
at Parser.parseSubscripts (/.../node_modules/@babel/parser/lib/index.js:8433:19)
at Parser.parseExprSubscripts (/.../node_modules/@babel/parser/lib/index.js:8422:17)
at Parser.parseMaybeUnary (/.../node_modules/@babel/parser/lib/index.js:8392:21)
at Parser.parseExprOps (/.../node_modules/@babel/parser/lib/index.js:8267:23)
at Parser.parseMaybeConditional (/.../node_modules/@babel/parser/lib/index.js:8240:23)
at Parser.parseMaybeAssign (/.../node_modules/@babel/parser/lib/index.js:8187:21)
at Parser.parseExpression (/.../node_modules/@babel/parser/lib/index.js:8135:23)
at Parser.parseStatementContent (/.../node_modules/@babel/parser/lib/index.js:9958:23)
at Parser.parseStatement (/.../node_modules/@babel/parser/lib/index.js:9829:17)
at Parser.parseBlockOrModuleBlockBody (/.../node_modules/@babel/parser/lib/index.js:10405:25)
at Parser.parseBlockBody (/.../node_modules/@babel/parser/lib/index.js:10392:10)
at Parser.parseTopLevel (/.../node_modules/@babel/parser/lib/index.js:9758:10)
at Parser.parse (/.../node_modules/@babel/parser/lib/index.js:11270:17)
at parse (/.../node_modules/@babel/parser/lib/index.js:11306:38)
at parser (/.../node_modules/@babel/core/lib/transformation/normalize-file.js:170:34)
at normalizeFile (/.../node_modules/@babel/core/lib/transformation/normalize-file.js:138:11)
at runSync (/.../node_modules/@babel/core/lib/transformation/index.js:44:43)
at runAsync (/.../node_modules/@babel/core/lib/transformation/index.js:35:14)
at process.nextTick (/.../node_modules/@babel/core/lib/transform.js:34:34)
at process._tickCallback (internal/process/next_tick.js:61:11)
Child html-webpack-plugin for "index.html":
1 asset
Entrypoint undefined = index.html
[./node_modules/html-webpack-plugin/lib/loader.js!./src/main/webapp/index.html] 1.74 KiB {0} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]
+ 1 hidden module
What do I need to change in my webpack config to get this to built properly?
Edit 1: Tried to ditch the route of setting up my own webpack.config and tried to use the CRA's react scripts. But I need to specify the location of the PUBLIC_URL since I do not have a folder named public in the root level. So I modified my package.json script section to so:
"scripts": {
...
"build": "set \"PUBLIC_URL=/src/main/webapp/\" && react-scripts build",
...
},
But I still end up getting the error:
Could not find a required file.
Name: index.html
Searched in: /.../FooApplication/public
How do you set CRA's public url?