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

Better Electron support #7753

Closed
zhuhaow opened this issue Feb 24, 2022 · 2 comments
Closed

Better Electron support #7753

zhuhaow opened this issue Feb 24, 2022 · 2 comments

Comments

@zhuhaow
Copy link

zhuhaow commented Feb 24, 2022

I'm quite new to parcel and just started to go through the source code, so some things I talked about below may be wrong.

While I have some undeveloped ideas and already started working on a fork, I think it's better to get some feedback in the early stage.

The following contains something the same from #2492, something different, and some other details.

The basic design

Given the main script

const { app, BrowserWindow } = require('electron')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: 'preload.js'
    }
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})

The user just need to set

{
    "targets": {
        "main": {
            "source": "main.js",
            "context": "electron"
        }
    }
}

Then three bundle targets (or maybe assets? not sure yet) are created with

  • main.js
    • context: electron-main
    • external: electron, ...
  • index.html
    • context: electron-renderer
    • external: ...
  • preload.js
    • context: electron-preload
    • external: node built-in modules and electron, ...

The New Contexts

Here we are creating two new contexts here, electron and electron-preload. It makes sense to have electron in this case since we don’t have an umbrella context to cover all Electron environments. electron-preload is not very useful just as electron-main and electron-renderer are not. They provide very few default configurations that users can do themselves if they want to.
But I’ll still keep them just for compatibility reasons. But some of the default configurations may not even make sense, e.g., electron-renderer set includeNodeModules to false by default while Electron has nodeIntegration set to false by default thus we should actually include node_modules by default.

I checked webpack code and AFAICT the only thing it does is to exclude some electron modules from bundling. For swc, it’s doing nothing with the Electron env set. And parcel is also just ignoring electron for bundling. So it seems like these contexts are really not doing that much but create unnecessary fragmentations for development and maintenance. (Maybe we can transform them into more basic configurations with context as node or browser immediately so we don’t have to handle them anywhere else?)

Finding Dependencies

I don’t think it’s easy to analyze the AST and understand the win is actually an instance of BrowserWindow imported from electron, so maybe for simplicity, at least for a quicker start, we can just look for a method called loadFile in the main.js target. For the same reason, we can try to find a dictionary value with the key as preload as the preload entry point.

Getting the Electron Runtime Configuration

Renderer and preload are two different environments with different configurations (e.g., #2492). We need a way to get the configurations, such as whether nodeIntegration, sandbox are enabled or not. So we can infer the default external module set or whether to bundle node_modules when building the targets.

This is not easy to get from the main.js file by analyzing the AST, so maybe a query format can help, such as win.loadFile(index.html?nodeIntegration=true), or preload.js?sandbox=true. The default value should be the same as the Electron default.

Development Workflow

With parcel serve, the parcel would build all three (or more) targets, replace loadFile() with loadURL() of the address of the dev server(s), and then start electron for the user.

With parcel build, everything is put to dist folder that is ready to be packaged by electron-forge or electron-builder directly. We won’t copy node_modules for the user so the user can do it only if needed. Packaging an electron app is too complicated at least it’s beyond the scope for now.

Native Modules

I’m not very experienced on this issue but I think it’s more complicated than #2493 for Electron.

For development, users should call electron-rebuild themselves.

For production, we can only know the target platform when we are packaging the app. Even with #2493 resolved, I don’t think we can have a perfect solution for this without integration with electron-forge or electron-builder, but that would be quite heavy.

But the good part is, I don’t see there will be any breaking change if we add support for native modules in the future.

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.

@TechQuery
Copy link

I build an Electron scaffold with Parcel 2: idea2app/Electron-Parcel-PNPM.tsx#1

@github-actions github-actions bot removed the Stale Inactive issues label Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants