From c203cf25aa8ce39bf81afeb05d3ab1d5b132297d Mon Sep 17 00:00:00 2001 From: Jacques Lorentz Date: Mon, 26 Sep 2022 19:51:51 +0200 Subject: [PATCH] fix: #272 Front end application base url with path --- Dockerfile | 2 +- client/config-overrides.js | 47 ++++++++++++++++++++++++++++++++++ client/package-lock.json | 42 ++++++++++++++++++++++++++++++ client/package.json | 7 ++--- client/public/index.html | 1 + client/src/api/socket.js | 3 ++- client/src/constants/Config.js | 8 +++++- client/src/constants/Paths.js | 12 +++++---- server/config/views.js | 3 ++- 9 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 client/config-overrides.js diff --git a/Dockerfile b/Dockerfile index fdbd4c0a..62d348c4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ COPY server . RUN cp .env.sample .env COPY --from=client-builder /app/build public -COPY --from=client-builder /app/build/index.html views +COPY --from=client-builder /app/build/index.html views/index.ejs VOLUME /app/public/user-avatars VOLUME /app/public/project-background-images diff --git a/client/config-overrides.js b/client/config-overrides.js new file mode 100644 index 00000000..21c3b646 --- /dev/null +++ b/client/config-overrides.js @@ -0,0 +1,47 @@ +const fs = require('fs'); +const path = require('path'); + +const BASE_URL_PLACEHOLDER = 'BASE_URL_PLACEHOLDER'; + +const replaceInFile = (file, search, replace) => { + fs.readFile(file, 'utf8', (err, data) => { + if (err) { + throw new Error(`${err}`); + } + const res = data.replaceAll(search, replace); + fs.writeFile(file, res, 'utf8', (err) => { + if (err) { + throw new Error(`${err}`); + } + }); + }); +}; + +const replaceBaseUrl = (compiler) => { + compiler.hooks.assetEmitted.tap("Test", (file, info) => { + if (info.content.indexOf(BASE_URL_PLACEHOLDER) >= 0) { + if (/\.css$/.exec(info.targetPath)) { + // For CSS 'url(...)' import we can use relative import + const relPath = path.relative(path.dirname(info.targetPath), info.outputPath); + replaceInFile(info.targetPath, BASE_URL_PLACEHOLDER, `${relPath}/`); + } else if (/\.js$/.exec(info.targetPath)) { + // For JS 'import ... from "some-asset"' we can get the variable injected in the window object + replaceInFile(info.targetPath, `"${BASE_URL_PLACEHOLDER}"`, '`${window.BASE_URL}/`'); + } else if (/index\.html$/.exec(info.targetPath)) { + // For the main html file, we set a placeholder for sails to inject the correct value as runtime + replaceInFile(info.targetPath, BASE_URL_PLACEHOLDER, '<%= BASE_URL %>'); + } + } + }); +}; + +module.exports = function override(config, env) { + config.plugins.forEach(plugin => { + if (plugin.constructor.name === 'InterpolateHtmlPlugin') { + plugin.replacements.PUBLIC_URL = BASE_URL_PLACEHOLDER; + } + }); + config.plugins.push({ apply: replaceBaseUrl }); + config.output.publicPath = BASE_URL_PLACEHOLDER; + return config; +}; diff --git a/client/package-lock.json b/client/package-lock.json index 915cfd50..f69a43cd 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -63,6 +63,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "jest-enzyme": "^7.1.2", "prettier": "2.7.1", + "react-app-rewired": "^2.2.1", "react-test-renderer": "^17.0.2" } }, @@ -18665,6 +18666,30 @@ "node": ">=14" } }, + "node_modules/react-app-rewired": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz", + "integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==", + "dev": true, + "dependencies": { + "semver": "^5.6.0" + }, + "bin": { + "react-app-rewired": "bin/index.js" + }, + "peerDependencies": { + "react-scripts": ">=2.1.3" + } + }, + "node_modules/react-app-rewired/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/react-beautiful-dnd": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", @@ -38717,6 +38742,23 @@ "whatwg-fetch": "^3.6.2" } }, + "react-app-rewired": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz", + "integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==", + "dev": true, + "requires": { + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "react-beautiful-dnd": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", diff --git a/client/package.json b/client/package.json index f4f05ae7..104986f3 100755 --- a/client/package.json +++ b/client/package.json @@ -2,11 +2,11 @@ "name": "planka-client", "private": true, "scripts": { - "build": "react-scripts build", + "build": "react-app-rewired build", "eject": "react-scripts eject", "lint": "eslint --ext js,jsx src", - "start": "react-scripts start", - "test": "react-scripts test" + "start": "react-app-rewired start", + "test": "react-app-rewired test" }, "browserslist": { "production": [ @@ -120,6 +120,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "jest-enzyme": "^7.1.2", "prettier": "2.7.1", + "react-app-rewired": "^2.2.1", "react-test-renderer": "^17.0.2" } } diff --git a/client/public/index.html b/client/public/index.html index e8955e7e..fc7327a7 100755 --- a/client/public/index.html +++ b/client/public/index.html @@ -26,6 +26,7 @@ --> Planka +
diff --git a/client/src/api/socket.js b/client/src/api/socket.js index 2902661b..94c2cbf5 100755 --- a/client/src/api/socket.js +++ b/client/src/api/socket.js @@ -5,7 +5,7 @@ import Config from '../constants/Config'; const io = sailsIOClient(socketIOClient); -io.sails.url = Config.SERVER_BASE_URL; +io.sails.url = Config.HOST_NAME; io.sails.autoConnect = false; io.sails.reconnection = true; io.sails.useCORSRouteToGetCookie = false; @@ -13,6 +13,7 @@ io.sails.environment = process.env.NODE_ENV; const { socket } = io; +socket.path = `${Config.BASE_PATH}/socket.io`; socket.connect = socket._connect; // eslint-disable-line no-underscore-dangle ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].forEach((method) => { diff --git a/client/src/constants/Config.js b/client/src/constants/Config.js index 28fb3747..05313a0c 100755 --- a/client/src/constants/Config.js +++ b/client/src/constants/Config.js @@ -1,6 +1,10 @@ +const { BASE_URL } = window; +const HOST_NAME = BASE_URL.replace(/^(.*\/\/[^/?#]*).*$/, '$1'); +const BASE_PATH = BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1'); + const SERVER_BASE_URL = process.env.REACT_APP_SERVER_BASE_URL || - (process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1337'); + (process.env.NODE_ENV === 'production' ? BASE_URL : 'http://localhost:1337'); const ACCESS_TOKEN_KEY = 'accessToken'; const ACCESS_TOKEN_VERSION_KEY = 'accessTokenVersion'; @@ -10,6 +14,8 @@ const POSITION_GAP = 65535; const ACTIVITIES_LIMIT = 50; export default { + HOST_NAME, + BASE_PATH, SERVER_BASE_URL, ACCESS_TOKEN_KEY, ACCESS_TOKEN_VERSION_KEY, diff --git a/client/src/constants/Paths.js b/client/src/constants/Paths.js index 1278d3cd..6f0d666a 100755 --- a/client/src/constants/Paths.js +++ b/client/src/constants/Paths.js @@ -1,8 +1,10 @@ -const ROOT = '/'; -const LOGIN = '/login'; -const PROJECTS = '/projects/:id'; -const BOARDS = '/boards/:id'; -const CARDS = '/cards/:id'; +import Config from './Config'; + +const ROOT = `${Config.BASE_PATH}/`; +const LOGIN = `${Config.BASE_PATH}/login`; +const PROJECTS = `${Config.BASE_PATH}/projects/:id`; +const BOARDS = `${Config.BASE_PATH}/boards/:id`; +const CARDS = `${Config.BASE_PATH}/cards/:id`; export default { ROOT, diff --git a/server/config/views.js b/server/config/views.js index 55ec7950..557ebf29 100644 --- a/server/config/views.js +++ b/server/config/views.js @@ -24,7 +24,7 @@ module.exports.views = { * */ - extension: 'html', + extension: 'ejs', /** * @@ -36,4 +36,5 @@ module.exports.views = { */ layout: false, + locals: { BASE_URL: process.env.BASE_URL }, };