Why Electron Remote not working on Electron-Tabs?

I get these errors in my Electron App Project:

webview logged from Dashboard.html(146): Uncaught TypeError: window.require is not a function
webview logged from dashboard.js(7): Uncaught ReferenceError: require is not defined

and further errors in other files that also use the require function.

Edit: To be more explicit: These errors occur in the tab files that should be opened. Not in the main Window.

These errors occured, because i updated my electron version to the latest one (was on 10 or 11 before) – but needed new version for a new npm module.

I already tried to add nodeIntegration: true, contextIsolation: false, enableRemoteModule: true to webpreferences of main browserwindow and also to each tab in electron-tabs and it didnt work.

I will show here only the main files, because showing the whole project is too much for the question text…

Index.html for Electron:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>ExMeX Companion App</title>

  <link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css">
  <style>
    body {
      margin: 0;
    }
  </style>
</head>

<body>
  <div class="etabs-tabgroup">
    <div class="etabs-tabs"></div>
    <div class="etabs-buttons"></div>
  </div>
  <div class="etabs-views"></div>

  <script>
    // 1. Require the module
    const TabGroup = require("electron-tabs");
    // 2. Define the instance of the tab group (container)
    let tabGroup = new TabGroup({});
    let tabDashboard = tabGroup.addTab({
      title: "Dashboard",
      src: "pages/Dashboard.html",
      visible: true,
      active: true,
      webviewAttributes: {
        webSecurity: false,
        plugins: true,
        nodeIntegration: true,
        contextIsolation: false,
        enableRemoteModule: true
      }
    });
    let webviewDashboard = tabDashboard.webview;
    webviewDashboard.addEventListener('console-message', function(e) {
      var srcFile = e.sourceId.replace(/^.*[\/]/, '');
      if (srcFile == 'renderer_init.js') {
        console.log("Electron Security warning hidden from console.");
      } else {
        console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
      }
    });
    //implementation to get messages from other renderer windows
    const {
      remote,
      ipcRenderer
    } = require('electron');
    var ExmexGUITabOpened = 'false';
    var ExmexGUITabID = 0;
    ipcRenderer.on("cardClickedExmexGUI", function(event, arg) {
      if (ExmexGUITabOpened == 'false') {
        //create new tab
        console.log("Tab creation ExmexGUI");
        let tabExmexGUI = tabGroup.addTab({
          title: "Batch Orchestration",
          src: "pages/BatchOrchestration.html",
          visible: true,
          active: true,
          webviewAttributes: {
            webSecurity: false,
            plugins: true,
            nodeIntegration: true,
            contextIsolation: false,
            enableRemoteModule: true
          }
        });
        ExmexGUITabOpened = 'true';
        ExmexGUITabID = tabExmexGUI.id;
        tabExmexGUI.on("close", (tab) => {
          ExmexGUITabOpened = 'false';
          ExmexGUITabID = 0;
        });
        let webview2 = tabExmexGUI.webview;
        webview2.addEventListener('console-message', function(e) {
          var srcFile = e.sourceId.replace(/^.*[\/]/, '');
          if (srcFile == 'renderer_init.js') {
            console.log("Electron Security warning hidden from console.");
          } else {
            console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
          }
        });
      } else {
        let activeExmexTab = tabGroup.getTab(ExmexGUITabID);
        activeExmexTab.activate();
      }
    });
    var ExmexConfigurationTabOpened = 'false';
    var ExmexConfigurationTabID = 0;
    ipcRenderer.on("cardClickedExmexConfiguration", function(event, arg) {
      if (ExmexConfigurationTabOpened == 'false') {
        //create new tab
        console.log("Tab creation ExmexConfiguration");
        let tabExmexConfig = tabGroup.addTab({
          title: "ExMeX Configuration",
          src: "pages/ExmexConfiguration.html",
          visible: true,
          active: true,
          webviewAttributes: {
            webSecurity: false,
            plugins: true,
            nodeIntegration: true,
            contextIsolation: false,
            enableRemoteModule: true
          }
        });
        ExmexConfigurationTabOpened = 'true';
        ExmexConfigurationTabID = tabExmexConfig.id;
        tabExmexConfig.on("close", (tab) => {
          ExmexConfigurationTabOpened = 'false';
          ExmexConfigurationTabID = 0;
        });
        let webview3 = tabExmexConfig.webview;
        webview3.addEventListener('console-message', function(e) {
          var srcFile = e.sourceId.replace(/^.*[\/]/, '');
          if (srcFile == 'renderer_init.js') {
            console.log("Electron Security warning hidden from console.");
          } else {
            console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
          }
        });
      } else {
        let activeExmexConfigTab = tabGroup.getTab(ExmexConfigurationTabID);
        activeExmexConfigTab.activate();
      }
    });

    var ExmexSourceFilterTabOpened = 'false';
    var ExmexSourceFilterTabID = 0;
    ipcRenderer.on("cardClickedSourceFilter", function(event, arg) {
      if (ExmexSourceFilterTabOpened == 'false') {
        //create new tab
        console.log("Tab creation SourceFilter");
        let tabSourceFilter = tabGroup.addTab({
          title: "Filter Configuration",
          src: "pages/FilterConfiguration.html",
          visible: true,
          active: true,
          webviewAttributes: {
            webSecurity: false,
            plugins: true,
            nodeIntegration: true,
            contextIsolation: false,
            enableRemoteModule: true
          }
        });
        ExmexSourceFilterTabOpened = 'true';
        ExmexSourceFilterTabID = tabSourceFilter.id;
        tabSourceFilter.on("close", (tab) => {
          ExmexSourceFilterTabOpened = 'false';
          ExmexSourceFilterTabID = 0;
        });
        let webview4 = tabSourceFilter.webview;
        webview4.addEventListener('console-message', function(e) {
          var srcFile = e.sourceId.replace(/^.*[\/]/, '');
          if (srcFile == 'renderer_init.js') {
            console.log("Electron Security warning hidden from console.");
          } else {
            console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
          }
        });
      } else {
        let activeExmexSourceFilterTab = tabGroup.getTab(ExmexSourceFilterTabID);
        activeExmexSourceFilterTab.activate();
      }
    });
  </script>
