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

Can we drop builtin AMD support? #1729

Closed
NullVoxPopuli opened this issue Oct 14, 2023 · 6 comments
Closed

Can we drop builtin AMD support? #1729

NullVoxPopuli opened this issue Oct 14, 2023 · 6 comments
Assignees
Labels
Category: Release Type: Meta Seek input from maintainers and contributors.
Milestone

Comments

@NullVoxPopuli
Copy link
Contributor

NullVoxPopuli commented Oct 14, 2023

Tip

You can continue to load source and test files with AMD in QUnit 3.0.
Refer to: https://qunitjs.com/api/config/autostart/#loading-with-requirejs


AMD is an implementation detail of a bundler, and it feels goofy to have built in.

all tools these days know how to work with The Platform, so I think this could be a good opportunity to have less to maintain.

@Krinkle
Copy link
Member

Krinkle commented Oct 25, 2023

I don't think of QUnit as a library one is meant to bundle. Most test runners afaik share that sentiment, in that test runner generally act on your behalf to run your tests, and your tests import your application code (possibly built/compiled), and the test framework is either imported by your test files (which would not be compiled or built) or ahead of time by the test runner itself.

In the case of AMD, there's usually a top-level file for the app and for the test, where test.html file would first load QUnit and their AMD loader, and then load their tests/application code from there.

I worry that requiring them to have a separate build just for QUnit would lower dev experience, and potentially decrease confidence in the test result as it means they would no longer integrate with their main build (or have a separate build that contains only QUnit, hence why we added upstream support at some point).

The projects I'm aware of that use QUnit and AMD, would, I suspect not benefit from this change. Do you agree?

I am open to dropping native support, but perhaps not for the same reasons as you.

For example, if it becomes a burden to support we could instead recommend that projects build their own qunit.amd.js file. It seems likely that such project might actually not be building any other AMD files yet. For example https://github.com/kiwix/kiwix-js/tree/3.9.0/, used AMD to directly load all test and production source files. (No bundling, it's an offline web app.) They'd have to build a variant of QUnit just to load their tests? Or do you propose we merely remove this from the src but still create an AMD variant during our own release process?

It looks like for ESM we'll need a separate distribution indeed since it's hard to import CJS directly in ESM, and transform services seem to currenlty misunderstand our exports (per #1724), so providing our own one would make that work directly, possibly even without needig to enumerate each export by name (we have quite a few).

For AMD, it seems like it'd be trivial to continue support in the non-ESM ("CJS") distribution with these three lines of code as-is.

@Krinkle Krinkle added Category: Release Type: Meta Seek input from maintainers and contributors. labels Oct 25, 2023
@NullVoxPopuli
Copy link
Contributor Author

I worry that requiring them to have a separate build just for QUnit would lower dev experience

Given that this works: https://jsbin.com/fipayiy/edit?html,output,
I don't think we need to support any target format other than ESM.

if it becomes a burden to support we could instead recommend that projects build their own

If folks are still using AMD without a tool to build AMD for them, then I think a wrapper script / build would be fine.
The main thing I want to get away from is the single file supporting every format in existence.

Or do you propose we merely remove this from the src but still create an AMD variant during our own release process?

yeah, I am ok with this.
I'm a big fan of:

  1. author only in one format
  2. build to all supported formats
  3. test all supported formats in an isolated way via monorepo (which gives us the most realistic way to reference our built project)

it's hard to import CJS directly in ESM,
and transform services

this happens in tool-less situations (local browser) as well. transform services are irrelevant.

For AMD, it seems like it'd be trivial to continue support in the non-ESM ("CJS") distribution with these three lines of code as-is.

yeah, and if we need to bundle an IIFE format, AMD is IIFE + the 3 lines easy peasy.

@NullVoxPopuli
Copy link
Contributor Author

NullVoxPopuli commented Oct 25, 2023

so, I think the main thing I'd like to do organizationally is move the repo to a monorepo so we can have a setup like:

./<qunit> (existing files)
./test-packages/
  ./browser/
    ./amd/
    ./esm/
    ./script-import-map/
    ./bundled-esm/
    ...
  ./node
    ./esm/
    ./cjs/
    ...

as far as I know, only pnpm supports this type of monorepo where the top level is also a publishable package. thoughts?

Krinkle pushed a commit that referenced this issue Oct 27, 2023
* Remove AMD export.
* Remove eslint globals entry.

Closes #1729.
@NullVoxPopuli
Copy link
Contributor Author

@Krinkle is there a discord or some other chat platform where we'd be able to talk more synchronously about planning the future of the repo?

@Krinkle
Copy link
Member

Krinkle commented Oct 27, 2023

@NullVoxPopuli Yes, we have a Matrix room at https://app.gitter.im/#/room/#qunitjs_qunit:gitter.im (webchat), or via other clients: https://matrix.to/#/#qunitjs_qunit:gitter.im

@Krinkle
Copy link
Member

Krinkle commented Jun 18, 2024

I've done a bit more research as part of #1551 (ESM support) which is somewhat orthogonal to this. Apologies if you know this already, I'm mainly sharing here for future reference and for transparancy. (Not specifically to NullVoxPopuli).

Findings

  • Our AMD export sets QUnit.config.autostart = false as side-effect.
  • Our AMD export sometimes prevents globalThis.QUnit from being set.

Action

  • Remove AMD export. No longer needed by AMD users.
  • Ensure globalThis.QUnit is always set consistency.
  • Remove QUnit.config.autostart = false setting. No longer needed by AMD users.

Background: AMD export

The feature we document and support is disabling autostart to load test files asynchronously. It doesn't matter to QUnit how you load your test files. It used to be that the most common reason someone would have to disable autostart, was to use AMD/RequireJS. Nowadays, a more likely reason is ESM async import(). Either way requires the same feature, and I've updated the docs to lead with an ESM import() example at https://qunitjs.com/api/config/autostart/.

Loading QUnit itself has not been recommended, documented, or tested for quite some time.

Our own autostart docs, and upstream RequireJS recommend to first loaded qunit.js normally, and then used AMD for individual test files.

As such, we simply don't need it. This doesn't affect the long tail of projects (such as Kiwix, mentioned above) that use RequireJS to load their code and/or their tests.

Background: Automatic config.autostart side-effect

I'd like to make it safe in QUnit 3.0 to load qunit.js multiple times. Today we consider this an error and throw an error. To adopt ESM we will likely have to provide a separate build. For projects that reference QUnit globally, with one part of the test stack responsible for actually loading it, this will work fine. They can switch or not switch depending on their needs and requirements, it's fine either way.

For projects that reference QUnit by importing it in individual plugins, integration layers, and/or test files, there's a good chance that there will be mixed use in practice. If we don't do anything to prevent it, this will cause various split-brain problems where config/plugins are missing, or tests are divided, event handlers firing multiple times, etc. This also came up in discussions for jQuery at jquery/jquery#5429 where similar concerns were raised. For QUnit, we're a bit more flexible in some ways and less flexible in others.

I'm thinking of making QUnit safe to load multiple times. We're not concerned about clashing versions of QUnit. These are going to be the same version. Whichever loads first will own the state, and subsequent imports (e.g. CJS first then ESM, or vice versa) will effectively resume that instead of exporting a different local copy.

In refactoring the code, I stubmled upon this:

qunit/src/export.js

Lines 36 to 40 in 1fc4865

if (typeof define === 'function' && define.amd) {
define(function () {
return QUnit;
});
QUnit.config.autostart = false;

We could grandfather this in, by replacing it with a change to src/config.js where we can set the autostart default to set based on if define.amd exists. But..., do we actually need this to support AMD?

From what I can tell..., no, we don't! Our own autostart docs, and upstream RequireJS docs already set this explicitly. Anecdotally, Kiwix does as well (example). I suggest we simply remove this in QUnit 3.0.

Krinkle added a commit to gruntjs/grunt-contrib-qunit that referenced this issue Jun 19, 2024
The current check in bridge.js is problematic because if a project
includes RequireJS anywhere, for any purpose, the bridge crashes
unless RequireJS is also in charge of loading QUnit.

QUnit 3.0 will remove support for its built-in AMD export
(ref qunitjs/qunit#1729).

It remains supported to use AMD/RequireJS in your HTML file, and to
use it to load source code and/or test files. However, it is no
longer supported to delay the loading of qunit.js itself via AMD.

In order to make that use possible in QUnit 3.0, the bridge.js must
stop assuming that presence of define.amd implies using it to load
QUnit itself.

Example at https://qunitjs.com/api/config/autostart/#loading-with-requirejs
Krinkle added a commit that referenced this issue Jun 19, 2024
* Remove AMD integration from coverage-bridge.js.

  Previously this was mandatory for /test/amd.html to pass, and
  indeed any for project in which RequireJS was present on the
  page somewhere. Because, grunt-contrib-qunit checks for RequireJS
  presence, and if found, insisted on delaying its bridge logic
  until an AMD module by the name of `qunit` was defined.

  I've removed this in grunt-contrib-qunit 10 with
  gruntjs/grunt-contrib-qunit@aa4a9db179.

  This means we now mandate the opposite. There is no feasible way
  for this to have an intermediary phase. Hence a breaking change.

* Update AMD example to match the docs at
  https://qunitjs.com/api/config/autostart/#loading-with-requirejs

  This was not possible before due to the above grunt-contrib-qunit
  behaviour mandating the opposite.

Ref #1729.
@Krinkle Krinkle added this to the 3.0 release milestone Jun 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Release Type: Meta Seek input from maintainers and contributors.
Development

No branches or pull requests

2 participants