Hey guys,
Any ideas on why I'm getting the following warning and an empty page when creating our add-in with the json config of:
{
"name": "orderNow",
"supportEmail": "support@test.io",
"version": "2.0.8",
"items": [
{
"url": "https://hostUrl.io/plugin.html",
"path": "ActivityLink/",
"menuName": {
"en": "Connection Settings"
},
"svgIcon": "https://hostUrl.io/orderNow/images/icon.svg"
}
],
"isSigned": false
}The add-in does show up in the proper place but I'm getting an empty page with this warning in the console:
No routes matched location "/addin-addinName"We've built the add in on top of the Geotab Add In generator repo which prefilled most of our configurations / webpack configs.
The url is pointing to the distribution version of the plugin but for some reason it doesn't load properly.
Our webpack config for the build:
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const config = require("./src/config.json");
const { name: appName } = config;
const transform = function (content, path) {
let config = JSON.parse(content);
let host = config.dev.dist.host;
let len = config.items.length;
const { name } = config;
for (let i = 0; i < len; i++) {
config.items[i].url = host + config.items[i].url;
if (config.items[i].svgIcon) {
config.items[i].svgIcon = host + config.items[i].svgIcon;
}
if (config.items[i].icon) {
config.items[i].icon = host + config.items[i].icon;
}
}
delete config["dev"];
let response = JSON.stringify(config, null, 2);
// Returned string is written to file
return response;
};
const jsFileName = () => {
let fileName = "[name]-[contenthash].js";
return fileName;
};
module.exports = {
mode: "production",
entry: {
bundle: path.resolve(__dirname, "src/app/index.js"),
},
output: {
path: path.resolve(__dirname, "dist"),
filename: jsFileName,
assetModuleFilename: "[name][ext]",
clean: true,
},
devServer: {
static: {
directory: path.resolve(__dirname, "dist"),
},
port: 3000,
open: true,
hot: true,
compress: true,
historyApiFallback: true,
},
devtool: "source-map",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.scss/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
},
{
test: /\.(js|jsx)$/,
exclude: [/node_modules/],
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
[
"@babel/preset-react",
{
runtime: "automatic",
},
],
],
},
},
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
},
],
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"], // Ensure TypeScript files can be resolved
},
plugins: [
new MiniCssExtractPlugin({
filename: "styles.css",
chunkFilename: "styles.css",
}),
new HtmlWebpackPlugin({
title: "plugin",
filename: `plugin.html`,
template: "src/app/plugin.html",
inject: "body",
}),
new CopyWebpackPlugin({
patterns: [
{ from: "./src/app/images/icon.svg", to: "images/" },
{
from: "./src/config.json",
transform: transform,
to: "configuration.json",
},
],
}),
new webpack.DefinePlugin({
"process.env.REACT_APP_PROJECT_ID": JSON.stringify(
process.env.REACT_APP_PROJECT_ID
),
"process.env.REACT_APP_ENV": JSON.stringify(process.env.REACT_APP_ENV),
"process.env.BE_PUBLIC_API_BASE_URL": JSON.stringify(
process.env.BE_PUBLIC_API_BASE_URL
),
"process.env.BE_PUBLIC_APP_API_KEY": JSON.stringify(
process.env.BE_PUBLIC_APP_API_KEY
)
}),
],
};The dist html file does have the js bundle in it as well which looks like this:
<!doctype html><html><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="description" content=""/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>order-now</title><link href="styles.css" rel="stylesheet"></head><body><div id="plugin-app"><div id="plugin"><header class="geotabPageHeader"><h1 class="geotabPageName">Test Plugin <span class="subdued">Subtitle</span></h1><div class="pageNameSecondary"><h3 class="geotabSecondaryTitle">by: <span id="plugin-user"></span></h3></div></header></div></div><script defer="defer" src="bundle-a4d4cf3841901f6be89a.js"></script></body></html>It seems that React doesn't seem to be able to mount on it which is weird as the dev version does work locally and loads the emulated login flow with the app
Can this be caused by the way our router is set up in app.jsx?
const App = ({ geotabApi, geotabState, appName }) => {
const logger = useMemo(() => Logger(appName), [appName]);
const [context, setContext] = useState({ geotabApi, geotabState, logger });
useEffect(() => {
async function fetchSession() {
try {
geotabApi.getSession((session) => {
if (session) {
setContext((prev) => ({
...prev,
database: session.database,
sessionUser: session.userName,
sessionId: session.sessionId,
}));
}
});
} catch (error) {
logger.error("Failed to fetch Geotab session", error);
}
}
fetchSession();
}, [geotabApi, logger]);
return (
<>
<GeotabContext.Provider value={[context, setContext]}>
<Router>
<Routes>
<Route path="/" element={<ConnectionSettings />} />
<Route path="/setup/pillars" element={<PillarConfig />} />
</Routes>
</Router>
</GeotabContext.Provider>
</>
);
};
export default App;