javascript - Spring Boot + React Webpack 配置
问题描述
所以我有一个需要 React 前端的 Spring boot 和基于 Java 的 REST API 项目。所以我曾经create-react-app
生成一个可以导入的简单反应项目。这是项目文件夹结构:
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
这是我的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"
]
}
}
我的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: '/' })
]
};
但是当我进行构建时,出现以下错误:
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
我需要在我的 webpack 配置中进行哪些更改才能正确构建它?
编辑 1:试图放弃设置我自己的 webpack.config 的路线,并尝试使用CRA 的反应脚本。但是我需要指定的位置,PUBLIC_URL
因为我在根级别没有名为 public 的文件夹。所以我将我的package.json
脚本部分修改为:
"scripts": {
...
"build": "set \"PUBLIC_URL=/src/main/webapp/\" && react-scripts build",
...
},
但我仍然最终得到错误:
Could not find a required file.
Name: index.html
Searched in: /.../FooApplication/public
您如何设置 CRA 的公共网址?
解决方案
.env
要设置公共位置,我相信您可以使用项目根目录中的文件设置 PUBLIC_URL ,设置该变量。
PUBLIC_URL=/src/main/webapp/
然后构建应该找到它。
也可以看看:
https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables https://facebook.github.io/create-react-app/docs/using-the-public-folder