Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full node-js support for electron main process. #73

Closed
4 tasks done
janakg opened this issue Dec 12, 2022 · 14 comments
Closed
4 tasks done

Full node-js support for electron main process. #73

janakg opened this issue Dec 12, 2022 · 14 comments
Labels
enhancement New feature or request

Comments

@janakg
Copy link

janakg commented Dec 12, 2022

Electron vite for main process

We are new to vite eco-system, moving a large electron application from webpack to vite using electron-vite plugin. One of our dep. package is @AWS-SDK , so we landed in the below issue. Vite doesn't have full support for "mainFields" or "environment". We needed to use ssr:true in the main.
vitejs/vite#4405

Once we do that, asset handling of vite is getting messed up. It is trying to fetch() an asset from chunks/hb.cb53d2e0.wasm inside the bundled js code and fails, as it has not exported to that path and also fetch() in node process is a node-fetch polyfill that doesn't support 'relative urls'.

Suggested solution

Can we think of a solution out side vite for bundling main scripts as vite is primarily for frontend tooling? also please suggest if there is any simple way to achieve the same.

Alternative

No response

Additional context

No response

Validations

@janakg janakg added the enhancement New feature or request label Dec 12, 2022
@alex8088
Copy link
Owner

@janakg

check out: #71 (comment) for more details

import { defineConfig, externalizeDepsPlugin } from 'electron-vite'

export default defineConfig({
  main: {
    plugins: [externalizeDepsPlugin()],
  },
  preload: {
    plugins: [externalizeDepsPlugin()]
  },
  // ...
})

I don't know if it will help you.

@janakg
Copy link
Author

janakg commented Dec 12, 2022

Thanks! for the suggestion @alex8088
We have externalised a few modules. As we have substantial business logic in the main process as well, we may not be able to move everything to externals. We need to bundle else we might increase the app size.

Just to give you a bit more context. We are not able to access the assets when ssr:true unless it is an inline asset. Actually, we are trying to load our wasm module in main.

I guess this will be a common scenario for apps with many deps in main scripts.

It would be great, if there is an option to export the certain assert types in main scripts with ssr:true as well.

@alex8088
Copy link
Owner

For wasm, you can try the rollup plugin @rollup/plugin-wasm.

Or, via polyfill:

export default defineConfig({
  main: {
    resolve: {
      alias: {
        '@aws-sdk/xxx': 'polyfills/xxx',
      },
    },
  }
})

@alex8088
Copy link
Owner

electron-vite uses vite's library mode by default for the main process to build the code as a cjs standard module to support electron. I was thinking why the build ssr option can meet your needs. Or it will be better understood with an example.

@janakg
Copy link
Author

janakg commented Dec 12, 2022

