wxt-dev / wxt-dev/wxt

Content Script ESM Support

Open
#357 39 comments 35 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
10.5k
Forks
564
PR merge metrics
No merged PRs in 30d

Description

Feature Request

As discussed in #335, it is possible to load ESM content scripts using a dynamic import. The downside is that since it's async, the standard run_at option has basically no effect.

I propose adding a new option to defineContentScript: type: "module". Similar to the background's type: "module" option.

When WXT sees an async content script, it will load the script asynchronously using a dynamic import.

await import(
  /* @vite-ignore */
  browser.runtime.getURL("path/to/chunk/entrypoint.js")
);

Questions:

  • Does the run_at in the manifest make a difference in loading speed when using a dynamic import

    Jan 20, 2024: Slightly, we should respect it, and allow configuring it, with the knowledge that document_start doesn't work. See https://github.com/wxt-dev/wxt/issues/357#issuecomment-1901769303

  • Can async content scripts be bundled in one step alongside HTML entrypoints, or do they have to be separated into their own step? My concern here is mixing chunks with side-effects that only work in HTML pages

    Jan 20, 2024: I don't think this is an issue, it's only an issue for the background service worker where there's no window global

  • How will dev mode function and reload content scripts. What about main world content scripts, should those be grouped with the regular HTML file builds, or be in their own build step?

    Feb 2, 2024: Have not tested dev mode yet, but I am building the ESM background script with the other extension pages, so I'll do the same with isolated world content scripts. Main world content scripts will be combined with the sandbox pages since those don't have access to the browser APIs, like sandbox pages.

  • Should type: "module" be the default value? It works well with the default run_at: "document_idle", and will likely provide a much better dev experience.

    Jan 21, 2024: If dev mode works well, yes, it will be the default.

    Feb 2, 2024: Initially, I'm going to make this an opt-in just like the background's type: "module". If it's working well for people, I'll try and make the the default before v1.0.

Is your feature request related to a bug?

#335

What are the alternatives?

No real alternatives to the feature as a whole. Instead of adding a new field, we could use runAt: "async", but that wouldn't provide a way to set the actual run_at in the manifest. That said, the run_at doesn't really matter, it can cause the browser to import the script earlier, but the code will never run before the DOMContentLoaded event.

Additional context

CC @yunsii

This will fix: https://github.com/wxt-dev/wxt/issues/270

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at defineContentScript and trace the existing background type: "module" implementation. Investigate dev-mode reload behavior and how isolated-world and main-world content scripts are grouped, as these remain unresolved in the issue. Done means opt-in module content scripts load through dynamic import while preserving configurable manifest run_at behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
build-system, web-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.