首页 > 解决方案 > 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 的公共网址?

标签: javascriptreactjsspring-bootwebpack

解决方案


.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


推荐阅读