【问题标题】:Hot reload for spring boot backend + frontendSpring Boot 后端 + 前端的热重载
【发布时间】:2018-09-28 01:08:20
【问题描述】:

我参考了那些关于 spring 开发工具和热重载的文档

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-hotswapping.html https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-restart-exclude

据此,可以看到热重载 java 和支持的 React/Typescript/webpack 应用程序的可能性

这是我们的架构(简而言之)

mainmodule
    backendModules <- those modules are just maven project have theirs poms and etc
          backendModule1
          backendModule2
fontendModule
       content <- React/Typescript/Webpack/Less etc

backendModule2 - 我们用来启动后端 backendModule1 - 只是一些附加服务 fontendModule/content - 是我们整个 react 应用程序

如果我说我必须为我们的前端文件重新加载我是对的吗:

  1. 像我通常为后端那样配置 Intellij

    1a。更改注册表

    1b。自动选择构建项目

我的问题是我必须做些什么来强制重新加载前端文件 - 所以开发人员只需要运行 1 个应用程序,然后后端 + 前端将自动重新加载

  1. 向资源模式添加前端扩展(Intellij:构建、执行 -> 编译器)? jsx、json、js、less等?

  2. 根据文档添加“spring.devtools.restart.additional-paths”

有人能做到吗?我们没有收到任何错误等...

如果有什么不清楚的地方请告诉我,以便我们澄清

【问题讨论】:

  • 在调试模式下启动将是您在 eclipse/intellij 中的最佳选择。请注意,如果您更改任何前端资产,开发人员将需要强制重新加载页面。在运行时更改分配也不可行,需要重新启动。
  • @Oskar 你如何为你的静态前端内容提供服务?
  • 可能有几种解决方案。我所做的是我有一个带有开发工具的 spring boot 后端,所以我可以很容易地从 Intellij 重新加载它。对于 Angular 前端,我只使用带有开发服务器和代理的 Angular cli,配置为将我的请求重定向到运行后端的端口。这是我为前端和后端使用开箱即用的东西,没有任何额外的黑客攻击。我不确定这样的解决方案对您是否可行。

标签: java spring maven spring-boot intellij-idea


【解决方案1】:

我知道有两种不同的方法可以做到这一点。

1) 使用 Intellij File Watcher 插件

2) 运行 webpack 开发服务器作为 spring-boot 应用程序的反向代理


1)

  • 从存储库安装插件“File Watchers”
  • 转到设置 - 工具 - 文件观察器
  • 定义一个 Webpack 任务
    • 文件类型:任何
    • 定义一个新的 Scope 以仅查看您的 javascript 文件
    • 程序:从 /node_modules/webpack/bin/webpack.js 运行 webpack 或创建一些其他可执行文件(如 $ProjectFileDir$/webpack.sh)
    • 如果您选择从 node_modules 运行 webpack(顺便说一句,由于相对路径问题,这对我不起作用)插入参数(如 --config)
    • 设置输出路径刷新:$ProjectFileDir$/src/main/static/js/bundled
    • 将工作目录设置为:$ProjectFileDir$

现在,如果您在定义的范围内保存文件,webpack 任务将运行。之后,您必须在浏览器中刷新页面。从https://intellij-support.jetbrains.com得到想法


2) 这种方式更高级,但更难正确配置。您将拥有自动重新加载(页面刷新)和完全热重新加载(反应状态持续)

基本思想是运行一个 webpack-dev-server 并将该服务器用作 spring-boot 后端的反向代理。开发服务器将自己处理对热重载内容的请求,并将其他所有内容传递给您的后端。从https://www.codingbismuth.com/ 得到这个想法。

作为示例配置

