`process is not defined` after importing ipcLink in renderer
Closed this issue · 10 comments
At first, that entire code works if I copy/paste it into my app. When I tried to use the npm package I faced with that issue:
I am using electron-react-boilerplate
I think it is caused because I am using import { ipcLink } from 'electron-trpc';
. When I am trying to use import { ipcLink } from 'electron-trpc/renderer';
I am getting:
Module not found: Error: Package path ./renderer is not exported from package [...]/node_modules/electron-trpc
Hi, sorry for getting back to you late.
Can you clarify for me which versions of trpc
and electron-trpc
you are using?
If you were running this off the next
branch, you needed to be on electron-trpc@next
and trpc
v10 pre-release.
Today I've cut the 0.2.0 release of electron-trpc
which works with trpc v10. If you're in a position to update to these versions and can compare with the example in the repo, if you're still having issues I'll be able to help further.
I installed a new version 0.2.0 and I faced an issue with Electron React Boilerplate webpack's build step which is run always after adding a new package:
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ electron-trpc@0.2.0
info All dependencies
└─ electron-trpc@0.2.0
$ ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts
{"type":"warning","data":"Filtering by arguments is deprecated. Please use the pattern option instead."}
Native dependencies could not be checked
• electron-builder version=23.6.0
• loaded configuration file=[...]/electron-builder.json
• installing production dependencies platform=darwin arch=arm64 appDir=[...]/release/app
ERROR in dll renderer renderer[20]
Module not found: Error: Package path . is not exported from package [...]/node_modules/electron-trpc (see exports field in [...]/node_modules/electron-trpc/package.json)
webpack compiled with 1 error
error Command failed with exit code 1.
If I add electron-trpc to webpack's externals
in webpack.config.renderer.dev.dll.ts
then it works, but after that I am getting another issue while importing createIPCHandler: Cannot find module 'electron-trpc/main' or its corresponding type declarations.
I added electron-trpc@0.2.0
to a new electron-react-boilerplate project and I didn't get the error you mentioned when installing.
I'm also able to get a working query using just the example in the project here. I'm adding the diff below, if you want to see what that looks like.
If you're still having issues, maybe you can push your project to a repo I can pull down to reproduce?
diff --git a/src/main/main.ts b/src/main/main.ts
index 327b81f..d3137c4 100644
--- a/src/main/main.ts
+++ b/src/main/main.ts
@@ -14,6 +14,8 @@ import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
+import { createIPCHandler } from 'electron-trpc/main';
+import { router } from './router';
class AppUpdater {
constructor() {
@@ -25,12 +27,6 @@ class AppUpdater {
let mainWindow: BrowserWindow | null = null;
-ipcMain.on('ipc-example', async (event, arg) => {
- const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`;
- console.log(msgTemplate(arg));
- event.reply('ipc-example', msgTemplate('pong'));
-});
-
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
@@ -128,6 +124,7 @@ app
.whenReady()
.then(() => {
createWindow();
+ createIPCHandler({ router });
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
diff --git a/src/main/preload.ts b/src/main/preload.ts
index d35fdfe..5e4212a 100644
--- a/src/main/preload.ts
+++ b/src/main/preload.ts
@@ -1,23 +1,5 @@
-import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
+import { exposeElectronTRPC } from 'electron-trpc/main';
-export type Channels = 'ipc-example';
-
-contextBridge.exposeInMainWorld('electron', {
- ipcRenderer: {
- sendMessage(channel: Channels, args: unknown[]) {
- ipcRenderer.send(channel, args);
- },
- on(channel: Channels, func: (...args: unknown[]) => void) {
- const subscription = (_event: IpcRendererEvent, ...args: unknown[]) =>
- func(...args);
- ipcRenderer.on(channel, subscription);
-
- return () => {
- ipcRenderer.removeListener(channel, subscription);
- };
- },
- once(channel: Channels, func: (...args: unknown[]) => void) {
- ipcRenderer.once(channel, (_event, ...args) => func(...args));
- },
- },
+process.once('loaded', () => {
+ exposeElectronTRPC();
});
diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx
index eb321c5..a58e09a 100644
--- a/src/renderer/App.tsx
+++ b/src/renderer/App.tsx
@@ -1,14 +1,24 @@
+import { useState } from 'react';
import { MemoryRouter as Router, Routes, Route } from 'react-router-dom';
+import { createTRPCReact } from '@trpc/react-query';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import { ipcLink } from 'electron-trpc/renderer';
+import type { AppRouter } from '../main/router';
import icon from '../../assets/icon.svg';
import './App.css';
+const trpcReact = createTRPCReact<AppRouter>();
+
const Hello = () => {
+ const { data } = trpcReact.greeting.useQuery();
+
return (
<div>
<div className="Hello">
<img width="200" alt="icon" src={icon} />
</div>
<h1>electron-react-boilerplate</h1>
+ <h2>From backend: {data?.text}</h2>
<div className="Hello">
<a
href="https://electron-react-boilerplate.js.org/"
@@ -40,11 +50,21 @@ const Hello = () => {
};
export default function App() {
+ const [queryClient] = useState(() => new QueryClient());
+
+ const [trpcClient] = useState(() =>
+ trpcReact.createClient({ links: [ipcLink()] })
+ );
+
return (
- <Router>
- <Routes>
- <Route path="/" element={<Hello />} />
- </Routes>
- </Router>
+ <trpcReact.Provider client={trpcClient} queryClient={queryClient}>
+ <QueryClientProvider client={queryClient}>
+ <Router>
+ <Routes>
+ <Route path="/" element={<Hello />} />
+ </Routes>
+ </Router>
+ </QueryClientProvider>
+ </trpcReact.Provider>
);
}
diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx
index a96350e..b7b48c1 100644
--- a/src/renderer/index.tsx
+++ b/src/renderer/index.tsx
@@ -4,10 +4,3 @@ import App from './App';
const container = document.getElementById('root')!;
const root = createRoot(container);
root.render(<App />);
-
-// calling IPC exposed from preload script
-window.electron.ipcRenderer.once('ipc-example', (arg) => {
- // eslint-disable-next-line no-console
- console.log(arg);
-});
-window.electron.ipcRenderer.sendMessage('ipc-example', ['ping']);
I also tried it on fresh ERB repo and both errors still occur.
I added
electron-trpc@0.2.0
to a new electron-react-boilerplate project and I didn't get the error you mentioned when installing.
Could you try to run yarn postinstall
or npm run postinstall
? It occurs during this step.
I'm also able to get a working query using just the example in the project here. I'm adding the diff below, if you want to see what that looks like.
I hope it will work but IDE shows it can't find type declarations. I'm guessing it happens because of the lack of .d.ts in the package. Correct me if I am wrong.
I see, so there's two separate issues here.
One is in how that project's webpack.config.renderer.dev.dll.ts
reads dependencies kinda naively. It's going to add electron-trpc
to the entries, but that's not a valid entry point—this package has two possible entries, electron-trpc/main
and electron-trpc/renderer
. Here's a short fix for that:
diff --git a/.erb/configs/webpack.config.renderer.dev.dll.ts b/.erb/configs/webpack.config.renderer.dev.dll.ts
index 614b90f..fd1bdff 100644
--- a/.erb/configs/webpack.config.renderer.dev.dll.ts
+++ b/.erb/configs/webpack.config.renderer.dev.dll.ts
@@ -31,7 +31,9 @@ const configuration: webpack.Configuration = {
module: require('./webpack.config.renderer.dev').default.module,
entry: {
- renderer: Object.keys(dependencies || {}),
+ renderer: Object.keys(dependencies || {}).map((dep) =>
+ dep === 'electron-trpc' ? 'electron-trpc/renderer' : dep
+ ),
},
output: {
The other issue is a mistake on my part, the .d.ts
files were being generated but not included in the package. I've published electron-next@0.2.1
which fixes this.
Your setup may need to be tweaked to take advantage of this, however. When using the updated package in my ERB setup I had to update moduleResolution
in the tsconfig.json
from node
to node16
for TS to take advantage. At that point I no longer got TS warnings about the types not being found, but I was still getting eslint warnings. You may want to see if there's an eslint setting or update needed to take advantage of the package.json exports field. EDIT: Looks like exports map is not supported by eslint-plugin-import yet: import-js/eslint-plugin-import#2580
Thank you for your help, now it works. Also, I don't have any issues with eslint-plugin-import
neither in my project nor the ERB repo. Which eslint's warning do you get?
I have a little problem with automatic imports in VSC after changing moduleResolution
to node16
.
It imports automatically [...]/Example/Example
or [...]/Example/index
, but previously it was just [...]/Example
. Of course, I can import it like that by hand but it is a little bit annoying when you need to do it manually.
Do you have any idea how to handle it? I never used node16
before.
Edit: It can also be a little bit annoying for other users of this package to do all of those setups so here are a few ideas:
- What do you think about getting rid of the
exports
field and splitting theelectron-trpc
package into two npm packages (electron-trpc/main and electron-trpc/renderer) with separated package.json files, but both placed in the same monorepo? Then settingmoduleResolution
tonode16
will be unnecessary and also changing anERB's
webpack configuration will not be needed. - On the other hand, maybe setting
package.json's
browser
torenderer.js
andmain
tomain.js
instead ofexports
will do the trick? - Or just set
package.json's
types
top field to point oneindex.d.ts
instead of two separated inexports
.
Do you have any idea how to handle it? I never used
node16
before.
Another solution to stick with node
instead of setting node16
is to add paths
to tsconfig.json
like:
"paths": {
"electron-trpc/main": ["../node_modules/electron-trpc/dist/main"],
"electron-trpc/renderer": ["../node_modules/electron-trpc/dist/renderer"],
}
Note:
paths
is relative to thebaseUrl
But still, it needs to do some additional setup which feels like a workaround.
-
eslint-plugin-import
gives an error for meUnable to resolve path to module 'electron-trpc/main'. [Error/import/no-unresolved]
I think the config can be adjusted to not give the error for this package.
-
What do you think about getting rid of the exports field and splitting the electron-trpc package into two npm packages
I'll think about this, but I'm inclined to keep things the way they are.
Usage of the
exports
field is not so widespread yet, but I do expect it to become a more popular alternative to multiple packages in some cases. It's normal for there to be some hiccups as more projects are able to support this. For now, plenty of tooling supports this out-of-the-box (node, webpack, rollup, vite). TypeScript has supported it for a couple major versions. Requiring two packages to be installed is a guaranteed cost, having to reconfigure a project to support exports is a possible cost, but not every user will have to do this.electron-react-boilerplate could read traverse dependencies and read exports map itself when building its DLL config if it so chose (this would work for electron-trpc but not all projects), or take an approach other than the DLL.
I read more about exports and the node16 option. I also thought more about this case and I agree with you. I think we can close this as resolved. Thank you for your time.