export default defineConfig({
  main: {
    plugins: [tsconfigPaths], 
    build: {
      ssr: true,
      rollupOptions: {
        input: {
          index: resolve('src/main/index.ts'),
          gen: resolve('src/gen/index.ts'),
        },
        output: {
          dir: resolve(devPath, 'main'),
        },
      },
    },
    resolve: {
      alias: modAlias
    },
  },

Above is an example of main config for electron-vite
modAlias - alias of isomorphic modules (which support both browser and node)
ssr:true - is required to avoid a long list of modAlias. (this is one side of a problem)

Lets say we listed all isomorphic modules and avoided ssr.

Then here is my bundle output looks like with ssr:false

out/main/chunks/Roboto-Black.2df97579.ttf   43.78 KiB
out/main/chunks/hb.cb53d2e0.wasm            305.10 KiB
out/main/chunks/mathjs_bg.67cc5380.wasm     1253.67 KiB
out/main/index.js                           212.39 KiB
out/main/chunks/index.d1cae5ba.js           20.33 KiB
out/main/gen.js                             793.62 KiB

Then I face two problems.

  1. wasm plugins and vite's in-built wasm support using file.wasm?init depend on fetch() in node-js environment. But it is supplied with a relative url, so node-fetch fails with 'Error: only absolute urls are supported' .

  2. I am not sure how to load other assets like a font file in main script (e.g: to process the font in our font engine for text shaping )
    import fontBlob from './Roboto-Black.ttf'

After resolution, I get a relative path in both the cases chunks/hb.cb53d2e0.wasm and chunks/Roboto-Black.2df97579.ttf

I hope this clarifies. May be there is an easier way or the problem is complex, let me know if you have any questions
around this? if it helps, i can create a test repo with these cases.

@janakg
Copy link
Author

janakg commented Dec 12, 2022

Simple question would be around. If electron-vite builds the main in library mode then i guess it should have inlined all assets. https://vitejs.dev/config/build-options.html#build-assetsinlinelimit

One solution works for me: increase assetsinlinelimit to 1 MB from 4KB (Default value). Then we will have multiple copies of assets (as base64 inlined) in all bundles. We do have child process script as part of the main.

Interestingly : electron-vite version 1.0.12 bundles all assets inline without explicitly specifying assetsinlinelimit. I guess it is because of library mode but after that something has changed.

@alex8088
Copy link
Owner

@janakg Nice, please provide a test repo. Maybe I try to find a best solution.

@janakg
Copy link
Author

janakg commented Dec 12, 2022

@alex8088

PFA test case repo
https://github.com/janakg/electron-vite-app-test-case

if you enable the assetsinlinelimit in electron.vite.config.ts , it will start working.
Else it will throw fetch undefined error. We can install node-fetch to polyfill then you will get only absolute urls are supported error.

Irrespective of wasm module loading. How to load any asset file like a font in main proecss? you can reproduce that , just by commenting off the wasm module lines and just keeping

import fontBlob from './Roboto-Black.ttf'

Let me know if you have any questions

We need check this thread for hints: vitejs/vite#3295

@janakg
Copy link
Author

janakg commented Dec 12, 2022

Even resolution of public assets are not working. PFA a branch with publicDir for assets handling
https://github.com/janakg/electron-vite-app-test-case/tree/public-dir

Also, I am trying to avoid multiple copies of public directory assets used across renderer and main.
PFA config here:
https://github.com/janakg/electron-vite-app-test-case/blob/public-dir-single/electron.vite.config.ts

@onesianinflaredguard
Copy link

Hello

@alex8088
Copy link
Owner

@janakg

Both wasm and ttf are asset resolve problem. But we should know that vite is designed for web development.

  1. For wasm, vite has a build-in plugin to resolve wasm. But the way to load wasm is based on the browser. So no matter how you use ?init or ?url, you will get an error. Even if you solve the path and fetch polyfill problems. The way to load wasm in nodejs is different from that in browsers.

My solution:

  • use the rollup plugin @rollup/plugin-wasm. It also has path problem(not compatible with vite). we can set assetsDir to '' in config file. Do not use chunk dir.

    import hbWasm from './hb.wasm'
    
    const hb = await hbWasm()

I tried this way and it loads correctly, but doesn't get the exports of wasm. I don't know if it's a wasm file problem or a plugin problem.

  • Treat wasm as a public resource file and implement the method of loading wasm yourself. The above plugin can provide reference

check out: Public Directory

  1. For ttf, vite has no build-in plugin to resolve tff.

My solution:

  • Use plugin unplugin-font-to-buffer, and import font files as Buffer. It works fine.
  • Treat tff as a public resource file
const base64 = await fs.readFile('*.ttf', { encoding: 'base64' })
...

@alex8088
Copy link
Owner

alex8088 commented Dec 13, 2022

For wasm, electron-vite plans to support it in future. Maybe next or ...

@janakg
Copy link
Author

janakg commented Dec 13, 2022

@alex8088 Thanks!
I assumed the same and built a function to handle node-js based wasm import. Other assets , as of now, I am inlining them to avoid any other loaders. Loading the wasm from public directory. Thanks again for the reassurance.

@alex8088
Copy link
Owner

alex8088 commented Jan 7, 2023

new ver v1.0.17 is out! It optimizes the static asset handling in the Electron main process.

@alex8088 alex8088 closed this as completed Jan 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants