I guess I like building things with JavaScript 🤷♂️
karolis-sh / electron-snowpack Goto Github PK
View Code? Open in Web Editor NEWUse Snowpack and esbuild for Electron app development
License: MIT License
Use Snowpack and esbuild for Electron app development
License: MIT License
I guess I like building things with JavaScript 🤷♂️
src/main/*
doesn't support TypeScript. It would be nice if it could.
When creating a BrowserWindow with a preload script, which exposes electron via a context bridge, this preload script is not bundled to dist/main, so in production it can't be found.
Minimal example of code:
window = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
preload: path.join(__dirname, "preload.js"), < PROBLEM
},
});
This is also the same for any scripts loaded with fork.
How can I include these additional scripts into the output for main?
As preload
is explicitly passed to the browser window (preload: path.join(__dirname, 'preload.js'),
), there could be a use-case for multiple preload files for different browser windows.
This is more a question than anything else. But I was wondering if its possible to use packages like koffi or node-ffi. I tried to see if I could add it manually to the package but I had no luck. I know that the creator of koffi just made some changes so that it works with electron so realistically it should work but I'm assuming there are some changes I need to make to access my dlls using this. Any help would be appreciated.
Implement some sort of log level mode mechanics:
snowpack
:
--verbose Enable verbose log messages.
--quiet Enable minimal log messages.
esbuild
(info | warning | error | silent):
echo 'typeof x == "null"' | esbuild --log-level=error
Error: Unable to find any entrypoint for "supabase". It could be a typo, or this package might not have a main entrypoint.
Thanks for the examples.
When I run "npm run dist" in the react-typescript example, the generated app opens an empty window, even though "npm run dev" displays the app as expected.
I got the same issue on both linux and mac.
Any ideas?
Thanks
Firstly, the relativeImport
on Windows has backslashes "\" in the path instead of forward slashes "/" which is why this relative proxy import plugin breaks on Windows. The fix is straightforward which is to normalize the relativeImport path.
snowpack-plugin-relative-proxy-imports.js
...
if (firstLine === `export default "/${relativeImport}";`) {
...
Secondly, the when the bundle/minify flag under the Snowpack optimize config are enabled it breaks as well. I assume under bundling it breaks because no *.proxy.js files are emitted. And for minification it changes export default "/someimport"
to export default"/someimport"
and the if statement doesn't get checked.
I suppose the fix for minification, you can remove check for the import without the space. Not exactly sure what you would do for bundling one
Given how brittle this plugin is, I'm wondering if there's a better way to alter the export.
Hi, I've been trying to make sqlite3 work on the react-typescript example ((link)) and it doesn't seem to work, have any of you tried anything similar?
The steps to reproduce are as follows.
package.json
:"scripts": {
"postinstall": "install-app-deps"
...
}
npm install --save-dev electron-builder
npm install --save sqlite3
npm run postinstall
src/main/index.ts
import sqlite3 from "sqlite3";
console.log(sqlite3);
npm run dev
And then it throws the error:
[17:24:40] [@snowpack/plugin-typescript] 4:23:40 PM - Starting compilation in watch mode...
[electron] App threw an error during load
(...)
[electron] A JavaScript error occurred in the main process
Uncaught Exception:
Error: package.json does not exist at /opt/electron-snowpack/examples/react-typescript/dist/package.json
at Object.exports2.find (/opt/electron-snowpack/examples/react-typescript/dist/main/index.js:10559:15)
at node_modules/sqlite3/lib/sqlite3-binding.js (/opt/electron-snowpack/examples/react-typescript/dist/main/index.js:10778:31)
at __require (/opt/electron-snowpack/examples/react-typescript/dist/main/index.js:9:44)
at node_modules/sqlite3/lib/sqlite3.js (/opt/electron-snowpack/examples/react-typescript/dist/main/index.js:10828:20)
at __require (/opt/electron-snowpack/examples/react-typescript/dist/main/index.js:9:44)
at Object.<anonymous> (/opt/electron-snowpack/examples/react-typescript/dist/main/index.js:11000:33)
at Module._compile (internal/modules/cjs/loader.js:1078:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
at Module.load (internal/modules/cjs/loader.js:935:32)
at Module._load (internal/modules/cjs/loader.js:776:14)
Thanks in advance.
We are currently evaluating snowpack
and I am very grateful for your work on this integration.
We use monaco-editor
in our app and using @monaco-editor/react for this works quite well.
The only issue I am facing is that by default that package loads monaco sources from a CDN. We need to provide them ourselves and for that we have to include monaco-editor/min/vs
directly or at least all scripts that are used from there (editor.worker.js, etc and one for every language).
What do I have to do to achieve this? I have tried using snowpack-plugin-copy
but haven't yet found the place to copy these sources to.
I also tried using mount
in snowpack.config.js
like this:
module.exports = {
mount: {
'node_modules/monaco-editor/min/vs': {static: true, resolve:false, url: '/monaco-editor'},
},
}
and then use loader
like this:
import { loader } from "@monaco-editor/react";
loader.config(
{
paths: {
vs: "/monaco-editor"
}
}
)
This kind of works but I get these errors:
[snowpack] [404] /min-maps/vs/loader.js.map
✘react-typescript-snowpack/public/min-maps/vs/loader.js
[snowpack] [404] /min-maps/vs/editor/editor.main.js.map
✘ react-typescript-snowpack/public/min-maps/vs/editor/editor.main.js
[snowpack] [404] /min-maps/vs/editor/editor.main.nls.js.map
✘ react-typescript-snowpack/public/min-maps/vs/editor/editor.main.nls.js
[snowpack] [404] /min-maps/vs/base/worker/workerMain.js.map
✘ react-typescript-snowpack/public/min-maps/vs/base/worker/workerMain.js
I would really appreciate any help you can provide.
Run on window system, I Got an error
node: 12.16.1
window10
error:
Value "" must be a URL path, and start with a "/"
[electron-snowpack] �🚨 An unexpected error has occurred!
It seems that the first line of electron-snowpack\config\snowpack.js
is modified to const path = require('path').posix;
that can fix it
I don't know if there are other problems
electron
. Curremtly it's only looking for electron 11, but I don't see anything in this lib that actually requires any specific version of electron.getAssetUrl
you are using url.format
which is deprecated in node v15. I know that electron uses a slightly older version, but switching to using the default URL constructor is the recommended fix. Personally I replaced url.format
with new URL(``file:///${path.join(__dirname, asset)}``).href
main
seems easy - https://esbuild.github.io/api/#minifyrenderer
- snowpack-plugin-relative-proxy-imports
would not work with bunding/minificationThanks @karolis-sh for your work on trying to bring snowpack to Electron app development!
The alias
config option from snowpack.config.js
does not seem to be respected in both renderer and main parts of the program.
For example, setting in snowpack's config: alias: { '@/': './src' }
(with respective tsconfig.json
entries) does not work as intended. I've attached a diff that sets alias options in the react-typescript example. The electron part logs the following error:
[electron] Error: Cannot find module '@/common/constants'
and the renderer part produces:
[snowpack] [404] /dist/@/common/constants
Normally this feature works very well in vanilla snowpack.
Diff which sets alias options on the react-typescript example (adds alias
to snowpack.config.js, baseUrl
and paths
options in tsconfig.json, and a small module, which is accessed with the alias.
diff --git a/examples/react-typescript/snowpack.config.js b/examples/react-typescript/snowpack.config.js
index 808fb1e..7b33c1b 100644
--- a/examples/react-typescript/snowpack.config.js
+++ b/examples/react-typescript/snowpack.config.js
@@ -1,5 +1,6 @@
/** @type { import("snowpack").SnowpackUserConfig } */
module.exports = {
extends: 'electron-snowpack/config/snowpack.js',
+ alias: { '@/': './src' },
plugins: ['@snowpack/plugin-react-refresh'],
};
diff --git a/examples/react-typescript/src/common/constants.ts b/examples/react-typescript/src/common/constants.ts
new file mode 100644
index 0000000..8fb001a
--- /dev/null
+++ b/examples/react-typescript/src/common/constants.ts
@@ -0,0 +1 @@
+export const TEST = 0;
diff --git a/examples/react-typescript/src/main/index.ts b/examples/react-typescript/src/main/index.ts
index 63e9e4e..3b7c47c 100644
--- a/examples/react-typescript/src/main/index.ts
+++ b/examples/react-typescript/src/main/index.ts
@@ -1,7 +1,10 @@
import { app, BrowserWindow } from 'electron';
import { getAssetURL } from 'electron-snowpack';
+import { TEST } from '@/common/constants';
+
let mainWindow: BrowserWindow | null | undefined;
+let id: ReturnType<typeof setInterval>;
function createMainWindow(): BrowserWindow {
const window = new BrowserWindow();
@@ -14,6 +17,7 @@ function createMainWindow(): BrowserWindow {
window.on('closed', (): void => {
mainWindow = null;
+ clearInterval(id);
});
window.webContents.on('devtools-opened', (): void => {
@@ -38,6 +42,7 @@ app.on('activate', (): void => {
// on macOS it is common to re-create a window even after all windows have been closed
if (mainWindow === null) {
mainWindow = createMainWindow();
+ id = setInterval(() => console.log(TEST), 1000);
}
});
diff --git a/examples/react-typescript/src/renderer/App.tsx b/examples/react-typescript/src/renderer/App.tsx
index f4f832c..cdcbac3 100644
--- a/examples/react-typescript/src/renderer/App.tsx
+++ b/examples/react-typescript/src/renderer/App.tsx
@@ -1,5 +1,7 @@
import React, { useState, useEffect } from 'react';
+import { TEST } from '@/common/constants';
+
import logo from './logo.svg';
import './App.css';
@@ -31,6 +33,7 @@ const App: React.FC = () => {
Learn React
</a>
</p>
+ <p>Test = {TEST}</p>
<div>
<img
src={`${import.meta.env.SNOWPACK_PUBLIC_BASE_HREF}/snowpack.svg`}
diff --git a/examples/react-typescript/tsconfig.json b/examples/react-typescript/tsconfig.json
index 3e7ba7e..99b0e47 100644
--- a/examples/react-typescript/tsconfig.json
+++ b/examples/react-typescript/tsconfig.json
@@ -1,4 +1,8 @@
{
"extends": "electron-snowpack/config/tsconfig.json",
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "paths": { "@/*": ["*"] }
+ },
"include": ["src", "types"]
}
Hello,
First of all thank you for your fantastic work on this. It has helped me save time immensely.
I'd like to request adding support for a shared folder. Especially when Typescript is also supported for src/main in the future.
One use case for this is for interfaces that can be shared between main and renderer.
Consider the following interface:
export interface Something { somethingA: string; somethingB: number; }
Then in the main process we have an IPC handle:
ipcMain.handle("my-channel", (event, args) => { // Return something or do something });
And in the renderer:
ipcRenderer.invoke("my-channel", something);
Likewise for common services that could be shared between main and renderer.
Thanks
When I tried to run the try
script in the examples (no pun intended), npm complained it didn't know the run-s
command.
Installing the npm-run-all
package as a dev dependency solved it for me. Is this package maybe installed globally on your machine @karolis-sh?
It would be nice to have typings (or even convert to TypeScript)
I was struggling with VSCode debuggin of the main process. Finally I've discovered that all that was needed was configuring the sourcemap inside the esbuild configuration.
I've added sourcemap = 'inline'
to the options parameter for getESBuildConfig
inside the dev command and it worked like a charm.
Hey 👋 ! Great work, thank you for this project!
I noticed that .env files are correctly read in dev mode in the main, but not in production (using yarn try
for ex). Any idea on how I could make this work?
Thanks a lot 🙏
I was expecting that as soon as i change something the view should update.
in the Iogs can see that snowpack is doing its thing as expected, but i have to manually reload (Ctrl+r) to see the changes.
Am i missing something essential or misinterpreted how it should behave?
Currently my port 9510 is used by some process. I know I could find which process is the issue or just restart, but I would prefer if I could just change the port with a ENV variable or config file or something
In PR #41, we made esbuild make a bundle for preload.js
. In this script, there is some cases use third party packages except for 'electron' such as 'lodash' and 'redis'. However default esbuild config 'external' only contains 'electron' so that 'preload.js' cannot import other third party packages.
For this reason, I suggest to add the way to pass the additional config to get-esbuild-config.js
or load it in the script. If you think it is needed and you can give me some guide to do it with documentation, I will send PR.
Example:
// my-project/package.json
{
"name": "my-project",
...,
"electron-snowpack": {
"esbuild": {
"external": ["electron", "lodash", "redis"]
}
},
...
}
// electron-snowpack/config/index.js
...
const projectRoot = process.cwd()
const isTS = fs.existsSync(path.join(projectRoot, 'tsconfig.json'));
const packageConfig = require(path.join(projectRoot, 'package.json'));
const userConfig = (packageConfig['electron-snowpack'] && packageConfig['electron-snowpack'].esbuild) || {};
module.exports = {
...,
isTs,
userConfig,
};
// electron-snowpack/lib/get-esbuild-config.js
...
const config = require('../config');
module.exports = async (more) => {
...
more = Object.assign({}, more, config.userConfig);
...
return {
platform: 'node',
format: 'cjs',
entryPoints: await promisify(glob)('src/main/@(index|preload).[jt]s'),
outdir: path.join(config.outputDir, 'main'),
bundle: true,
external: ['electron'],
define,
logLevel,
...(dev ? {} : { minify: true }),
...more,
};
}
I was testing the examples. They work perfectly in dev but when I try the .exe (created with npm run dist) I alwasy get an empty HTML and the devtools open up automatically as in dev mode, as if the process.env.MODE
wasn't set to "production".
Live reload in src/main/*
is not implemented. Let's implement this!
Implement the Snowpack's reload
option:
--reload Clear the local cache (useful for troubleshooting).
https://www.snowpack.dev/reference/javascript-interface#clearcache()
I've been trying to move all my electron projects over from webpack to snowpack recently as I've loved it so much for web applications. I'm having a few issues trying to add a preload script so if I could get some help/verification that would be great!
Within my index.ts
(which is located inside src > main) I currently have this code while creating my browser window:
webPreferences: {
devTools: !app.isPackaged,
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.ts'),
},
I then wrote my preload functions and declared my types in my preload.d.ts
file but I haven't had any luck calling my functions from my renderer code. I have all my appropriate event listeners setup in my index.ts
file as well. I'd appreciate any help.
Thanks!
I'm using https://github.com/lovell/sharp-libvips in my project.
When running electron-snowpack dev --verbose I get below error.
How do I configure a loader for Native Node Modules?
Thanks!
[16:22:37] [@snowpack/plugin-react-refresh] transform() starting… [node_modules/sharp/build/Release/sharp.node]
[16:22:37] [@snowpack/plugin-react-refresh] ✔ transform() success [node_modules/sharp/build/Release/sharp.node]
[16:22:37] [esinstall:sharp] FAILURE: Error: Unexpected character '�' (Note that you need plugins to import files that are not JavaScript)
[16:22:37] [esinstall:sharp] Failed to load ../build/Release/sharp.node
Unexpected character '�' (Note that you need plugins to import files that are not JavaScript)
[electron-snowpack] Error: Install failed.
[electron-snowpack] 🚨 An unexpected error has occurred!
Cannot open devtools
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.