{
  "name": "",
  "version": "0.0.1",
  "description": "",
  "repository": {
    "type": "git",
    "url": ""
  },
  "keywords": [
    "xy"
  ],
  "author": "murphy",
  "license": "",
  "bugs": {
    "url": ""
  },
  "scripts": {
    "start:dev": "webpack-dev-server --config webpack.dev_server.js"
  },
  "homepage": "",
  "dependencies": {
    "file-saver": "^1.3.3",
    "prop-types": "^15.5.10",
    "react": "^16.2.0",
    "react-bootstrap-typeahead": "^2.3.0",
    "react-dom": "^16.2.0",
    "react-modal": "^3.1.8",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-datetime": "^2.11.1",
    "rest": "^1.3.1",
    "moment": "^2.20.1",
    "webpack": "^3.10.0",
    "swagger-ui": "^3.13.4",
    "webpack-dev-server": "^2.11.2"
  },
  "devDependencies": {
    "webpack-cli": "^2.0.15",
    "react-hot-loader": "^4.1.2",
    "babel-core": "^6.18.2",
    "babel-eslint": "^8.0.3",
    "babel-loader": "^7.1.2",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-react": "^6.16.0",
    "eslint": "^4.13.1",
    "eslint-plugin-react": "^7.5.1",
    "eslint-loader": "^1.9.0",
    "eslint-watch": "^3.1.3",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-jsx-a11y": "^6.0.2",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-flowtype": "^2.40.1",
    "uglifyjs-webpack-plugin2": "^1.0.3"
  }
}

const { resolve } = require('path');
const path = require('path');
const webpack = require('webpack');

module.exports = {
    context: resolve(__dirname, '.'),

    entry: [
        'react-hot-loader/patch',
        // activate HMR for React

        'webpack-dev-server/client?http://localhost:8888',
        // bundle the client for webpack-dev-server
        // and connect to the provided endpoint

        'webpack/hot/only-dev-server',
        // bundle the client for hot reloading
        // only- means to only hot reload for successful updates

        // the entry point of our app
        './src/main/js/router/mainrouter.jsx',
    ],
    output: {
        filename: './mainbundle.js',
        // the output bundle

        path: resolve(__dirname, '/src/main/resources/static/js/bundled'),

        publicPath: '/js/bundled/',
        // necessary for HMR to know where to load the hot update chunks
    },

    devtool: 'sourcemaps',
    devServer: {
        hot: true,
        contentBase: [resolve(__dirname, "."), resolve(__dirname, "./src/main/resources/static/js/bundled")],
        proxy: {
            "/": {
                target: {
                    host: "localhost",
                    protocol: 'http:',
                    port: 8087,
                },
            },
            ignorePath: true,
            changeOrigin: true,
            secure: false,
        },
        publicPath: '/js/bundled/',
        port: 8888,
        host: "localhost",
    },
    module: {
        rules: [
            {
                enforce: "pre",
                test: /\.jsx$/,
                exclude: /node_modules/,
                loader: "eslint-loader",
                options: {
                    // fix: true, // autofix
                    cache: true,
                    failOnError: false,
                    emitWarning: true,
                    quiet: true,
                },
            },
            {
                test: path.join(__dirname, '.'),
                exclude: /node_modules/,
                loader: "babel-loader",
                query: {
                    // cacheDirectory: true,
                    presets: ['es2015', 'react'],
                },
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader?modules'],
            },
        ],
    },

    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        // enable HMR globally

        new webpack.NamedModulesPlugin(),
        // prints more readable module names in the browser console on HMR updates
    ],
};

spring boot 应用在 :8087 上运行,webpack 开发服务器在 :8888 上运行。现在在您的 index.html 中包含 mainbundle.js。 运行你的 spring-boot 应用程序并在第二个终端运行:

npm run start:dev

访问 :8888 上的网页以对文件更改进行热重载。

【讨论】:

  • 感谢@murphy1312 的详细回答。我使用了上面提到的第 1 步,它非常有用,因为我浪费了大量时间重新打包应用程序。不确定为什么您的解决方案未被接受。它绝对有效。
  • 我对你提出的两种方式印象深刻,第二种方式有点复杂,我使用的第三种方式是:使用 npm 的 dev:watch 并在 targer/classes/public 中创建输出文件夹并告诉 tomcat(因为我使用战争档案)在帧停用时更新资源......更新需要 3-5 秒的时间,但减少了很多维护的复杂性。
猜你喜欢
  • 2021-05-15
  • 1970-01-01
  • 2016-11-05
  • 2018-08-25
  • 2017-10-25
  • 2020-11-05
  • 2019-02-05
  • 1970-01-01
  • 2020-09-30
相关资源
最近更新 更多