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

feat: I guess it's esm #37535

Merged
merged 47 commits into from Aug 31, 2023
Merged

feat: I guess it's esm #37535

merged 47 commits into from Aug 31, 2023

Conversation

MarshallOfSound
Copy link
Member

@MarshallOfSound MarshallOfSound commented Mar 8, 2023

This PR is a little chonky and it fixes a lot of things and changes some things under the hood. In theory though this PR contains zero breaking changes and it should be fully backwards compatible with existing applications. However due to the scope of the changes this change will not be backported.

Things that were fixed

  • Loading ESM files from within an asar file now actually works instead of throwing ENOTDIR
  • Using an ESM file type: module or index.mjs as the entrypoint to your Electron app now works
  • Using an ESM file as a preload script when sandbox is disabled now works
  • Using dynamic ESM import() calls from within a non-sandboxed context isolated preload script now correctly uses node's ESM loader instead of always using blinks

Things that were changed

  • Preload scripts with the extension .mjs are now always loaded via the ESM loader, when node is enabled. This could result in some interesting side-effects but so far testing seems to show it's ok. Existing preload scripts that have the .js extension will continue to operate exactly how they used to, ESM preload scripts have some gotchas that have been documented.
  • The main process now has its event loop manually pumped until the initial script load / evaluate is complete. This allows node's internal ESM implementation to be async without impacting Electron's core assumptions about synchronous startup hooks provided by Chromium
    • This technically allows apps to hang themselves by for instance doing a top level await app.whenReady() which result in effectively a spinlock
  • Preload scripts now "defer" loading of the page until the preload script load / evaluate is complete. This allows node's internal ESM implementation to be async without impacting the "preload runs first" part of Electron's preload scripts
  • The default_app is now ESM, partially to support additional ESM entrypoints from end-user apps but also to prove that this all works 😅

Known Limitations / Things that can't be fixed

  • Check the docs/tutorial/esm-limitations.md in this PR

TODO

  • Test the performance implications of these changes, they're cool but I have a feeling that startup time with ESM vs CJS might be slower. Would be good to know for sure
  • Tests, so many tests...

Notes: Enabled ESM support. For more details, see the ESM limitations document

@MarshallOfSound MarshallOfSound added semver/minor backwards-compatible functionality no-backport labels Mar 8, 2023
@MarshallOfSound MarshallOfSound requested a review from a team as a code owner March 8, 2023 21:14
@electron-cation electron-cation bot added new-pr 🌱 PR opened in the last 24 hours api-review/requested 🗳 labels Mar 8, 2023
@MarshallOfSound MarshallOfSound mentioned this pull request Mar 8, 2023
3 tasks
Copy link
Member

@clavin clavin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty small changes. 😄 This PR is impressive in how much ESM functionality it opens up for only doing a few tiny patches.

  • Not a big fan with some bits of how default_app/main.ts is written, but those exist prior to this PR so I'll leave that for the future.
  • I do want to see a test on this PR, even if it's just a smoke test.

P.S. I agree w/ your theory that these could probably impact startup time of an ESM app minorly, possibly even negligibly, mostly stemming from awaits and microtasks and stuff like that.

default_app/preload.ts Show resolved Hide resolved
docs/tutorial/esm-limitations.md Outdated Show resolved Hide resolved
lib/renderer/init.ts Outdated Show resolved Hide resolved
shell/common/node_bindings.h Show resolved Hide resolved
MarshallOfSound and others added 5 commits March 9, 2023 01:25
Blink has it's own event loop so pumping the uv loop in the renderer is not enough, luckily in blink we can suspend the loading of the frame while we do additional work.
default_app/main.ts Show resolved Hide resolved
default_app/main.ts Outdated Show resolved Hide resolved
default_app/main.ts Outdated Show resolved Hide resolved
default_app/main.ts Show resolved Hide resolved
docs/tutorial/esm-limitations.md Outdated Show resolved Hide resolved
shell/common/node_bindings.cc Show resolved Hide resolved
shell/common/node_bindings.cc Show resolved Hide resolved
shell/common/node_bindings.cc Outdated Show resolved Hide resolved
shell/common/node_bindings.cc Show resolved Hide resolved
MarshallOfSound and others added 3 commits March 9, 2023 11:46
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
shell/common/node_bindings.h Outdated Show resolved Hide resolved
@MarshallOfSound MarshallOfSound merged commit ac031bf into main Aug 31, 2023
17 checks passed
@MarshallOfSound MarshallOfSound deleted the engineering-science-magic branch August 31, 2023 00:38
@release-clerk
Copy link

release-clerk bot commented Aug 31, 2023

Release Notes Persisted

Added ESM support. For more details, see the ESM limitations document

@mahnunchik
Copy link
Contributor

When is the release planned?

@martpie
Copy link

martpie commented Sep 4, 2023

Electron 28, which is in nightly right now. Cf. #21457

Offroaders123 added a commit to Offroaders123/Electron-Text-Editor that referenced this pull request Sep 24, 2023
Wow, can't believe this day has finally come! You can essentially write most of your Electron code in pure ESM now! The only holdup is that preload scripts must be CommonJS still. But you can just add the `.cjs/.cts` extension for that one module, so that works out really well.

