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

Implement WICG's import map #2919

Open
mstoykov opened this issue Feb 20, 2023 · 3 comments
Open

Implement WICG's import map #2919

mstoykov opened this issue Feb 20, 2023 · 3 comments
Labels
evaluation needed proposal needs to be validated or tested before fully implementing it in k6 feature js-compat ux

Comments

@mstoykov
Copy link
Contributor

Feature Description

Implement WICG's import map.

This will allow users to define how import specifiers are interpreted

Use cases:

Versioning libraries

Currently if someone is using https://jslib.k6.io/aws/0.7.0/aws.js in a script and wants to update to v0.7.1 (for example) and they do that in 5 different modules they need to go and change all of those.

With an import map they could've defined the jslib/aws and then used that in the 5 places and then update only the import map.

Having / mean relative to the main script

This has been requested in the past, but users do have utility modules and they are usually in some file structure such as

/path/to/project/main-script.js
/path/to/project/utils/my-cool-lib.js
/path/to/project/scenarios/featureA/script.js
/path/to/project/scenarios/featureA/utils/cool-fetaureA-script.js

In all the different files the users might want to import /path/to/project/utils/my-cool-lib.js but it's relative file path will change in all 3 other scripts make it a bit hard. And the usage of absolute paths will mean this will not be portible between machines (or at least harder to port).

But it is possible to redefined / as the root of /path/to/project or more accurately to be relative to main-script.js

Note this is not referenced in the specification but is illustrated in the deno documention. So it might turn out to be something deno did 🤷

Making it easier to mock or migrate between modules/imports

If somebody has a library that happens to import I don't know nodes' axios (for example) and use it to implement some kind of API. It will be nice if the user can levarage all of that code and just "polyfill"/"mock" what import axios from 'axios' does.

This might also be useful if users want to switch between using experimental modules or external ones as in
k6/x/browser and k6/experimental/browser. This might be particularly helpful if in the future we have a long living external module that becomes experimental but newer features first land in the external one before getting pushed in the core k6.

Mocking for unit tests is already a thing that is being inqueried.

Caveats:

Configuration

By far the biggest question is "how" does someone configure this.

In script

Having this in the script will not be feasable as it changes how modules are resolved which happens before execution of the module happens.

It might be possible to have it as a comment that k6 reads, but that seems a bit strange.

Configuration file

Having it in the "main" configuration file is the cleanest solution but means that it will need a cli argument if you want different ones for different tests.

Same if it is just another cli flag that needs to be provided

Any kind of automatic detecting og imports.map (name is just for illustration) next to the script borders on

package.json alikes

K6 has historically went out of it's way to not need some kind of per test run config file.

And this has worked out for us and I am not certain it is worth adding it just for that or if there are other needs.

What others do:

Browsers are easy they have <script type="importmap"> and after that it is set 🎉.

In theory wecan have very special import "path/to/import.map" that k6 somehow detects meas that it is importing an import map and change how it resolves module from then onwards.

Nodejs has no support atm.

Deno has cli flag and a configuration file.

Complexity/Readability for users

There is definitely something possitive to be said about both having full urls which you always know will resolve to the same thing and have shorter ones that you can change between execution instead of having to rewrite the code.

I would argue given the usecases above there is likely enough more benefits for the complexity of users needing to justify it.

Documentation and a lot of examples are going to be very helpful here in explaining to users.

But I would expect that we would also log (debug level) what each specifier got resolved to and how/why.

Complexity for k6 maintainers

On the service this is pretty whatever:
The majority of the complexity will be in parsing the map and layign down what it the confugration means.

Whether path/to/somewhere/something goes directly to a loader package function or goes through some importmap struct that then calls loader is negligible in complexity.

And after #2881 it will be concentrated in the moduleResolver.

Future/current ESM work also does not really care about this, the specificaiton is agnostic to what any import specifier means so we can have it mean whatever we want.

This still likely should wait for ESM or at least given the configuration problems will likely just not happen before ESM support is in a more advance state 🤞 .

@mstoykov mstoykov added ux feature js-compat evaluation needed proposal needs to be validated or tested before fully implementing it in k6 labels Feb 20, 2023
@na--
Copy link
Member

na-- commented Feb 20, 2023

🤔 One of the unresolved issues when it comes to test suites (#1342), even after the PoC in #2816, is how to define more complex test suites than just linear k6 run script1.js script2.js script3.js.

We'd need some way for users to define relationships like "testC.js should to be executed only after both testA.js and testB.js finish successfully". My implicit assumption was that this could probably be done by some other JS exported property (e.g. tests) that k6 checks after the first init context execution. That is, the main script can look somewhat like this:

export test = {
  'testA': {
    'exec': 'path/to/scriptA.js',
    // ...
  },
  'testB': {
    'exec': 'path/to/scriptB.js',
    // ...
  },
  'testC': {
    'exec': 'path/to/scriptC.js',
    'startAfter': ['testA', 'testB'],
    // ...
  },
};

This is only for illustrative purposes, the actual format will probably be quite different... However, whatever way we choose to define the test suites, it will likely be a fairly natural place to specify these import maps as well? WDYT?

@mstoykov
Copy link
Contributor Author

I guess if we end up having a super/meta test file that is the argument to k6 run superfile that does not actually import the final scripts but just paths to the actual scripts that are what you currently can give to k6 run, then I guess yeah. It might be a bit ... not particularly intuitive or nice for cases where there won't be "test suites" but a single test though.

But (with risk on going down a rabbit hole of discussing that particular) - my main caveat here will be that users will be confused why we have 1 js file that does not import others but names them and then it calls the others. And why is it a javascript file in that case?

I would argue that this file should not be a js file but a simple static (json) configuration one.

@na--
Copy link
Member

na-- commented Feb 20, 2023

that does not actually import the final scripts but just paths to the actual scripts

This is currently my assumption, since it will allow way more flexibility. Besides these import maps, the "superfile" can also define custom env variables per script (which will affect their init contexts) and even things like grafana/k6-cloud-feature-requests#19. Requiring every k6 instance to parse all of the test files in a test suite immediately on k6 start will require more resources and add way more restrictions to what we can do with test suites.

I would argue that this file should not be a js file but a simple static (json) configuration one.

👍 good point, and that might be one option, but having it a JS file allows users to add logic, parametrize things, etc.

This whole is quite far off and needs a lot of further evaluation and discussions, I just decided to mention it as one possible option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
evaluation needed proposal needs to be validated or tested before fully implementing it in k6 feature js-compat ux
Projects
None yet
Development

No branches or pull requests

2 participants