</body>

</html>

Main.js for electron

/*jshint esversion: 8 */
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

const path = require('path');
const url = require('url');


global.mainWindow = null;

/* Configuration for server is stored in these variables, accessible for all windows or tabs */
/*Test Config*/


const appversion = '0.5.0 Beta';

/*Live Config*/
global.user = 'Not available';
global.password = 'Not Set';
global.server = 'Not available';
global.serverPort = 0;
global.database = 'Not available';
global.serverInfoText = 'Server connection is not configured.';
global.installedExmexVersion = 'ExMeX | Core ? | App ' + appversion + '';
global.trustedConnectionOption = 'no';

global.userDeploy = '';
global.passwordDeploy = '';
global.serverDeploy = '';
global.databaseDeploy = '';

function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1080,
    height: 1000,
    webPreferences: {
      webviewTag: true,
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true
    }
  });

  // Open the DevTools.
  //mainWindow.webContents.openDevTools();

  //remove the top menu from electron
  //mainWindow.removeMenu();

  // load the index.html of the app.
  mainWindow.loadFile('index.html');

}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow);



// Quit when all windows are closed.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});


const {
  ipcMain
} = require('electron'); // include the ipc module to communicate with render process ie to receive the message from render process

ipcMain.on("setUser", function(event, arg) {
  global.user = arg;
});
ipcMain.on("setPassword", function(event, arg) {
  global.password = arg;
});
ipcMain.on("setServer", function(event, arg) {
  global.server = arg;
});
ipcMain.on("setServerPort", function(event, arg) {
  global.serverPort = parseInt(arg, 10);
});
ipcMain.on("setDatabase", function(event, arg) {
  global.database = arg;
});


ipcMain.on("setServerInfoText", function(event, arg) {
  global.serverInfoText = arg;
});
ipcMain.on("setInstalledExmexVersion", function(event, arg) {
  global.installedExmexVersion = 'ExMeX | Core ' + arg + ' | App ' + appversion + '';
});
ipcMain.on("setTrustedConnection", function(event, arg) {
  global.trustedConnectionOption = arg;
});


const Store = require('electron-store');
Store.initRenderer();

Dashboard.html
This is the first Tab that should be opened, here the error occurs at the first time

<!doctype html>
<html lang="en" class="no-js">
<!-- <link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css"> -->
<link rel="stylesheet" href="../css/dashboard.css">
<link rel="stylesheet" href="../css/sweetalert.css" />

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>ExMeX Dashboard App</title>
</head>

<body>

  <div class="grid-container-dashboard">
    <header class="header">
      <div class="header_server_info">
        <p style="font-size:16px">Server</p>
        <p style="font-size:12px" id="serverInfoText">No server connection.</p>
      </div>
      <!-- Button to open the serverConfigPopupWindow -->
      <div class="header_server_connect">
        <button id="myBtn" class="header_button"> Connect</button>
      </div>
      <div id="serverConfigPopupWindow" class="modal">
        <div class="modal-content">
          <!-- <span class="close">&times;</span> -->
          <p style="font-size:20px ">Configure the server connection</p>
          <br><br>
          <div class="box">
            <p class="item1">Server Name: </p> <input type="text" id="serverInputField" class="item2" placeholder="Server to connect">
          </div>
          <div class="box">
            <p class="item1">Server Port: </p> <input type="text" id="serverPortInputField" class="item2" placeholder="Port to connect" value="1433">
          </div>
          <div class="box">
            <p class="item1">Database Name: </p> <input type="text" id="databaseInputField" class="item2" placeholder="Your ExMeX database name">
          </div>
          <div class="box">
            <p class="item1">Authentication Mode: </p>
            <select class="item2" id="authenticationModeOptionField" onclick="showOrHideUserPWFields()">
              <option>Windows Authentication</option>
              <option>SQL Server Authentication</option>
            </select>
          </div>
          <div class="box" id="userBox" style="visibility: hidden">
            <p class="item1">User: </p> <input type="text" id="userInputField" class="item2" placeholder="Your user login name">
          </div>
          <div class="box" id="passwordBox" style="visibility: hidden">
            <p class="item1">Password: </p> <input type="password" id="passwordInputField" class="item2" placeholder="Your password">
          </div>
          <br><br>
          <textarea type="text" id="OutputTestServerConnection" name="FilterSPOutput" disabled rows="4" cols="70" style="resize: none;">Output will be shown after saving first filter.
                </textarea>
          <button id="testServerConfig" class="blue_button_big" onclick="testServerConfigFunction()">Connect</button>
          <button id="cancelServerConfig" class="blue_button_big" onclick="cancelServerConfigFunction()">Cancel</button>
        </div>
      </div>
    </header>
    <aside class="sidenav">
      <img src="../img/TedamohLogoFull.png" style="  display: block; margin-left: auto; margin-right: auto; width: 90%; height:80px; object-fit: contain;" alt="Logo" id="spin">
      <ul class="sidenav_list">
        <p style="font-size:20px">Quick Links</p>
        <li class="sidenav_list-item" id="sidenav_Tedamoh" onclick="openTedamohHomepageInBrowser()">TEDAMOH</li>
        <li class="sidenav_list-item" id="sidenav_Helpdesk" onclick="openHelpdeskInBrowser()">Helpdesk</li>
        <li class="sidenav_list-item" id="sidenav_FAQ" onclick="openFAQInBrowser()">FAQ</li>
        <li class="sidenav_list-item" id="sidenav_Documentation" onclick="openDocumentationInBrowser()">Documentation</li>
      </ul>
    </aside>
    <main class="main">
      <div class="main-header">
        <div class="main-header_heading">
          <img src="../img/ExMeX_Banner_Dashboard.png" style="width: 100%; height: 100%; " alt="ExMeX Dashboard">
        </div>
        <!-- <div class="main-header_updates">A powerful interface component for the Tedamoh ExMeX Framework. <br />We call it ExMeX Companion App!</div> -->
      </div>
      <div class="main-overview-dashboard">
        <div class="overviewcard" id="cardIDExmexConfiguration">
          <div class="overviewcard_icon"><img src="../img/dashboard_config.png" style="width:70px;height:70px;" alt="ConfigIcon"></div>
          <div class="overviewcard_info">Exmex Configuration</div>
        </div>
        <div class="overviewcard" id="cardIDExmexGUI">
          <div class="overviewcard_icon"><img src="../img/dashboard_threearrows.png" style="width:70px;height:70px;" alt="ThreeArrowIcon"></div>
          <div class="overviewcard_info">Batch Orchestration</div>
        </div>
        <div class="overviewcard" id="cardIDFilterConfig">
          <div class="overviewcard_icon"><img src="../img/dashboard_filter.png" style="width:70px;height:70px;" alt="FilterIcon"></div>
          <div class="overviewcard_info">Filter Configuration</div>
        </div>

        <!-- future -->
        <div class="overviewcard" id="cardIDFuture4" style=" pointer-events: none;">
          <!-- <div class="overviewcard_icon">Icon</div>
            <div class="overviewcard_info">Future feature</div> -->
        </div>
        <div class="overviewcard" id="cardIDFuture5" style=" pointer-events: none;">
          <!-- <div class="overviewcard_icon">Icon</div>
            <div class="overviewcard_info">Future feature</div> -->
        </div>
        <div class="overviewcard" id="cardIDFuture6" style=" pointer-events: none;">
          <!-- <div class="overviewcard_icon">Icon</div>
            <div class="overviewcard_info">Future feature</div> -->
        </div>
        <div class="overviewcard" id="cardIDFuture7" style=" pointer-events: none;">
          <!-- <div class="overviewcard_icon">Icon</div>
            <div class="overviewcard_info">Future feature</div> -->
        </div>
        <div class="overviewcard" id="cardIDFuture8" style=" pointer-events: none;">
          <!-- <div class="overviewcard_icon">Icon</div>
            <div class="overviewcard_info">Future feature</div> -->
        </div>
        <div class="overviewcard" id="cardIDFuture9" style=" pointer-events: none;">
          <!-- <div class="overviewcard_icon">Icon</div> -->
          <!-- <div class="overviewcard_info">Future feature</div> -->
        </div>
        <!-- future end -->
      </div>
    </main>
    <footer class="footer">
      <div class="footer_copyright">&copy; 2019-2022 TEDAMOH GmbH</div>
      <div class="footer_signature" id="footer_signature">ExMeX | Core ? | App ?</div>
    </footer>
  </div>

</body>

<!-- Insert this line above script imports  -->

<script>
  if (typeof module === 'object') {
    window.module = module;
    module = undefined;
  }
</script>

<!-- normal script imports etc  -->

<script src="../js/sweetalert.min.downloaded.js"></script>

<script src="../js/swal-messages.js"></script>
<!-- scripts for opening the links on the dashboard  -->

<script>
  const {
    shell
  } = window.require('electron');

  function openDocumentationInBrowser() {
    shell.openExternal("https://tedamoh.com/de/helpdesk/doc-faq/exmex-framework-book");
  }

  function openFAQInBrowser() {
    shell.openExternal("https://tedamoh.com/de/helpdesk/doc-faq/frequently-asked-questions");
  }

  function openTedamohHomepageInBrowser() {
    shell.openExternal("https://tedamoh.com/de/");
  }

  function openHelpdeskInBrowser() {
    shell.openExternal("https://tedamoh.com/de/helpdesk/my-tickets");
  }
</script>

<script src="../js/SQLConnectAndQuery.js"></script>

<script src="../js/dashboard.js"></script>


<!-- Insert this line after script imports -->

<script>
  if (window.module) module = window.module;
  actualizeVersionInfo('footer_signature');
</script>



</html>

Dashboard.js
This is the javascript for the first tab that should be opened.

/*jshint esversion: 8 */

// include the ipc module to communicate with main process.
const {
  remote,
  ipcRenderer
} = require('electron');


const Store = require('electron-store');
const store = new Store();
//if store file was never initialized, put defaults in it
if (store.get('serverConfigStore') == undefined) {
  store.set('serverConfigStore', {
    serverName: "Server to connect",
    serverPort: 1433,
    databaseName: "Your ExMeX database name",
    authenticationMode: "Windows Authentication",
    user: ""
  });
}
// console.log(store.get('serverConfigStore').serverName);
// console.log(store.get('serverConfigStore').serverPort);
// console.log(store.get('serverConfigStore').databaseName);


let btnclick2 = document.getElementById('cardIDExmexGUI');
btnclick2.addEventListener('click', () => {
  var arg2 = "secondparam";

  //send the info to main process . we can pass any arguments as second param.
  //ipcRenderer.send("btnclick", arg); // ipcRender.send will pass the information to main process
  let mainWindowTest2 = remote.getGlobal('mainWindow');
  if (mainWindowTest2) mainWindowTest2.webContents.send("cardClickedExmexGUI", arg2);
});

let btnclick3 = document.getElementById('cardIDExmexConfiguration');
btnclick3.addEventListener('click', () => {
  var arg3 = "secondparam";

  //send the info to main process . we can pass any arguments as second param.
  //ipcRenderer.send("btnclick", arg); // ipcRender.send will pass the information to main process
  let mainWindowTest3 = remote.getGlobal('mainWindow');
  if (mainWindowTest3) mainWindowTest3.webContents.send("cardClickedExmexConfiguration", arg3);
});

let btnclick4 = document.getElementById('cardIDFilterConfig');
btnclick4.addEventListener('click', () => {
  var arg4 = "secondparam";

  //send the info to main process . we can pass any arguments as second param.
  //ipcRenderer.send("btnclick", arg); // ipcRender.send will pass the information to main process
  let mainWindowTest4 = remote.getGlobal('mainWindow');
  if (mainWindowTest4) mainWindowTest4.webContents.send("cardClickedSourceFilter", arg4);

});


// Get the modal
var modal = document.getElementById("serverConfigPopupWindow");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on the button, open the modal
btn.onclick = function() {

  console.log(store.get('serverConfigStore').serverName);
  console.log(store.get('serverConfigStore').serverPort);
  console.log(store.get('serverConfigStore').databaseName);

  console.log('The connect button clicked and onclickfunction starts');
  modal.style.display = "block";
  document.getElementById('OutputTestServerConnection').innerHTML = '';

  document.getElementById('serverInputField').value = store.get('serverConfigStore').serverName;
  document.getElementById('serverPortInputField').value = store.get('serverConfigStore').serverPort;
  document.getElementById('databaseInputField').value = store.get('serverConfigStore').databaseName;
  document.getElementById('userInputField').value = store.get('serverConfigStore').user;

  //Make sure that authentication mode is one of the two possible values (instead a poweruser changes the config file manually...)
  if (store.get('serverConfigStore').authenticationMode == "Windows Authentication" || store.get('serverConfigStore').authenticationMode == "SQL Server Authentication") {
    document.getElementById('authenticationModeOptionField').value = store.get('serverConfigStore').authenticationMode;
  } else {
    document.getElementById('authenticationModeOptionField').value = "Windows Authentication";
  }

  showOrHideUserPWFields();

};
// When the user clicks on <span> (x), close the modal
// span.onclick = function() {
//  modal.style.display = "none";
// };
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
};

function testServerConfigFunction() {
  console.log("The test server config button was clicked.");
  document.getElementById('OutputTestServerConnection').innerHTML = 'Wait for database response...';

  const sql = require('mssql/msnodesqlv8');

  var authOption = '' + document.getElementById('authenticationModeOptionField').value;
  var trustedAuthBool = false;
  if (authOption == 'Windows Authentication') {
    trustedAuthBool = true;
  }
  var config;

  //if trustedAuthBool is true, then WindowsAuthentification should be used (no User+PW)
  if (trustedAuthBool) {
    config = {
      user: 'Win User',
      password: 'Win User',
      server: '' + document.getElementById('serverInputField').value,
      database: '' + document.getElementById('databaseInputField').value,
      port: parseInt(document.getElementById('serverPortInputField').value, 10),
      options: {
        trustedConnection: "yes"
      }
    };
  }
  //else SQL Server Authentification is available (User+PW needed)
  else {
    config = {
      user: '' + document.getElementById('userInputField').value,
      password: '' + document.getElementById('passwordInputField').value,
      server: '' + document.getElementById('serverInputField').value,
      database: '' + document.getElementById('databaseInputField').value,
      port: parseInt(document.getElementById('serverPortInputField').value, 10)
    };
  }
  // async function invocation - connect to db and try a query
  queryDatabase(config, 'Select TOP(1) ReleaseVersion FROM [MetadataZone].[TEDAMOHExMeXRelease] Order by ReleaseInstalledDate DESC')
    .then(result => {
      var obj = JSON.parse(JSON.stringify(result.recordsets[0]));
      console.log('Connection succesful! Your last installed ExMeX Version is: ' + obj[0].ReleaseVersion);

      const {
        remote,
        ipcRenderer
      } = require('electron');
      ipcRenderer.send('setInstalledExmexVersion', '' + obj[0].ReleaseVersion);
      var s = obj[0].ReleaseVersion;
      if ((s.match(/2.12.*/)) || (s.match(/2.11.*/)) || (s.match(/2.10.*/)) || (s.match(/2.9.*/)) || (s.match(/2.8.*/)) || (s.match(/2.7.*/)) || (s.match(/2.6.*/)) || (s.match(/2.5.*/))) {
        swal('Old ExMeX Version installed', 'On the connected database the latest installed ExMeX Version is lower than 2.13.* ! The companion App will not work stable in all features! Please install the latest ExMeX release.', 'warning');
      }
      //document.getElementById('footer_signature').innerHTML = "ExMeX Version: " + obj[0].ReleaseVersion;
      actualizeVersionInfo('footer_signature');
    })
    .catch(err => {
      sql.close();
      console.log("A connection error happened");
      document.getElementById('OutputTestServerConnection').innerHTML = 'An error occurred while trying to query the database. The detailed error message is: ' + err.message;
    });

  // async function invocation - connect to db and try a query
  queryDatabase(config, 'SELECT SUSER_NAME() as LoggedInUser;')
    .then(result => {
      var obj = JSON.parse(JSON.stringify(result.recordsets[0]));
      console.log('Connection succesful! Your SysUsername is: ' + obj[0].LoggedInUser);
      const {
        remote,
        ipcRenderer
      } = require('electron');
      modal.style.display = "none";
      var sysusername = obj[0].LoggedInUser;
      saveServerConfigFunction(config, sysusername);
    })
    .catch(err => {
      sql.close();
      console.log("A connection error happened");
      document.getElementById('OutputTestServerConnection').innerHTML = 'An error occurred while trying to query the database. The detailed error message is: ' + err.message;
    });
}


//needed to delete some parts here for question length

I hope this is something where you can follow the code and give me an advise, on how to change my electron code to get the require function working on my tabs.

Best wishes!