This was what made me come back to work on this project a little bit again. Rather than starting fresh with a new Electron project, I thought it would be a better idea to update this one to use my more recent tooling (TS, ESM in this case), and I want to try some Electron-specific things out too, like Accelerators, things like that. Ooh, I want to get Vite/live reload working with this too, I didn't end up getting that set up when I started this, Node projects were still above my head at that time.

electron/electron#21457
electron/electron#37535
https://github.com/electron/electron/blob/main/docs/tutorial/esm.md

This was a placeholder I set up for the reference to resolve the preload script, since `__dirname` isn't an available global from within ESM.
https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/

Sevendust Next is definitely one of my favorite albums of theirs for me, looking back on it more recently the last year or so.
MrHuangJser pushed a commit to MrHuangJser/electron that referenced this pull request Dec 11, 2023
* fix: allow ESM loads from within ASAR files

* fix: ensure that ESM entry points finish loading before app ready

* fix: allow loading ESM entrypoints via default_app

* fix: allow ESM loading for renderer preloads

* docs: document current known limitations of esm

* chore: add patches to support blending esm handlers

* refactor: use SetDefersLoading instead of JoinAppCode in renderers

Blink has it's own event loop so pumping the uv loop in the renderer is not enough, luckily in blink we can suspend the loading of the frame while we do additional work.

* chore: add patch to expose SetDefersLoading

* fix: use fileURLToPath instead of pathname

* chore: update per PR feedback

* fix: fs.exists/existsSync should never throw

* fix: convert path to file url before importing

* fix: oops

* fix: oops

* Update docs/tutorial/esm-limitations.md

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* windows...

* windows...

* chore: update patches

* spec: fix tests and document empty body edge case

* Apply suggestions from code review

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* spec: add tests for esm

* spec: windows

* chore: update per PR feedback

* chore: update patches

* Update shell/common/node_bindings.h

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* chore: update patches

* rebase

* use cjs loader by default for preload scripts

* chore: fix lint

* chore: update patches

* chore: update patches

* chore: fix patches

* build: debug depshash

* ?

* Revert "build: debug depshash"

This reverts commit 0de8252.

* chore: allow electron as builtin protocol in esm loader

* Revert "Revert "build: debug depshash""

This reverts commit ff86b12.

* chore: fix esm doc

* chore: update node patches

---------

Co-authored-by: Jeremy Rose <jeremya@chromium.org>
Co-authored-by: electron-patch-conflict-fixer[bot] <83340002+electron-patch-conflict-fixer[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>
@yejimeiming
Copy link

yejimeiming commented Jan 2, 2024

image image

Hey! 👋 thanks this PR!
Details link is not found!

@AlexWayfer
Copy link

image image
Hey! 👋 thanks this PR! Details link is not found!

I think, it's not this file: https://github.com/electron/electron/blob/main/docs/tutorial/esm.md

It's always better to attach links with ref to the latest commit, not an alive branch: https://github.com/electron/electron/blob/2085aae/docs/tutorial/esm.md

Anyway, it's easier to read on the official site: https://www.electronjs.org/docs/latest/tutorial/esm

(I see /latest in the URL, but don't see any switch on the site)

undergroundwires added a commit to undergroundwires/privacy.sexy that referenced this pull request Mar 18, 2024
This commit bumps Electron and related dependencies to their latest
versions to leverage native ESM support. It adjusts build configuration
to use native ESM support instead of relying on CommonJS bundling.

Key changes:

- Bump Electron to latest v29.
  Electron v28 ships with native ESM/ECMAScript modules support.
  Details on Electron ESM support:
    - electron/electron#21457
    - electron/electron#37535
- Bump `electron-builder` to latest v24.13.
  `electron-builder` is used to package and publish the application.
  It supports ESM since 24.10.
  Details on `electron-builder` ESM support:
    - electron-userland/electron-builder#7936
    - electron-userland/electron-builder#7935
- Bump `electron-log` to latest v5.1.
  `electron-log` supports ESM since version 5.0.4.
  Details on `electron-log` ESM support:
    - megahertz/electron-log#390.
- Change `electron-vite` configuration to bundle as ESM instead of
  CommonJS to leverage Electron's native ESM support.

Other supporting changes:

- Add type hint for electron-builder configuration file.
- Update import statements for `electron-updater` as it still is a
  CommonJS module and does not support ESM.
  Details:
    - electron-userland/electron-builder#7976
- Improve `electron-builder` configuration file to dynamically locate
  main entry files, supporting various JavaScript file extensions
  (`.js`, `.mjs` and `.cjs`) to facilitate easier future changes.
- Change comment about Electron process-specific module alias
  registration. This issue has been fixed in `electron-vite`, but
  subpath module imports for Electron still do not work when building
  tests (`npm run test:unit`).
  Details:
   - alex8088/electron-vite#372
- Add `electron-log` in bundling process instead of externalizing to
  workaround Electron ESM loader issues with subpath imports (inability
  to do `electron-log/main`).
  Details:
    - alex8088/electron-vite#401
    - electron/electron#41241
- Improve desktop runtime error checks' assertion message for better
  clarity.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet