From 7fe9b072a9983296568c895bb426e95235978908 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Fri, 26 Jan 2024 02:20:52 +0100 Subject: [PATCH 01/21] Update Modules and JavaScript Mode docs --- .../build-k6-binary-using-docker.md | 6 + .../using-k6/javascript-compatibility-mode.md | 142 +++---- docs/sources/next/using-k6/modules.md | 368 ++++++------------ .../next/using-k6/test-authoring/_index.md | 2 +- .../build-k6-binary-using-docker.md | 6 + .../using-k6/javascript-compatibility-mode.md | 142 +++---- docs/sources/v0.47.x/using-k6/modules.md | 368 ++++++------------ .../v0.47.x/using-k6/test-authoring/_index.md | 2 +- .../build-k6-binary-using-docker.md | 6 + .../using-k6/javascript-compatibility-mode.md | 142 +++---- docs/sources/v0.48.x/using-k6/modules.md | 368 ++++++------------ .../v0.48.x/using-k6/test-authoring/_index.md | 2 +- 12 files changed, 540 insertions(+), 1014 deletions(-) diff --git a/docs/sources/next/extensions/build-k6-binary-using-docker.md b/docs/sources/next/extensions/build-k6-binary-using-docker.md index a6bb55ec7d..e3d6aefeac 100644 --- a/docs/sources/next/extensions/build-k6-binary-using-docker.md +++ b/docs/sources/next/extensions/build-k6-binary-using-docker.md @@ -8,6 +8,12 @@ weight: 03 Using the [xk6 Docker image](https://hub.docker.com/r/grafana/xk6/) can simplify the process of creating a custom k6 binary. It avoids having to setup a local Go environment, and install xk6 manually. +{{% admonition type="note" %}} + +This tutorial is about creating a custom k6 binary (using Docker). If you want to create a Docker image with a custom k6 binary, refer instead to [Using modules with Docker](https://grafana.com/docs/k6//using-k6/modules/#using-modules-with-docker). + +{{% /admonition %}} + ## Building your first extension For example, to build a custom k6 binary with the latest versions of k6 and the [`xk6-kafka`](https://github.com/mostafa/xk6-kafka) and [`xk6-output-influxdb`](https://github.com/grafana/xk6-output-influxdb) extensions, run one of the commands below, depending on your operating system: diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 792fc58049..907769a911 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -6,39 +6,71 @@ _build: weight: 19 --- -# JavaScript Compatibility Mode +# JavaScript compatibility mode -You can run test scripts with different ECMAScript compatibility modes with the -`run --compatibility-mode` CLI option or `K6_COMPATIBILITY_MODE` environment variable. +You can write k6 scripts in various ECMAScript versions: -Currently two modes are available: +- ES6+ JavaScript with ES modules (ESM). +- Plain old JavaScript (ES5.1+) with CommonJS modules. -## Base +k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. + +Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: + +![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) + +Since large tests can consume significant resources, some users prefer to bundle and **optimize their test code outside k6 for better performance**. For this reason, k6 offers two JavaScript Compatibility modes: + +- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. + +When running tests, you can change the mode through the `--compatibility-mode` option: + +| Env | CLI | Code / Config file | Default | +| ----------------------- | ---------------------- | ------------------ | ------------ | +| `K6_COMPATIBILITY_MODE` | `--compatibility-mode` | N/A | `"extended"` | + +## Extended mode + +By default, k6 uses the `--compatibility-mode=extended` mode: + +{{< code >}} + +```default +$ k6 run script.js +``` + +{{< /code >}} + +As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. + +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. Also, it may increase startup time (refer to [Performance comparison](#performance-comparison)) and produces code with slightly different line/column numbers. + +## Base mode {{< code >}} -```bash +```cli $ k6 run --compatibility-mode=base script.js ``` -```bash +```env $ K6_COMPATIBILITY_MODE=base k6 run script.js ``` {{< /code >}} -Pure Golang JavaScript VM supporting ES5.1+. Use this mode if your scripts are already written -using only ES5.1 features, or were previously transformed by [Babel](https://babeljs.io/), -to reduce startup time, RAM usage and improve performance. See the [k6-es6 project](https://github.com/k6io/k6-es6) -for an example [Webpack](https://webpack.js.org/) setup that does this -transformation outside of k6. +This mode omits the Babel transformation step, supporting only ES5.1+ code. -> ### ⚠️ Disclaimer -> -> Your mileage may vary while running `--compatibility-mode=base` and also importing external dependencies. For instance, -> `xml2js` and `cheerio` currently do not work, while `lodash` does. +Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. This mode can lead to reduce startup time, RAM usage, and overall improved performance. + +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): + +- [k6-template-es6](https://github.com/grafana/k6-template-es6) +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript) +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example) -### Basic Example +### CommonJS Example {{< code >}} @@ -69,72 +101,13 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -### Advanced Example - -{{< code >}} - -```javascript -const http = require('k6/http'); -const metrics = require('k6/metrics'); -const k6 = require('k6'); - -module.exports.options = { - stages: [ - { duration: '30s', target: 20 }, - { duration: '1m30s', target: 10 }, - { duration: '20s', target: 0 }, - ], - thresholds: { - 'failed requests': ['rate<0.1'], - }, -}; - -const myFailRate = new metrics.Rate('failed requests'); - -module.exports.default = function () { - const res = http.get('https://httpbin.test.k6.io/'); - const checkRes = k6.check(res, { - 'status was 200': function (r) { - return r.status == 200; - }, - }); - if (!checkRes) { - myFailRate.add(1); - } - k6.sleep(1); -}; -``` - -{{< /code >}} - -## Extended - -{{< code >}} - -```bash -$ k6 run --compatibility-mode=extended script.js -``` - -```bash -$ K6_COMPATIBILITY_MODE=extended k6 run script.js -``` - -{{< /code >}} - -In case of syntax/parsing errors, the script will be transformed using Babel with specific plugins bringing the compatibility to ES2015(ES6)+. This means that features such as classes and arrow functions can be used. This does take some time to transpile and the produced code has slightly different line/column numbers. - -Before v0.31.0, k6 included [core.js](https://github.com/zloirock/core-js) v2 and even more Babel plugins in extended mode. -This added around 2MB extra memory usage per VU and some of the transformations (generators, async/await) of Babel were still insufficient to get k6 working with these features. - ## Performance Comparison -There's a substantial difference in performance between both modes, as shown by -[GNU time](https://www.gnu.org/software/time/) below, especially when running tests with a large -number of VUs: +There might be a notable performance difference between both compatibility modes, particularly influenced by the script code and the number of VUs. The following [GNU time](https://www.gnu.org/software/time/) metrics provide insights about their differences: {{< code >}} -```bash +```base $ /usr/bin/time -v k6 run \ --compatibility-mode=base \ --vus 3500 \ @@ -166,7 +139,7 @@ Page size (bytes): 4096 Exit status: 0 ``` -```bash +```extended $ /usr/bin/time -v k6 run \ --compatibility-mode=extended \ --vus 3500 \ @@ -199,3 +172,14 @@ Exit status: 0 ``` {{< /code >}} + +  + +## Read more + +- [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. +- [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. +- [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. +- [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index 8f13aaf8fc..49db2ff989 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -10,11 +10,12 @@ weight: 07 ## Importing modules It's common to import modules, or parts of modules, to use in your test scripts. -In k6, you can import three different kinds of modules: +In k6, you can import different kinds of modules: - [Built-in modules](#built-in-modules) - [Local filesystem modules](#local-filesystem-modules) - [Remote HTTP(S) modules](#remote-https-modules) +- [Extension modules](#extension-modules) ### Built-in modules @@ -27,19 +28,11 @@ For the full list of built-in modules, refer to the [API documentation](https:// import http from 'k6/http'; ``` -### Local filesystem modules +### Local modules -These modules are stored on the local filesystem, and accessed either through relative -or absolute filesystem paths. To make local filesystem modules compatible -with k6, the module itself may use only relative or absolute filesystem imports to access its -dependencies. +These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -```javascript -//helpers.js -export function someHelper() { - // ... -} -``` +k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -50,13 +43,22 @@ export default function () { } ``` -### Remote HTTP(S) modules +```javascript +//helpers.js +export function someHelper() { + // ... +} +``` + +### Remote modules -These modules are accessed over HTTP(S), from a source like [the k6 JSLib](#the-jslib-repository) or +These modules are accessed over HTTP(S), from a public source like GitHub, any CDN, or from any publicly accessible web server. The imported modules are downloaded and executed at runtime, making it extremely important to **make sure you trust the code before including it in a test script**. +For example, [jslib](https://grafana.com/docs/k6//javascript-api/jslib) is a set of k6 JavaScript libraries available as remote HTTPS modules. They can be downloaded and imported as local modules or directly imported as remote modules. + ```javascript import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; @@ -65,282 +67,101 @@ export default function () { } ``` -### The JSLib repository - -**JSLib** is a set of libraries known to work well with k6. It is available at https://jslib.k6.io/. - -These libraries can either be downloaded and included with the test project or loaded directly using HTTP imports. - -## Bundling node modules - -{{% admonition type="caution" %}} - -k6 is not NodeJS, nor is it a browser. Packages that rely on APIs provided by NodeJS, for -instance the `os` and `fs` modules, will not work in k6. The same goes for browser-specific -APIs like the `window` object. - -{{% /admonition %}} - -The steps of this tutorial are as follows: - -1. [Setting up the bundler](#setting-up-the-bundler) - 1. [Installing packages](#installing-packages) - 1. [Configuring Webpack](#configuring-webpack) - 1. [Adding a bundle command](#adding-a-bundle-command) -2. [Running the bundling](#running-the-bundling) -3. [Running the tests](#running-the-tests) - -{{% admonition type="note" %}} - -A [ready-to-use Webpack and Babel starter](https://github.com/k6io/k6-es6) is avaialble in a repository. - -{{% /admonition %}} - -In a JavaScript project running NodeJS, modules are imported using either `import` or `require()`, -using the node module resolution algorithm. -This means that the developer can import modules by name, without providing the full filesystem path to the module. For instance: - -```javascript -import { ClassInAModule } from 'cool-module'; -``` - -would be automatically resolved by the node resolution algorithm by searching: - -- The current directory -- Any `node_modules` folder in the directory -- Any `node_modules` folder in a parent directory, up to the closest `package.json` file. - -As the implementation of `import` in k6 lacks support for the node module resolution algorithm, -node modules that resolve external dependencies will first need to be transformed into a self-contained, -isolated, bundle. - -This is done with the help of a bundling tool, like Webpack, which analyses the test script, -identifies all external dependencies, and then continues to create a self-contained bundle including -everything necessary to run the script. - -If the test script has no external dependencies, already has them vendored in a k6 compatible way, -or only uses ES5.1+ features, using a bundler will not be necessary. - -**Picking a bundler** - -It is possible to use any bundler that supports transpilation. Popular ones include, but are not -limited to, [webpack](https://github.com/webpack/webpack), -[parcel](https://github.com/parcel-bundler/parcel), [rollup](https://github.com/rollup/rollup) -and [browserify](https://github.com/browserify/browserify). - -Due to its flexibility, ease of use, relatively low resource consumption, and known compatibility -with k6, it is recommended to use [webpack](https://github.com/webpack/webpack) unless you have a -specific reason to choose something else. - -**Things to consider** - -In general, all external modules added to a test project have a negative impact on performance, as they further increase the memory footprint and CPU usage. - -Usually, this is not a big problem as each application only allocates these resources once. In k6, however, every VU has a separate JavaScript virtual machine (VM), duplicating the resource usage once each. - -By running code requiring additional features on top of ES5.1, we also need additional extensions to the JavaScript VM, further boosting the resource usage. This is the default mode of k6. - -When bundling using the configuration described in this article, babel and corejs automatically adds the features needed, thus allowing us to run our script without these extensions, using `--compatibility-mode=base`. For more details on the performance benefits of running in the base compatibility mode, see [this article](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode#performance-comparison). - -### Setting up the bundler - -Setting up a Babel and Webpack project from scratch might sound like a big undertaking, but -is usually accomplished within minutes. Start by creating a project folder and initializing -npm: - -{{< code >}} - -```bash -$ mkdir ./example-project && \ - cd "$_" && \ - npm init -y -``` - -{{< /code >}} - -#### Installing packages - -Then, install the packages needed: - -{{< code >}} - -```bash -$ npm install --save-dev \ - webpack \ - webpack-cli \ - @types/k6 \ - babel-loader \ - @babel/core \ - @babel/preset-env \ - core-js -``` - -{{< /code >}} +You can also build your custom Javascript libraries and distribute them via a public web hosting. For reference, [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws) and [k6-rollup-example](https://github.com/grafana/k6-rollup-example) host their modules as GitHub release assets. -| Package | Usage | -| :---------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [webpack](https://github.com/webpack/webpack) | The bundler part of Webpack | -| [webpack-cli](https://github.com/webpack/webpack-cli) | The CLI part of Webpack, which allows us to use it from the terminal | -| [@types/k6](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/k6) | k6 Typescript definition | -| [babel-loader](https://github.com/babel/babel-loader) | A loader used by Webpack to leverage babel functionality while bundling | -| [@babel/core](https://github.com/babel/babel/tree/master/packages/babel-core) | The core functionality of Babel | -| [@babel/preset-env](https://github.com/babel/babel/tree/master/packages/babel-preset-env) | A smart preset using [browserlist](https://github.com/browserslist/browserslist), [compat-table](https://github.com/kangax/compat-table) and [electron-to-chromium](https://github.com/Kilian/electron-to-chromium) to determine what code to transpile and polyfill. | -| [core-js](https://github.com/zloirock/core-js) | A modular standard library for JS including polyfills | +### Extension modules -#### Configuring Webpack +Like the [k6 APIs](https://grafana.com/docs/k6//javascript-api), you can build custom modules in Go code and expose them as JavaScript modules. These custom Go-to-JS modules are known as [k6 extensions](https://grafana.com/docs/k6//extensions). -Once these packages have been added, the next step will be to set up a `webpack.config.js` file: - -{{< code >}} +Below is an example that imports the `k6/x/kubernetes` module from the [xk6-kubernetes](https://github.com/grafana/xk6-kubernetes) extension. ```javascript -const path = require('path'); - -module.exports = { - mode: 'production', - entry: { - login: './src/login.test.js', - signup: './src/signup.test.js', +import { Kubernetes } from 'k6/x/kubernetes'; + +const podSpec = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { name: 'busybox', namespace: 'testns' }, + spec: { + containers: [ + { + name: 'busybox', + image: 'busybox', + command: ['sh', '-c', 'sleep 30'], + }, + ], }, - output: { - path: path.resolve(__dirname, 'dist'), // eslint-disable-line - libraryTarget: 'commonjs', - filename: '[name].bundle.js', - }, - module: { - rules: [{ test: /\.js$/, use: 'babel-loader' }], - }, - target: 'web', - externals: /k6(\/.*)?/, }; +export default function () { + const kubernetes = new Kubernetes(); + kubernetes.create(podSpec); + const pods = kubernetes.list('Pod', 'testns'); + pods.map(function (pod) { + console.log(pod.metadata.name); + }); +} ``` -{{< /code >}} - -`Mode` - -Tells Webpack to automatically use the optimizations associated with the `mode`. -Additional details available in [the webpack docs](https://webpack.js.org/configuration/mode/). +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. -`Entry` +To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). -The files Webpack will use as its entry points while performing the bundling. From these points, -Webpack will automatically traverse all imports recursively until every possible dependency path has -been exhausted. For instance: +## Sharing JavaScript modules -{{< code >}} - -```javascript -// login.test.js - -import { SomeService } from './some.service.js'; +As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. -const svc = new SomeService(); -``` - -{{< /code >}} +> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. -and +**As remote modules** -{{< code >}} +You can host your modules in a public webserver like GitHub and any CDN and be imported remotely. ```javascript -// some.service.js - -import * as lodash from 'lodash'; +// As GitHub release assets +import { + WorkloadConfig, + sayHello, +} from 'https://github.com/grafana/k6-rollup-example/releases/download/v0.0.2/index.js'; -export class SomeService { - constructor() { - this._ = lodash; - } -} +// or hosted in a CDN +import { randomIntBetween, randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; ``` -{{< /code >}} - -would result in Webpack bundling `login.test.js`, `some.service.js` and all upstream dependencies -utilized by `lodash`. - -`Output` - -The `path` key takes an absolute path which is where the finished bundle will be placed. In -this example, `path.resolve` is used to concatenate `__dirname` and `'dist'` into an absolute -path. +When the library consists of multiple files and modules, you may want to bundle these modules to create public releases. Here are some examples for reference: -The `libraryTarget` key configures how the library will be exposed. Setting it to `commonjs` -will result in it being exported using `module.exports`. Additional details available in [the -Webpack docs](https://webpack.js.org/configuration/output/#outputlibrarytarget). +- Using Webpack: [k6-jslib-utils](https://github.com/grafana/k6-jslib-utils) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: [test-commons](https://github.com/grafana/k6-rollup-example/). -The `filename` key, as the name suggests, configures the name of the finished bundles. In this -example, the [template string](https://webpack.js.org/configuration/output/#template-strings) `[name]` -is used to add a dynamic part to the output filename. +Be aware that k6 automatically executes remote modules, making it crucial to trust the source code of these remote modules. There is a **risk of altering the remote modules with certain hosting mechanisms**. To mitigate this security risk, some users prefer to download and import the modules locally to ensure full control of the source code. -#### Adding a bundle command +**As local modules** -Open the `package.json` file and add a new script entry, used for running the bundling process. +In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: -```diff -{ - "name": "bundling-example", - "description": "", - "version": "0.1.0", - "private": true, - "scripts": { -+ "bundle": "webpack" - } - ... -} -``` - -### Running the bundling - -Running webpack will now output two different test bundles, that may be executed independently: - -{{< code >}} - -```bash -$ npm run bundle -# ... -$ tree dist - -dist -├── login.bundle.js -└── signup.bundle.js +```javascript +import { WorkloadConfig, sayHello } from './libs/test-commons.js'; -0 directories, 2 files +import { randomIntBetween, randomItem } from './libs/k6-utils.js'; ``` -{{< /code >}} +Another option to distribute libraries is to use a package manager tool like npm, which enables version locking and the linking of local libraries. The latter can be useful during development. -### Running the tests +Although k6 does not resolve node modules, you can utilize a Bundler to load npm dependencies, as shown in the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -{{< code >}} - -```bash -$ npm run bundle -# ... -$ k6 run dist/login.bundle.js -# ... -``` +## Using TypeScript -{{< /code >}} +k6 does not natively support TypeScript. If you wish to write k6 tests in Typescript, you will need a bundler, as demonstrated in the previous examples: -{{< code >}} +- Using Webpack: Refer to [k6-template-typescript](https://github.com/grafana/k6-template-typescript) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: Apply the [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/master/packages/typescript) to the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -```bash -$ npm run bundle -# ... -$ k6 run dist/signup.bundle.js \ - --vus 10 \ - --duration 10s -# ... -``` +## Using modules with Docker -{{< /code >}} +Built-in and remote modules work out of the box when running k6 in a Docker container like the [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6). -## Using local modules with Docker +### Local modules -When running k6 in a Docker container you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/), so that k6 can see all the JS modules it needs to import. +To run k6 with Docker and import a local module, you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/). Thus, k6 can see all the JS modules it needs to import. For example, say you have the following structure on your host machine: @@ -380,11 +201,42 @@ $ docker run --rm -v /home/k6/example/src:/src -i grafana/k6 run /src/index.js {{< /code >}} Note that on Windows, you also need to make sure that your drive in question, say `C:\`, -has been marked for sharing in the Docker settings: +has been marked for sharing in the Docker Desktop settings. + +### Extension modules -![Running k6 in docker on Windows](/media/docs/k6-oss/running-k6-in-docker-on-windows.png) +The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. + +To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. + +```bash +# Stage 1 - download xk6 and desired extensions, then compile a new binary. +FROM golang:1.20-alpine3.18 as builder +WORKDIR $GOPATH/src/go.k6.io/k6 +COPY . . +RUN apk --no-cache add git=~2 +RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ + && CGO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-output-prometheus-remote=. \ + --output /tmp/k6 + +# Stage 2 - Copy our custom k6 for use within a minimal linux image. +FROM alpine:3.18 +RUN apk add --no-cache ca-certificates && \ + adduser -D -u 12345 -g 12345 k6 +COPY --from=builder /tmp/k6 /usr/bin/k6 + +USER 12345 +WORKDIR /home/k6 + +ENTRYPOINT ["k6"] +``` ## Read more -- [ES6 template](https://github.com/k6io/template-es6): a scaffolding project to use ES6 in your k6 scripts. -- [TypeScript template](https://github.com/k6io/template-typescript): a scaffolding project to use TypeScript in your k6 scripts. +- [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. +- [Extensions directory](https://grafana.com/docs/k6//extensions/explore): A collection of k6 extensions maintained by Grafana Labs and the community. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a common library and testing suite. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules and polyfill ES+ features. +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript): Template using Webpack and Babel to use TypeScript in your k6 scripts. +- [JavaScript Compatibility Mode](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode): An option to change the ECMAScript version supported by k6. diff --git a/docs/sources/next/using-k6/test-authoring/_index.md b/docs/sources/next/using-k6/test-authoring/_index.md index 43d5544628..6ccf82b716 100644 --- a/docs/sources/next/using-k6/test-authoring/_index.md +++ b/docs/sources/next/using-k6/test-authoring/_index.md @@ -1,6 +1,6 @@ --- title: Test authoring -weight: 14 +weight: 15 --- # Test authoring diff --git a/docs/sources/v0.47.x/extensions/build-k6-binary-using-docker.md b/docs/sources/v0.47.x/extensions/build-k6-binary-using-docker.md index a6bb55ec7d..e3d6aefeac 100644 --- a/docs/sources/v0.47.x/extensions/build-k6-binary-using-docker.md +++ b/docs/sources/v0.47.x/extensions/build-k6-binary-using-docker.md @@ -8,6 +8,12 @@ weight: 03 Using the [xk6 Docker image](https://hub.docker.com/r/grafana/xk6/) can simplify the process of creating a custom k6 binary. It avoids having to setup a local Go environment, and install xk6 manually. +{{% admonition type="note" %}} + +This tutorial is about creating a custom k6 binary (using Docker). If you want to create a Docker image with a custom k6 binary, refer instead to [Using modules with Docker](https://grafana.com/docs/k6//using-k6/modules/#using-modules-with-docker). + +{{% /admonition %}} + ## Building your first extension For example, to build a custom k6 binary with the latest versions of k6 and the [`xk6-kafka`](https://github.com/mostafa/xk6-kafka) and [`xk6-output-influxdb`](https://github.com/grafana/xk6-output-influxdb) extensions, run one of the commands below, depending on your operating system: diff --git a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md index 792fc58049..907769a911 100644 --- a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md @@ -6,39 +6,71 @@ _build: weight: 19 --- -# JavaScript Compatibility Mode +# JavaScript compatibility mode -You can run test scripts with different ECMAScript compatibility modes with the -`run --compatibility-mode` CLI option or `K6_COMPATIBILITY_MODE` environment variable. +You can write k6 scripts in various ECMAScript versions: -Currently two modes are available: +- ES6+ JavaScript with ES modules (ESM). +- Plain old JavaScript (ES5.1+) with CommonJS modules. -## Base +k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. + +Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: + +![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) + +Since large tests can consume significant resources, some users prefer to bundle and **optimize their test code outside k6 for better performance**. For this reason, k6 offers two JavaScript Compatibility modes: + +- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. + +When running tests, you can change the mode through the `--compatibility-mode` option: + +| Env | CLI | Code / Config file | Default | +| ----------------------- | ---------------------- | ------------------ | ------------ | +| `K6_COMPATIBILITY_MODE` | `--compatibility-mode` | N/A | `"extended"` | + +## Extended mode + +By default, k6 uses the `--compatibility-mode=extended` mode: + +{{< code >}} + +```default +$ k6 run script.js +``` + +{{< /code >}} + +As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. + +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. Also, it may increase startup time (refer to [Performance comparison](#performance-comparison)) and produces code with slightly different line/column numbers. + +## Base mode {{< code >}} -```bash +```cli $ k6 run --compatibility-mode=base script.js ``` -```bash +```env $ K6_COMPATIBILITY_MODE=base k6 run script.js ``` {{< /code >}} -Pure Golang JavaScript VM supporting ES5.1+. Use this mode if your scripts are already written -using only ES5.1 features, or were previously transformed by [Babel](https://babeljs.io/), -to reduce startup time, RAM usage and improve performance. See the [k6-es6 project](https://github.com/k6io/k6-es6) -for an example [Webpack](https://webpack.js.org/) setup that does this -transformation outside of k6. +This mode omits the Babel transformation step, supporting only ES5.1+ code. -> ### ⚠️ Disclaimer -> -> Your mileage may vary while running `--compatibility-mode=base` and also importing external dependencies. For instance, -> `xml2js` and `cheerio` currently do not work, while `lodash` does. +Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. This mode can lead to reduce startup time, RAM usage, and overall improved performance. + +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): + +- [k6-template-es6](https://github.com/grafana/k6-template-es6) +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript) +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example) -### Basic Example +### CommonJS Example {{< code >}} @@ -69,72 +101,13 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -### Advanced Example - -{{< code >}} - -```javascript -const http = require('k6/http'); -const metrics = require('k6/metrics'); -const k6 = require('k6'); - -module.exports.options = { - stages: [ - { duration: '30s', target: 20 }, - { duration: '1m30s', target: 10 }, - { duration: '20s', target: 0 }, - ], - thresholds: { - 'failed requests': ['rate<0.1'], - }, -}; - -const myFailRate = new metrics.Rate('failed requests'); - -module.exports.default = function () { - const res = http.get('https://httpbin.test.k6.io/'); - const checkRes = k6.check(res, { - 'status was 200': function (r) { - return r.status == 200; - }, - }); - if (!checkRes) { - myFailRate.add(1); - } - k6.sleep(1); -}; -``` - -{{< /code >}} - -## Extended - -{{< code >}} - -```bash -$ k6 run --compatibility-mode=extended script.js -``` - -```bash -$ K6_COMPATIBILITY_MODE=extended k6 run script.js -``` - -{{< /code >}} - -In case of syntax/parsing errors, the script will be transformed using Babel with specific plugins bringing the compatibility to ES2015(ES6)+. This means that features such as classes and arrow functions can be used. This does take some time to transpile and the produced code has slightly different line/column numbers. - -Before v0.31.0, k6 included [core.js](https://github.com/zloirock/core-js) v2 and even more Babel plugins in extended mode. -This added around 2MB extra memory usage per VU and some of the transformations (generators, async/await) of Babel were still insufficient to get k6 working with these features. - ## Performance Comparison -There's a substantial difference in performance between both modes, as shown by -[GNU time](https://www.gnu.org/software/time/) below, especially when running tests with a large -number of VUs: +There might be a notable performance difference between both compatibility modes, particularly influenced by the script code and the number of VUs. The following [GNU time](https://www.gnu.org/software/time/) metrics provide insights about their differences: {{< code >}} -```bash +```base $ /usr/bin/time -v k6 run \ --compatibility-mode=base \ --vus 3500 \ @@ -166,7 +139,7 @@ Page size (bytes): 4096 Exit status: 0 ``` -```bash +```extended $ /usr/bin/time -v k6 run \ --compatibility-mode=extended \ --vus 3500 \ @@ -199,3 +172,14 @@ Exit status: 0 ``` {{< /code >}} + +  + +## Read more + +- [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. +- [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. +- [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. +- [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/v0.47.x/using-k6/modules.md b/docs/sources/v0.47.x/using-k6/modules.md index 8f13aaf8fc..49db2ff989 100644 --- a/docs/sources/v0.47.x/using-k6/modules.md +++ b/docs/sources/v0.47.x/using-k6/modules.md @@ -10,11 +10,12 @@ weight: 07 ## Importing modules It's common to import modules, or parts of modules, to use in your test scripts. -In k6, you can import three different kinds of modules: +In k6, you can import different kinds of modules: - [Built-in modules](#built-in-modules) - [Local filesystem modules](#local-filesystem-modules) - [Remote HTTP(S) modules](#remote-https-modules) +- [Extension modules](#extension-modules) ### Built-in modules @@ -27,19 +28,11 @@ For the full list of built-in modules, refer to the [API documentation](https:// import http from 'k6/http'; ``` -### Local filesystem modules +### Local modules -These modules are stored on the local filesystem, and accessed either through relative -or absolute filesystem paths. To make local filesystem modules compatible -with k6, the module itself may use only relative or absolute filesystem imports to access its -dependencies. +These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -```javascript -//helpers.js -export function someHelper() { - // ... -} -``` +k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -50,13 +43,22 @@ export default function () { } ``` -### Remote HTTP(S) modules +```javascript +//helpers.js +export function someHelper() { + // ... +} +``` + +### Remote modules -These modules are accessed over HTTP(S), from a source like [the k6 JSLib](#the-jslib-repository) or +These modules are accessed over HTTP(S), from a public source like GitHub, any CDN, or from any publicly accessible web server. The imported modules are downloaded and executed at runtime, making it extremely important to **make sure you trust the code before including it in a test script**. +For example, [jslib](https://grafana.com/docs/k6//javascript-api/jslib) is a set of k6 JavaScript libraries available as remote HTTPS modules. They can be downloaded and imported as local modules or directly imported as remote modules. + ```javascript import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; @@ -65,282 +67,101 @@ export default function () { } ``` -### The JSLib repository - -**JSLib** is a set of libraries known to work well with k6. It is available at https://jslib.k6.io/. - -These libraries can either be downloaded and included with the test project or loaded directly using HTTP imports. - -## Bundling node modules - -{{% admonition type="caution" %}} - -k6 is not NodeJS, nor is it a browser. Packages that rely on APIs provided by NodeJS, for -instance the `os` and `fs` modules, will not work in k6. The same goes for browser-specific -APIs like the `window` object. - -{{% /admonition %}} - -The steps of this tutorial are as follows: - -1. [Setting up the bundler](#setting-up-the-bundler) - 1. [Installing packages](#installing-packages) - 1. [Configuring Webpack](#configuring-webpack) - 1. [Adding a bundle command](#adding-a-bundle-command) -2. [Running the bundling](#running-the-bundling) -3. [Running the tests](#running-the-tests) - -{{% admonition type="note" %}} - -A [ready-to-use Webpack and Babel starter](https://github.com/k6io/k6-es6) is avaialble in a repository. - -{{% /admonition %}} - -In a JavaScript project running NodeJS, modules are imported using either `import` or `require()`, -using the node module resolution algorithm. -This means that the developer can import modules by name, without providing the full filesystem path to the module. For instance: - -```javascript -import { ClassInAModule } from 'cool-module'; -``` - -would be automatically resolved by the node resolution algorithm by searching: - -- The current directory -- Any `node_modules` folder in the directory -- Any `node_modules` folder in a parent directory, up to the closest `package.json` file. - -As the implementation of `import` in k6 lacks support for the node module resolution algorithm, -node modules that resolve external dependencies will first need to be transformed into a self-contained, -isolated, bundle. - -This is done with the help of a bundling tool, like Webpack, which analyses the test script, -identifies all external dependencies, and then continues to create a self-contained bundle including -everything necessary to run the script. - -If the test script has no external dependencies, already has them vendored in a k6 compatible way, -or only uses ES5.1+ features, using a bundler will not be necessary. - -**Picking a bundler** - -It is possible to use any bundler that supports transpilation. Popular ones include, but are not -limited to, [webpack](https://github.com/webpack/webpack), -[parcel](https://github.com/parcel-bundler/parcel), [rollup](https://github.com/rollup/rollup) -and [browserify](https://github.com/browserify/browserify). - -Due to its flexibility, ease of use, relatively low resource consumption, and known compatibility -with k6, it is recommended to use [webpack](https://github.com/webpack/webpack) unless you have a -specific reason to choose something else. - -**Things to consider** - -In general, all external modules added to a test project have a negative impact on performance, as they further increase the memory footprint and CPU usage. - -Usually, this is not a big problem as each application only allocates these resources once. In k6, however, every VU has a separate JavaScript virtual machine (VM), duplicating the resource usage once each. - -By running code requiring additional features on top of ES5.1, we also need additional extensions to the JavaScript VM, further boosting the resource usage. This is the default mode of k6. - -When bundling using the configuration described in this article, babel and corejs automatically adds the features needed, thus allowing us to run our script without these extensions, using `--compatibility-mode=base`. For more details on the performance benefits of running in the base compatibility mode, see [this article](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode#performance-comparison). - -### Setting up the bundler - -Setting up a Babel and Webpack project from scratch might sound like a big undertaking, but -is usually accomplished within minutes. Start by creating a project folder and initializing -npm: - -{{< code >}} - -```bash -$ mkdir ./example-project && \ - cd "$_" && \ - npm init -y -``` - -{{< /code >}} - -#### Installing packages - -Then, install the packages needed: - -{{< code >}} - -```bash -$ npm install --save-dev \ - webpack \ - webpack-cli \ - @types/k6 \ - babel-loader \ - @babel/core \ - @babel/preset-env \ - core-js -``` - -{{< /code >}} +You can also build your custom Javascript libraries and distribute them via a public web hosting. For reference, [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws) and [k6-rollup-example](https://github.com/grafana/k6-rollup-example) host their modules as GitHub release assets. -| Package | Usage | -| :---------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [webpack](https://github.com/webpack/webpack) | The bundler part of Webpack | -| [webpack-cli](https://github.com/webpack/webpack-cli) | The CLI part of Webpack, which allows us to use it from the terminal | -| [@types/k6](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/k6) | k6 Typescript definition | -| [babel-loader](https://github.com/babel/babel-loader) | A loader used by Webpack to leverage babel functionality while bundling | -| [@babel/core](https://github.com/babel/babel/tree/master/packages/babel-core) | The core functionality of Babel | -| [@babel/preset-env](https://github.com/babel/babel/tree/master/packages/babel-preset-env) | A smart preset using [browserlist](https://github.com/browserslist/browserslist), [compat-table](https://github.com/kangax/compat-table) and [electron-to-chromium](https://github.com/Kilian/electron-to-chromium) to determine what code to transpile and polyfill. | -| [core-js](https://github.com/zloirock/core-js) | A modular standard library for JS including polyfills | +### Extension modules -#### Configuring Webpack +Like the [k6 APIs](https://grafana.com/docs/k6//javascript-api), you can build custom modules in Go code and expose them as JavaScript modules. These custom Go-to-JS modules are known as [k6 extensions](https://grafana.com/docs/k6//extensions). -Once these packages have been added, the next step will be to set up a `webpack.config.js` file: - -{{< code >}} +Below is an example that imports the `k6/x/kubernetes` module from the [xk6-kubernetes](https://github.com/grafana/xk6-kubernetes) extension. ```javascript -const path = require('path'); - -module.exports = { - mode: 'production', - entry: { - login: './src/login.test.js', - signup: './src/signup.test.js', +import { Kubernetes } from 'k6/x/kubernetes'; + +const podSpec = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { name: 'busybox', namespace: 'testns' }, + spec: { + containers: [ + { + name: 'busybox', + image: 'busybox', + command: ['sh', '-c', 'sleep 30'], + }, + ], }, - output: { - path: path.resolve(__dirname, 'dist'), // eslint-disable-line - libraryTarget: 'commonjs', - filename: '[name].bundle.js', - }, - module: { - rules: [{ test: /\.js$/, use: 'babel-loader' }], - }, - target: 'web', - externals: /k6(\/.*)?/, }; +export default function () { + const kubernetes = new Kubernetes(); + kubernetes.create(podSpec); + const pods = kubernetes.list('Pod', 'testns'); + pods.map(function (pod) { + console.log(pod.metadata.name); + }); +} ``` -{{< /code >}} - -`Mode` - -Tells Webpack to automatically use the optimizations associated with the `mode`. -Additional details available in [the webpack docs](https://webpack.js.org/configuration/mode/). +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. -`Entry` +To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). -The files Webpack will use as its entry points while performing the bundling. From these points, -Webpack will automatically traverse all imports recursively until every possible dependency path has -been exhausted. For instance: +## Sharing JavaScript modules -{{< code >}} - -```javascript -// login.test.js - -import { SomeService } from './some.service.js'; +As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. -const svc = new SomeService(); -``` - -{{< /code >}} +> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. -and +**As remote modules** -{{< code >}} +You can host your modules in a public webserver like GitHub and any CDN and be imported remotely. ```javascript -// some.service.js - -import * as lodash from 'lodash'; +// As GitHub release assets +import { + WorkloadConfig, + sayHello, +} from 'https://github.com/grafana/k6-rollup-example/releases/download/v0.0.2/index.js'; -export class SomeService { - constructor() { - this._ = lodash; - } -} +// or hosted in a CDN +import { randomIntBetween, randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; ``` -{{< /code >}} - -would result in Webpack bundling `login.test.js`, `some.service.js` and all upstream dependencies -utilized by `lodash`. - -`Output` - -The `path` key takes an absolute path which is where the finished bundle will be placed. In -this example, `path.resolve` is used to concatenate `__dirname` and `'dist'` into an absolute -path. +When the library consists of multiple files and modules, you may want to bundle these modules to create public releases. Here are some examples for reference: -The `libraryTarget` key configures how the library will be exposed. Setting it to `commonjs` -will result in it being exported using `module.exports`. Additional details available in [the -Webpack docs](https://webpack.js.org/configuration/output/#outputlibrarytarget). +- Using Webpack: [k6-jslib-utils](https://github.com/grafana/k6-jslib-utils) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: [test-commons](https://github.com/grafana/k6-rollup-example/). -The `filename` key, as the name suggests, configures the name of the finished bundles. In this -example, the [template string](https://webpack.js.org/configuration/output/#template-strings) `[name]` -is used to add a dynamic part to the output filename. +Be aware that k6 automatically executes remote modules, making it crucial to trust the source code of these remote modules. There is a **risk of altering the remote modules with certain hosting mechanisms**. To mitigate this security risk, some users prefer to download and import the modules locally to ensure full control of the source code. -#### Adding a bundle command +**As local modules** -Open the `package.json` file and add a new script entry, used for running the bundling process. +In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: -```diff -{ - "name": "bundling-example", - "description": "", - "version": "0.1.0", - "private": true, - "scripts": { -+ "bundle": "webpack" - } - ... -} -``` - -### Running the bundling - -Running webpack will now output two different test bundles, that may be executed independently: - -{{< code >}} - -```bash -$ npm run bundle -# ... -$ tree dist - -dist -├── login.bundle.js -└── signup.bundle.js +```javascript +import { WorkloadConfig, sayHello } from './libs/test-commons.js'; -0 directories, 2 files +import { randomIntBetween, randomItem } from './libs/k6-utils.js'; ``` -{{< /code >}} +Another option to distribute libraries is to use a package manager tool like npm, which enables version locking and the linking of local libraries. The latter can be useful during development. -### Running the tests +Although k6 does not resolve node modules, you can utilize a Bundler to load npm dependencies, as shown in the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -{{< code >}} - -```bash -$ npm run bundle -# ... -$ k6 run dist/login.bundle.js -# ... -``` +## Using TypeScript -{{< /code >}} +k6 does not natively support TypeScript. If you wish to write k6 tests in Typescript, you will need a bundler, as demonstrated in the previous examples: -{{< code >}} +- Using Webpack: Refer to [k6-template-typescript](https://github.com/grafana/k6-template-typescript) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: Apply the [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/master/packages/typescript) to the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -```bash -$ npm run bundle -# ... -$ k6 run dist/signup.bundle.js \ - --vus 10 \ - --duration 10s -# ... -``` +## Using modules with Docker -{{< /code >}} +Built-in and remote modules work out of the box when running k6 in a Docker container like the [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6). -## Using local modules with Docker +### Local modules -When running k6 in a Docker container you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/), so that k6 can see all the JS modules it needs to import. +To run k6 with Docker and import a local module, you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/). Thus, k6 can see all the JS modules it needs to import. For example, say you have the following structure on your host machine: @@ -380,11 +201,42 @@ $ docker run --rm -v /home/k6/example/src:/src -i grafana/k6 run /src/index.js {{< /code >}} Note that on Windows, you also need to make sure that your drive in question, say `C:\`, -has been marked for sharing in the Docker settings: +has been marked for sharing in the Docker Desktop settings. + +### Extension modules -![Running k6 in docker on Windows](/media/docs/k6-oss/running-k6-in-docker-on-windows.png) +The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. + +To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. + +```bash +# Stage 1 - download xk6 and desired extensions, then compile a new binary. +FROM golang:1.20-alpine3.18 as builder +WORKDIR $GOPATH/src/go.k6.io/k6 +COPY . . +RUN apk --no-cache add git=~2 +RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ + && CGO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-output-prometheus-remote=. \ + --output /tmp/k6 + +# Stage 2 - Copy our custom k6 for use within a minimal linux image. +FROM alpine:3.18 +RUN apk add --no-cache ca-certificates && \ + adduser -D -u 12345 -g 12345 k6 +COPY --from=builder /tmp/k6 /usr/bin/k6 + +USER 12345 +WORKDIR /home/k6 + +ENTRYPOINT ["k6"] +``` ## Read more -- [ES6 template](https://github.com/k6io/template-es6): a scaffolding project to use ES6 in your k6 scripts. -- [TypeScript template](https://github.com/k6io/template-typescript): a scaffolding project to use TypeScript in your k6 scripts. +- [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. +- [Extensions directory](https://grafana.com/docs/k6//extensions/explore): A collection of k6 extensions maintained by Grafana Labs and the community. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a common library and testing suite. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules and polyfill ES+ features. +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript): Template using Webpack and Babel to use TypeScript in your k6 scripts. +- [JavaScript Compatibility Mode](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode): An option to change the ECMAScript version supported by k6. diff --git a/docs/sources/v0.47.x/using-k6/test-authoring/_index.md b/docs/sources/v0.47.x/using-k6/test-authoring/_index.md index 43d5544628..6ccf82b716 100644 --- a/docs/sources/v0.47.x/using-k6/test-authoring/_index.md +++ b/docs/sources/v0.47.x/using-k6/test-authoring/_index.md @@ -1,6 +1,6 @@ --- title: Test authoring -weight: 14 +weight: 15 --- # Test authoring diff --git a/docs/sources/v0.48.x/extensions/build-k6-binary-using-docker.md b/docs/sources/v0.48.x/extensions/build-k6-binary-using-docker.md index a6bb55ec7d..e3d6aefeac 100644 --- a/docs/sources/v0.48.x/extensions/build-k6-binary-using-docker.md +++ b/docs/sources/v0.48.x/extensions/build-k6-binary-using-docker.md @@ -8,6 +8,12 @@ weight: 03 Using the [xk6 Docker image](https://hub.docker.com/r/grafana/xk6/) can simplify the process of creating a custom k6 binary. It avoids having to setup a local Go environment, and install xk6 manually. +{{% admonition type="note" %}} + +This tutorial is about creating a custom k6 binary (using Docker). If you want to create a Docker image with a custom k6 binary, refer instead to [Using modules with Docker](https://grafana.com/docs/k6//using-k6/modules/#using-modules-with-docker). + +{{% /admonition %}} + ## Building your first extension For example, to build a custom k6 binary with the latest versions of k6 and the [`xk6-kafka`](https://github.com/mostafa/xk6-kafka) and [`xk6-output-influxdb`](https://github.com/grafana/xk6-output-influxdb) extensions, run one of the commands below, depending on your operating system: diff --git a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md index 792fc58049..907769a911 100644 --- a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md @@ -6,39 +6,71 @@ _build: weight: 19 --- -# JavaScript Compatibility Mode +# JavaScript compatibility mode -You can run test scripts with different ECMAScript compatibility modes with the -`run --compatibility-mode` CLI option or `K6_COMPATIBILITY_MODE` environment variable. +You can write k6 scripts in various ECMAScript versions: -Currently two modes are available: +- ES6+ JavaScript with ES modules (ESM). +- Plain old JavaScript (ES5.1+) with CommonJS modules. -## Base +k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. + +Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: + +![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) + +Since large tests can consume significant resources, some users prefer to bundle and **optimize their test code outside k6 for better performance**. For this reason, k6 offers two JavaScript Compatibility modes: + +- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. + +When running tests, you can change the mode through the `--compatibility-mode` option: + +| Env | CLI | Code / Config file | Default | +| ----------------------- | ---------------------- | ------------------ | ------------ | +| `K6_COMPATIBILITY_MODE` | `--compatibility-mode` | N/A | `"extended"` | + +## Extended mode + +By default, k6 uses the `--compatibility-mode=extended` mode: + +{{< code >}} + +```default +$ k6 run script.js +``` + +{{< /code >}} + +As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. + +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. Also, it may increase startup time (refer to [Performance comparison](#performance-comparison)) and produces code with slightly different line/column numbers. + +## Base mode {{< code >}} -```bash +```cli $ k6 run --compatibility-mode=base script.js ``` -```bash +```env $ K6_COMPATIBILITY_MODE=base k6 run script.js ``` {{< /code >}} -Pure Golang JavaScript VM supporting ES5.1+. Use this mode if your scripts are already written -using only ES5.1 features, or were previously transformed by [Babel](https://babeljs.io/), -to reduce startup time, RAM usage and improve performance. See the [k6-es6 project](https://github.com/k6io/k6-es6) -for an example [Webpack](https://webpack.js.org/) setup that does this -transformation outside of k6. +This mode omits the Babel transformation step, supporting only ES5.1+ code. -> ### ⚠️ Disclaimer -> -> Your mileage may vary while running `--compatibility-mode=base` and also importing external dependencies. For instance, -> `xml2js` and `cheerio` currently do not work, while `lodash` does. +Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. This mode can lead to reduce startup time, RAM usage, and overall improved performance. + +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): + +- [k6-template-es6](https://github.com/grafana/k6-template-es6) +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript) +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example) -### Basic Example +### CommonJS Example {{< code >}} @@ -69,72 +101,13 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -### Advanced Example - -{{< code >}} - -```javascript -const http = require('k6/http'); -const metrics = require('k6/metrics'); -const k6 = require('k6'); - -module.exports.options = { - stages: [ - { duration: '30s', target: 20 }, - { duration: '1m30s', target: 10 }, - { duration: '20s', target: 0 }, - ], - thresholds: { - 'failed requests': ['rate<0.1'], - }, -}; - -const myFailRate = new metrics.Rate('failed requests'); - -module.exports.default = function () { - const res = http.get('https://httpbin.test.k6.io/'); - const checkRes = k6.check(res, { - 'status was 200': function (r) { - return r.status == 200; - }, - }); - if (!checkRes) { - myFailRate.add(1); - } - k6.sleep(1); -}; -``` - -{{< /code >}} - -## Extended - -{{< code >}} - -```bash -$ k6 run --compatibility-mode=extended script.js -``` - -```bash -$ K6_COMPATIBILITY_MODE=extended k6 run script.js -``` - -{{< /code >}} - -In case of syntax/parsing errors, the script will be transformed using Babel with specific plugins bringing the compatibility to ES2015(ES6)+. This means that features such as classes and arrow functions can be used. This does take some time to transpile and the produced code has slightly different line/column numbers. - -Before v0.31.0, k6 included [core.js](https://github.com/zloirock/core-js) v2 and even more Babel plugins in extended mode. -This added around 2MB extra memory usage per VU and some of the transformations (generators, async/await) of Babel were still insufficient to get k6 working with these features. - ## Performance Comparison -There's a substantial difference in performance between both modes, as shown by -[GNU time](https://www.gnu.org/software/time/) below, especially when running tests with a large -number of VUs: +There might be a notable performance difference between both compatibility modes, particularly influenced by the script code and the number of VUs. The following [GNU time](https://www.gnu.org/software/time/) metrics provide insights about their differences: {{< code >}} -```bash +```base $ /usr/bin/time -v k6 run \ --compatibility-mode=base \ --vus 3500 \ @@ -166,7 +139,7 @@ Page size (bytes): 4096 Exit status: 0 ``` -```bash +```extended $ /usr/bin/time -v k6 run \ --compatibility-mode=extended \ --vus 3500 \ @@ -199,3 +172,14 @@ Exit status: 0 ``` {{< /code >}} + +  + +## Read more + +- [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. +- [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. +- [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. +- [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/v0.48.x/using-k6/modules.md b/docs/sources/v0.48.x/using-k6/modules.md index 8f13aaf8fc..49db2ff989 100644 --- a/docs/sources/v0.48.x/using-k6/modules.md +++ b/docs/sources/v0.48.x/using-k6/modules.md @@ -10,11 +10,12 @@ weight: 07 ## Importing modules It's common to import modules, or parts of modules, to use in your test scripts. -In k6, you can import three different kinds of modules: +In k6, you can import different kinds of modules: - [Built-in modules](#built-in-modules) - [Local filesystem modules](#local-filesystem-modules) - [Remote HTTP(S) modules](#remote-https-modules) +- [Extension modules](#extension-modules) ### Built-in modules @@ -27,19 +28,11 @@ For the full list of built-in modules, refer to the [API documentation](https:// import http from 'k6/http'; ``` -### Local filesystem modules +### Local modules -These modules are stored on the local filesystem, and accessed either through relative -or absolute filesystem paths. To make local filesystem modules compatible -with k6, the module itself may use only relative or absolute filesystem imports to access its -dependencies. +These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -```javascript -//helpers.js -export function someHelper() { - // ... -} -``` +k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -50,13 +43,22 @@ export default function () { } ``` -### Remote HTTP(S) modules +```javascript +//helpers.js +export function someHelper() { + // ... +} +``` + +### Remote modules -These modules are accessed over HTTP(S), from a source like [the k6 JSLib](#the-jslib-repository) or +These modules are accessed over HTTP(S), from a public source like GitHub, any CDN, or from any publicly accessible web server. The imported modules are downloaded and executed at runtime, making it extremely important to **make sure you trust the code before including it in a test script**. +For example, [jslib](https://grafana.com/docs/k6//javascript-api/jslib) is a set of k6 JavaScript libraries available as remote HTTPS modules. They can be downloaded and imported as local modules or directly imported as remote modules. + ```javascript import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; @@ -65,282 +67,101 @@ export default function () { } ``` -### The JSLib repository - -**JSLib** is a set of libraries known to work well with k6. It is available at https://jslib.k6.io/. - -These libraries can either be downloaded and included with the test project or loaded directly using HTTP imports. - -## Bundling node modules - -{{% admonition type="caution" %}} - -k6 is not NodeJS, nor is it a browser. Packages that rely on APIs provided by NodeJS, for -instance the `os` and `fs` modules, will not work in k6. The same goes for browser-specific -APIs like the `window` object. - -{{% /admonition %}} - -The steps of this tutorial are as follows: - -1. [Setting up the bundler](#setting-up-the-bundler) - 1. [Installing packages](#installing-packages) - 1. [Configuring Webpack](#configuring-webpack) - 1. [Adding a bundle command](#adding-a-bundle-command) -2. [Running the bundling](#running-the-bundling) -3. [Running the tests](#running-the-tests) - -{{% admonition type="note" %}} - -A [ready-to-use Webpack and Babel starter](https://github.com/k6io/k6-es6) is avaialble in a repository. - -{{% /admonition %}} - -In a JavaScript project running NodeJS, modules are imported using either `import` or `require()`, -using the node module resolution algorithm. -This means that the developer can import modules by name, without providing the full filesystem path to the module. For instance: - -```javascript -import { ClassInAModule } from 'cool-module'; -``` - -would be automatically resolved by the node resolution algorithm by searching: - -- The current directory -- Any `node_modules` folder in the directory -- Any `node_modules` folder in a parent directory, up to the closest `package.json` file. - -As the implementation of `import` in k6 lacks support for the node module resolution algorithm, -node modules that resolve external dependencies will first need to be transformed into a self-contained, -isolated, bundle. - -This is done with the help of a bundling tool, like Webpack, which analyses the test script, -identifies all external dependencies, and then continues to create a self-contained bundle including -everything necessary to run the script. - -If the test script has no external dependencies, already has them vendored in a k6 compatible way, -or only uses ES5.1+ features, using a bundler will not be necessary. - -**Picking a bundler** - -It is possible to use any bundler that supports transpilation. Popular ones include, but are not -limited to, [webpack](https://github.com/webpack/webpack), -[parcel](https://github.com/parcel-bundler/parcel), [rollup](https://github.com/rollup/rollup) -and [browserify](https://github.com/browserify/browserify). - -Due to its flexibility, ease of use, relatively low resource consumption, and known compatibility -with k6, it is recommended to use [webpack](https://github.com/webpack/webpack) unless you have a -specific reason to choose something else. - -**Things to consider** - -In general, all external modules added to a test project have a negative impact on performance, as they further increase the memory footprint and CPU usage. - -Usually, this is not a big problem as each application only allocates these resources once. In k6, however, every VU has a separate JavaScript virtual machine (VM), duplicating the resource usage once each. - -By running code requiring additional features on top of ES5.1, we also need additional extensions to the JavaScript VM, further boosting the resource usage. This is the default mode of k6. - -When bundling using the configuration described in this article, babel and corejs automatically adds the features needed, thus allowing us to run our script without these extensions, using `--compatibility-mode=base`. For more details on the performance benefits of running in the base compatibility mode, see [this article](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode#performance-comparison). - -### Setting up the bundler - -Setting up a Babel and Webpack project from scratch might sound like a big undertaking, but -is usually accomplished within minutes. Start by creating a project folder and initializing -npm: - -{{< code >}} - -```bash -$ mkdir ./example-project && \ - cd "$_" && \ - npm init -y -``` - -{{< /code >}} - -#### Installing packages - -Then, install the packages needed: - -{{< code >}} - -```bash -$ npm install --save-dev \ - webpack \ - webpack-cli \ - @types/k6 \ - babel-loader \ - @babel/core \ - @babel/preset-env \ - core-js -``` - -{{< /code >}} +You can also build your custom Javascript libraries and distribute them via a public web hosting. For reference, [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws) and [k6-rollup-example](https://github.com/grafana/k6-rollup-example) host their modules as GitHub release assets. -| Package | Usage | -| :---------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [webpack](https://github.com/webpack/webpack) | The bundler part of Webpack | -| [webpack-cli](https://github.com/webpack/webpack-cli) | The CLI part of Webpack, which allows us to use it from the terminal | -| [@types/k6](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/k6) | k6 Typescript definition | -| [babel-loader](https://github.com/babel/babel-loader) | A loader used by Webpack to leverage babel functionality while bundling | -| [@babel/core](https://github.com/babel/babel/tree/master/packages/babel-core) | The core functionality of Babel | -| [@babel/preset-env](https://github.com/babel/babel/tree/master/packages/babel-preset-env) | A smart preset using [browserlist](https://github.com/browserslist/browserslist), [compat-table](https://github.com/kangax/compat-table) and [electron-to-chromium](https://github.com/Kilian/electron-to-chromium) to determine what code to transpile and polyfill. | -| [core-js](https://github.com/zloirock/core-js) | A modular standard library for JS including polyfills | +### Extension modules -#### Configuring Webpack +Like the [k6 APIs](https://grafana.com/docs/k6//javascript-api), you can build custom modules in Go code and expose them as JavaScript modules. These custom Go-to-JS modules are known as [k6 extensions](https://grafana.com/docs/k6//extensions). -Once these packages have been added, the next step will be to set up a `webpack.config.js` file: - -{{< code >}} +Below is an example that imports the `k6/x/kubernetes` module from the [xk6-kubernetes](https://github.com/grafana/xk6-kubernetes) extension. ```javascript -const path = require('path'); - -module.exports = { - mode: 'production', - entry: { - login: './src/login.test.js', - signup: './src/signup.test.js', +import { Kubernetes } from 'k6/x/kubernetes'; + +const podSpec = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { name: 'busybox', namespace: 'testns' }, + spec: { + containers: [ + { + name: 'busybox', + image: 'busybox', + command: ['sh', '-c', 'sleep 30'], + }, + ], }, - output: { - path: path.resolve(__dirname, 'dist'), // eslint-disable-line - libraryTarget: 'commonjs', - filename: '[name].bundle.js', - }, - module: { - rules: [{ test: /\.js$/, use: 'babel-loader' }], - }, - target: 'web', - externals: /k6(\/.*)?/, }; +export default function () { + const kubernetes = new Kubernetes(); + kubernetes.create(podSpec); + const pods = kubernetes.list('Pod', 'testns'); + pods.map(function (pod) { + console.log(pod.metadata.name); + }); +} ``` -{{< /code >}} - -`Mode` - -Tells Webpack to automatically use the optimizations associated with the `mode`. -Additional details available in [the webpack docs](https://webpack.js.org/configuration/mode/). +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. -`Entry` +To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). -The files Webpack will use as its entry points while performing the bundling. From these points, -Webpack will automatically traverse all imports recursively until every possible dependency path has -been exhausted. For instance: +## Sharing JavaScript modules -{{< code >}} - -```javascript -// login.test.js - -import { SomeService } from './some.service.js'; +As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. -const svc = new SomeService(); -``` - -{{< /code >}} +> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. -and +**As remote modules** -{{< code >}} +You can host your modules in a public webserver like GitHub and any CDN and be imported remotely. ```javascript -// some.service.js - -import * as lodash from 'lodash'; +// As GitHub release assets +import { + WorkloadConfig, + sayHello, +} from 'https://github.com/grafana/k6-rollup-example/releases/download/v0.0.2/index.js'; -export class SomeService { - constructor() { - this._ = lodash; - } -} +// or hosted in a CDN +import { randomIntBetween, randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; ``` -{{< /code >}} - -would result in Webpack bundling `login.test.js`, `some.service.js` and all upstream dependencies -utilized by `lodash`. - -`Output` - -The `path` key takes an absolute path which is where the finished bundle will be placed. In -this example, `path.resolve` is used to concatenate `__dirname` and `'dist'` into an absolute -path. +When the library consists of multiple files and modules, you may want to bundle these modules to create public releases. Here are some examples for reference: -The `libraryTarget` key configures how the library will be exposed. Setting it to `commonjs` -will result in it being exported using `module.exports`. Additional details available in [the -Webpack docs](https://webpack.js.org/configuration/output/#outputlibrarytarget). +- Using Webpack: [k6-jslib-utils](https://github.com/grafana/k6-jslib-utils) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: [test-commons](https://github.com/grafana/k6-rollup-example/). -The `filename` key, as the name suggests, configures the name of the finished bundles. In this -example, the [template string](https://webpack.js.org/configuration/output/#template-strings) `[name]` -is used to add a dynamic part to the output filename. +Be aware that k6 automatically executes remote modules, making it crucial to trust the source code of these remote modules. There is a **risk of altering the remote modules with certain hosting mechanisms**. To mitigate this security risk, some users prefer to download and import the modules locally to ensure full control of the source code. -#### Adding a bundle command +**As local modules** -Open the `package.json` file and add a new script entry, used for running the bundling process. +In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: -```diff -{ - "name": "bundling-example", - "description": "", - "version": "0.1.0", - "private": true, - "scripts": { -+ "bundle": "webpack" - } - ... -} -``` - -### Running the bundling - -Running webpack will now output two different test bundles, that may be executed independently: - -{{< code >}} - -```bash -$ npm run bundle -# ... -$ tree dist - -dist -├── login.bundle.js -└── signup.bundle.js +```javascript +import { WorkloadConfig, sayHello } from './libs/test-commons.js'; -0 directories, 2 files +import { randomIntBetween, randomItem } from './libs/k6-utils.js'; ``` -{{< /code >}} +Another option to distribute libraries is to use a package manager tool like npm, which enables version locking and the linking of local libraries. The latter can be useful during development. -### Running the tests +Although k6 does not resolve node modules, you can utilize a Bundler to load npm dependencies, as shown in the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -{{< code >}} - -```bash -$ npm run bundle -# ... -$ k6 run dist/login.bundle.js -# ... -``` +## Using TypeScript -{{< /code >}} +k6 does not natively support TypeScript. If you wish to write k6 tests in Typescript, you will need a bundler, as demonstrated in the previous examples: -{{< code >}} +- Using Webpack: Refer to [k6-template-typescript](https://github.com/grafana/k6-template-typescript) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: Apply the [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/master/packages/typescript) to the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -```bash -$ npm run bundle -# ... -$ k6 run dist/signup.bundle.js \ - --vus 10 \ - --duration 10s -# ... -``` +## Using modules with Docker -{{< /code >}} +Built-in and remote modules work out of the box when running k6 in a Docker container like the [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6). -## Using local modules with Docker +### Local modules -When running k6 in a Docker container you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/), so that k6 can see all the JS modules it needs to import. +To run k6 with Docker and import a local module, you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/). Thus, k6 can see all the JS modules it needs to import. For example, say you have the following structure on your host machine: @@ -380,11 +201,42 @@ $ docker run --rm -v /home/k6/example/src:/src -i grafana/k6 run /src/index.js {{< /code >}} Note that on Windows, you also need to make sure that your drive in question, say `C:\`, -has been marked for sharing in the Docker settings: +has been marked for sharing in the Docker Desktop settings. + +### Extension modules -![Running k6 in docker on Windows](/media/docs/k6-oss/running-k6-in-docker-on-windows.png) +The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. + +To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. + +```bash +# Stage 1 - download xk6 and desired extensions, then compile a new binary. +FROM golang:1.20-alpine3.18 as builder +WORKDIR $GOPATH/src/go.k6.io/k6 +COPY . . +RUN apk --no-cache add git=~2 +RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ + && CGO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-output-prometheus-remote=. \ + --output /tmp/k6 + +# Stage 2 - Copy our custom k6 for use within a minimal linux image. +FROM alpine:3.18 +RUN apk add --no-cache ca-certificates && \ + adduser -D -u 12345 -g 12345 k6 +COPY --from=builder /tmp/k6 /usr/bin/k6 + +USER 12345 +WORKDIR /home/k6 + +ENTRYPOINT ["k6"] +``` ## Read more -- [ES6 template](https://github.com/k6io/template-es6): a scaffolding project to use ES6 in your k6 scripts. -- [TypeScript template](https://github.com/k6io/template-typescript): a scaffolding project to use TypeScript in your k6 scripts. +- [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. +- [Extensions directory](https://grafana.com/docs/k6//extensions/explore): A collection of k6 extensions maintained by Grafana Labs and the community. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a common library and testing suite. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules and polyfill ES+ features. +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript): Template using Webpack and Babel to use TypeScript in your k6 scripts. +- [JavaScript Compatibility Mode](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode): An option to change the ECMAScript version supported by k6. diff --git a/docs/sources/v0.48.x/using-k6/test-authoring/_index.md b/docs/sources/v0.48.x/using-k6/test-authoring/_index.md index 43d5544628..6ccf82b716 100644 --- a/docs/sources/v0.48.x/using-k6/test-authoring/_index.md +++ b/docs/sources/v0.48.x/using-k6/test-authoring/_index.md @@ -1,6 +1,6 @@ --- title: Test authoring -weight: 14 +weight: 15 --- # Test authoring From 90ecc4c112afec420bfd26f48448ad0508ae7c25 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Fri, 26 Jan 2024 16:59:06 +0100 Subject: [PATCH 02/21] Update Javascript Compatibility Mode --- .../using-k6/javascript-compatibility-mode.md | 96 +++---------------- .../next/using-k6/test-authoring/_index.md | 2 +- .../using-k6/javascript-compatibility-mode.md | 96 +++---------------- .../v0.47.x/using-k6/test-authoring/_index.md | 2 +- .../using-k6/javascript-compatibility-mode.md | 96 +++---------------- .../v0.48.x/using-k6/test-authoring/_index.md | 2 +- 6 files changed, 36 insertions(+), 258 deletions(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 907769a911..29b57dc23b 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -1,6 +1,7 @@ --- -title: JavaScript Compatibility Mode -description: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' +title: JavaScript compatibility mode +menuTitle: JavaScript mode +excerpt: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' _build: list: false weight: 19 @@ -19,7 +20,7 @@ Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internall ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -Since large tests can consume significant resources, some users prefer to bundle and **optimize their test code outside k6 for better performance**. For this reason, k6 offers two JavaScript Compatibility modes: +The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: - [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. @@ -44,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. Also, it may increase startup time (refer to [Performance comparison](#performance-comparison)) and produces code with slightly different line/column numbers. +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. ## Base mode @@ -60,15 +61,9 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. +This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. -Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. This mode can lead to reduce startup time, RAM usage, and overall improved performance. - -The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): - -- [k6-template-es6](https://github.com/grafana/k6-template-es6) -- [k6-template-typescript](https://github.com/grafana/k6-template-typescript) -- [k6-rollup-example](https://github.com/grafana/k6-rollup-example) +In general, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example @@ -101,85 +96,16 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -## Performance Comparison - -There might be a notable performance difference between both compatibility modes, particularly influenced by the script code and the number of VUs. The following [GNU time](https://www.gnu.org/software/time/) metrics provide insights about their differences: - -{{< code >}} - -```base -$ /usr/bin/time -v k6 run \ - --compatibility-mode=base \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 15.10 -System time (seconds): 10.02 -Percent of CPU this job got: 40% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:01.88 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 903612 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 352090 -Voluntary context switches: 558479 -Involuntary context switches: 4689 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` - -```extended -$ /usr/bin/time -v k6 run \ - --compatibility-mode=extended \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 104.44 -System time (seconds): 6.96 -Percent of CPU this job got: 101% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:49.49 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 7972316 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 2595676 -Voluntary context switches: 535511 -Involuntary context switches: 9306 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` +## Bundling with Babel outside of k6 -{{< /code >}} +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): -  +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. ## Read more - [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. -- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules. -- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. - [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. - [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. - [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/next/using-k6/test-authoring/_index.md b/docs/sources/next/using-k6/test-authoring/_index.md index 6ccf82b716..43d5544628 100644 --- a/docs/sources/next/using-k6/test-authoring/_index.md +++ b/docs/sources/next/using-k6/test-authoring/_index.md @@ -1,6 +1,6 @@ --- title: Test authoring -weight: 15 +weight: 14 --- # Test authoring diff --git a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md index 907769a911..29b57dc23b 100644 --- a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md @@ -1,6 +1,7 @@ --- -title: JavaScript Compatibility Mode -description: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' +title: JavaScript compatibility mode +menuTitle: JavaScript mode +excerpt: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' _build: list: false weight: 19 @@ -19,7 +20,7 @@ Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internall ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -Since large tests can consume significant resources, some users prefer to bundle and **optimize their test code outside k6 for better performance**. For this reason, k6 offers two JavaScript Compatibility modes: +The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: - [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. @@ -44,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. Also, it may increase startup time (refer to [Performance comparison](#performance-comparison)) and produces code with slightly different line/column numbers. +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. ## Base mode @@ -60,15 +61,9 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. +This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. -Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. This mode can lead to reduce startup time, RAM usage, and overall improved performance. - -The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): - -- [k6-template-es6](https://github.com/grafana/k6-template-es6) -- [k6-template-typescript](https://github.com/grafana/k6-template-typescript) -- [k6-rollup-example](https://github.com/grafana/k6-rollup-example) +In general, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example @@ -101,85 +96,16 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -## Performance Comparison - -There might be a notable performance difference between both compatibility modes, particularly influenced by the script code and the number of VUs. The following [GNU time](https://www.gnu.org/software/time/) metrics provide insights about their differences: - -{{< code >}} - -```base -$ /usr/bin/time -v k6 run \ - --compatibility-mode=base \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 15.10 -System time (seconds): 10.02 -Percent of CPU this job got: 40% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:01.88 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 903612 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 352090 -Voluntary context switches: 558479 -Involuntary context switches: 4689 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` - -```extended -$ /usr/bin/time -v k6 run \ - --compatibility-mode=extended \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 104.44 -System time (seconds): 6.96 -Percent of CPU this job got: 101% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:49.49 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 7972316 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 2595676 -Voluntary context switches: 535511 -Involuntary context switches: 9306 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` +## Bundling with Babel outside of k6 -{{< /code >}} +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): -  +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. ## Read more - [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. -- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules. -- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. - [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. - [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. - [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/v0.47.x/using-k6/test-authoring/_index.md b/docs/sources/v0.47.x/using-k6/test-authoring/_index.md index 6ccf82b716..43d5544628 100644 --- a/docs/sources/v0.47.x/using-k6/test-authoring/_index.md +++ b/docs/sources/v0.47.x/using-k6/test-authoring/_index.md @@ -1,6 +1,6 @@ --- title: Test authoring -weight: 15 +weight: 14 --- # Test authoring diff --git a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md index 907769a911..29b57dc23b 100644 --- a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md @@ -1,6 +1,7 @@ --- -title: JavaScript Compatibility Mode -description: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' +title: JavaScript compatibility mode +menuTitle: JavaScript mode +excerpt: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' _build: list: false weight: 19 @@ -19,7 +20,7 @@ Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internall ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -Since large tests can consume significant resources, some users prefer to bundle and **optimize their test code outside k6 for better performance**. For this reason, k6 offers two JavaScript Compatibility modes: +The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: - [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. @@ -44,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. Also, it may increase startup time (refer to [Performance comparison](#performance-comparison)) and produces code with slightly different line/column numbers. +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. ## Base mode @@ -60,15 +61,9 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. +This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. -Use this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. This mode can lead to reduce startup time, RAM usage, and overall improved performance. - -The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): - -- [k6-template-es6](https://github.com/grafana/k6-template-es6) -- [k6-template-typescript](https://github.com/grafana/k6-template-typescript) -- [k6-rollup-example](https://github.com/grafana/k6-rollup-example) +In general, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example @@ -101,85 +96,16 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -## Performance Comparison - -There might be a notable performance difference between both compatibility modes, particularly influenced by the script code and the number of VUs. The following [GNU time](https://www.gnu.org/software/time/) metrics provide insights about their differences: - -{{< code >}} - -```base -$ /usr/bin/time -v k6 run \ - --compatibility-mode=base \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 15.10 -System time (seconds): 10.02 -Percent of CPU this job got: 40% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:01.88 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 903612 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 352090 -Voluntary context switches: 558479 -Involuntary context switches: 4689 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` - -```extended -$ /usr/bin/time -v k6 run \ - --compatibility-mode=extended \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 104.44 -System time (seconds): 6.96 -Percent of CPU this job got: 101% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:49.49 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 7972316 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 2595676 -Voluntary context switches: 535511 -Involuntary context switches: 9306 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` +## Bundling with Babel outside of k6 -{{< /code >}} +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): -  +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. ## Read more - [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. -- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules. -- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. - [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. - [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. - [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/v0.48.x/using-k6/test-authoring/_index.md b/docs/sources/v0.48.x/using-k6/test-authoring/_index.md index 6ccf82b716..43d5544628 100644 --- a/docs/sources/v0.48.x/using-k6/test-authoring/_index.md +++ b/docs/sources/v0.48.x/using-k6/test-authoring/_index.md @@ -1,6 +1,6 @@ --- title: Test authoring -weight: 15 +weight: 14 --- # Test authoring From 840ed31b7f7a517c3c2c7d191877d0d6f32fe50d Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:50:38 +0100 Subject: [PATCH 03/21] Port changes to v0.49.x --- .../build-k6-binary-using-docker.md | 6 + .../using-k6/javascript-compatibility-mode.md | 200 +++------- docs/sources/v0.49.x/using-k6/modules.md | 368 ++++++------------ 3 files changed, 171 insertions(+), 403 deletions(-) diff --git a/docs/sources/v0.49.x/extensions/build-k6-binary-using-docker.md b/docs/sources/v0.49.x/extensions/build-k6-binary-using-docker.md index a6bb55ec7d..e3d6aefeac 100644 --- a/docs/sources/v0.49.x/extensions/build-k6-binary-using-docker.md +++ b/docs/sources/v0.49.x/extensions/build-k6-binary-using-docker.md @@ -8,6 +8,12 @@ weight: 03 Using the [xk6 Docker image](https://hub.docker.com/r/grafana/xk6/) can simplify the process of creating a custom k6 binary. It avoids having to setup a local Go environment, and install xk6 manually. +{{% admonition type="note" %}} + +This tutorial is about creating a custom k6 binary (using Docker). If you want to create a Docker image with a custom k6 binary, refer instead to [Using modules with Docker](https://grafana.com/docs/k6//using-k6/modules/#using-modules-with-docker). + +{{% /admonition %}} + ## Building your first extension For example, to build a custom k6 binary with the latest versions of k6 and the [`xk6-kafka`](https://github.com/mostafa/xk6-kafka) and [`xk6-output-influxdb`](https://github.com/grafana/xk6-output-influxdb) extensions, run one of the commands below, depending on your operating system: diff --git a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md index 792fc58049..29b57dc23b 100644 --- a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md @@ -1,44 +1,71 @@ --- -title: JavaScript Compatibility Mode -description: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' +title: JavaScript compatibility mode +menuTitle: JavaScript mode +excerpt: 'k6 supports running test scripts with different ECMAScript compatibility modes using --compatibility-mode' _build: list: false weight: 19 --- -# JavaScript Compatibility Mode +# JavaScript compatibility mode -You can run test scripts with different ECMAScript compatibility modes with the -`run --compatibility-mode` CLI option or `K6_COMPATIBILITY_MODE` environment variable. +You can write k6 scripts in various ECMAScript versions: -Currently two modes are available: +- ES6+ JavaScript with ES modules (ESM). +- Plain old JavaScript (ES5.1+) with CommonJS modules. -## Base +k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. + +Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: + +![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) + +The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: + +- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. + +When running tests, you can change the mode through the `--compatibility-mode` option: + +| Env | CLI | Code / Config file | Default | +| ----------------------- | ---------------------- | ------------------ | ------------ | +| `K6_COMPATIBILITY_MODE` | `--compatibility-mode` | N/A | `"extended"` | + +## Extended mode + +By default, k6 uses the `--compatibility-mode=extended` mode: + +{{< code >}} + +```default +$ k6 run script.js +``` + +{{< /code >}} + +As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. + +This k6 Babel transformation enables the k6 JavaScript VM to execute the test. + +## Base mode {{< code >}} -```bash +```cli $ k6 run --compatibility-mode=base script.js ``` -```bash +```env $ K6_COMPATIBILITY_MODE=base k6 run script.js ``` {{< /code >}} -Pure Golang JavaScript VM supporting ES5.1+. Use this mode if your scripts are already written -using only ES5.1 features, or were previously transformed by [Babel](https://babeljs.io/), -to reduce startup time, RAM usage and improve performance. See the [k6-es6 project](https://github.com/k6io/k6-es6) -for an example [Webpack](https://webpack.js.org/) setup that does this -transformation outside of k6. +This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. -> ### ⚠️ Disclaimer -> -> Your mileage may vary while running `--compatibility-mode=base` and also importing external dependencies. For instance, -> `xml2js` and `cheerio` currently do not work, while `lodash` does. +In general, this mode is not recommended as it offers minor benefits in reducing startup time. -### Basic Example +### CommonJS Example {{< code >}} @@ -69,133 +96,16 @@ module.exports.default = function () { > but it does _not_ support the > [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -### Advanced Example - -{{< code >}} - -```javascript -const http = require('k6/http'); -const metrics = require('k6/metrics'); -const k6 = require('k6'); - -module.exports.options = { - stages: [ - { duration: '30s', target: 20 }, - { duration: '1m30s', target: 10 }, - { duration: '20s', target: 0 }, - ], - thresholds: { - 'failed requests': ['rate<0.1'], - }, -}; - -const myFailRate = new metrics.Rate('failed requests'); - -module.exports.default = function () { - const res = http.get('https://httpbin.test.k6.io/'); - const checkRes = k6.check(res, { - 'status was 200': function (r) { - return r.status == 200; - }, - }); - if (!checkRes) { - myFailRate.add(1); - } - k6.sleep(1); -}; -``` - -{{< /code >}} - -## Extended - -{{< code >}} - -```bash -$ k6 run --compatibility-mode=extended script.js -``` - -```bash -$ K6_COMPATIBILITY_MODE=extended k6 run script.js -``` +## Bundling with Babel outside of k6 -{{< /code >}} +The examples below demonstrate the use of Babel with bundlers like [Webpack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/): -In case of syntax/parsing errors, the script will be transformed using Babel with specific plugins bringing the compatibility to ES2015(ES6)+. This means that features such as classes and arrow functions can be used. This does take some time to transpile and the produced code has slightly different line/column numbers. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a testing project. -Before v0.31.0, k6 included [core.js](https://github.com/zloirock/core-js) v2 and even more Babel plugins in extended mode. -This added around 2MB extra memory usage per VU and some of the transformations (generators, async/await) of Babel were still insufficient to get k6 working with these features. +## Read more -## Performance Comparison - -There's a substantial difference in performance between both modes, as shown by -[GNU time](https://www.gnu.org/software/time/) below, especially when running tests with a large -number of VUs: - -{{< code >}} - -```bash -$ /usr/bin/time -v k6 run \ - --compatibility-mode=base \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 15.10 -System time (seconds): 10.02 -Percent of CPU this job got: 40% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:01.88 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 903612 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 352090 -Voluntary context switches: 558479 -Involuntary context switches: 4689 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` - -```bash -$ /usr/bin/time -v k6 run \ - --compatibility-mode=extended \ - --vus 3500 \ - --duration=60s \ - script.js - -[...] -User time (seconds): 104.44 -System time (seconds): 6.96 -Percent of CPU this job got: 101% -Elapsed (wall clock) time (h:mm:ss or m:ss): 1:49.49 -Average shared text size (kbytes): 0 -Average unshared data size (kbytes): 0 -Average stack size (kbytes): 0 -Average total size (kbytes): 0 -Maximum resident set size (kbytes): 7972316 -Average resident set size (kbytes): 0 -Major (requiring I/O) page faults: 1 -Minor (reclaiming a frame) page faults: 2595676 -Voluntary context switches: 535511 -Involuntary context switches: 9306 -Swaps: 0 -File system inputs: 0 -File system outputs: 78856 -Socket messages sent: 0 -Socket messages received: 0 -Signals delivered: 0 -Page size (bytes): 4096 -Exit status: 0 -``` - -{{< /code >}} +- [Native ESM support](https://github.com/grafana/k6/issues/3265): GitHub issue for native ESM support in k6. This feature aims to eliminate the Babel transformation step within k6. +- [Running large tests](https://grafana.com/docs/k6//testing-guides/running-large-tests): Optimize k6 for better performance. +- [k6 Modules](https://grafana.com/docs/k6//using-k6/modules): Different options to import modules in k6. +- [k6 Archive Command](https://grafana.com/docs/k6//misc/archive): The `k6 archive` command bundles all k6 test dependencies into a `tar` file, which can then be used for execution. It may also reduce the execution startup time. diff --git a/docs/sources/v0.49.x/using-k6/modules.md b/docs/sources/v0.49.x/using-k6/modules.md index 8f13aaf8fc..49db2ff989 100644 --- a/docs/sources/v0.49.x/using-k6/modules.md +++ b/docs/sources/v0.49.x/using-k6/modules.md @@ -10,11 +10,12 @@ weight: 07 ## Importing modules It's common to import modules, or parts of modules, to use in your test scripts. -In k6, you can import three different kinds of modules: +In k6, you can import different kinds of modules: - [Built-in modules](#built-in-modules) - [Local filesystem modules](#local-filesystem-modules) - [Remote HTTP(S) modules](#remote-https-modules) +- [Extension modules](#extension-modules) ### Built-in modules @@ -27,19 +28,11 @@ For the full list of built-in modules, refer to the [API documentation](https:// import http from 'k6/http'; ``` -### Local filesystem modules +### Local modules -These modules are stored on the local filesystem, and accessed either through relative -or absolute filesystem paths. To make local filesystem modules compatible -with k6, the module itself may use only relative or absolute filesystem imports to access its -dependencies. +These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -```javascript -//helpers.js -export function someHelper() { - // ... -} -``` +k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -50,13 +43,22 @@ export default function () { } ``` -### Remote HTTP(S) modules +```javascript +//helpers.js +export function someHelper() { + // ... +} +``` + +### Remote modules -These modules are accessed over HTTP(S), from a source like [the k6 JSLib](#the-jslib-repository) or +These modules are accessed over HTTP(S), from a public source like GitHub, any CDN, or from any publicly accessible web server. The imported modules are downloaded and executed at runtime, making it extremely important to **make sure you trust the code before including it in a test script**. +For example, [jslib](https://grafana.com/docs/k6//javascript-api/jslib) is a set of k6 JavaScript libraries available as remote HTTPS modules. They can be downloaded and imported as local modules or directly imported as remote modules. + ```javascript import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; @@ -65,282 +67,101 @@ export default function () { } ``` -### The JSLib repository - -**JSLib** is a set of libraries known to work well with k6. It is available at https://jslib.k6.io/. - -These libraries can either be downloaded and included with the test project or loaded directly using HTTP imports. - -## Bundling node modules - -{{% admonition type="caution" %}} - -k6 is not NodeJS, nor is it a browser. Packages that rely on APIs provided by NodeJS, for -instance the `os` and `fs` modules, will not work in k6. The same goes for browser-specific -APIs like the `window` object. - -{{% /admonition %}} - -The steps of this tutorial are as follows: - -1. [Setting up the bundler](#setting-up-the-bundler) - 1. [Installing packages](#installing-packages) - 1. [Configuring Webpack](#configuring-webpack) - 1. [Adding a bundle command](#adding-a-bundle-command) -2. [Running the bundling](#running-the-bundling) -3. [Running the tests](#running-the-tests) - -{{% admonition type="note" %}} - -A [ready-to-use Webpack and Babel starter](https://github.com/k6io/k6-es6) is avaialble in a repository. - -{{% /admonition %}} - -In a JavaScript project running NodeJS, modules are imported using either `import` or `require()`, -using the node module resolution algorithm. -This means that the developer can import modules by name, without providing the full filesystem path to the module. For instance: - -```javascript -import { ClassInAModule } from 'cool-module'; -``` - -would be automatically resolved by the node resolution algorithm by searching: - -- The current directory -- Any `node_modules` folder in the directory -- Any `node_modules` folder in a parent directory, up to the closest `package.json` file. - -As the implementation of `import` in k6 lacks support for the node module resolution algorithm, -node modules that resolve external dependencies will first need to be transformed into a self-contained, -isolated, bundle. - -This is done with the help of a bundling tool, like Webpack, which analyses the test script, -identifies all external dependencies, and then continues to create a self-contained bundle including -everything necessary to run the script. - -If the test script has no external dependencies, already has them vendored in a k6 compatible way, -or only uses ES5.1+ features, using a bundler will not be necessary. - -**Picking a bundler** - -It is possible to use any bundler that supports transpilation. Popular ones include, but are not -limited to, [webpack](https://github.com/webpack/webpack), -[parcel](https://github.com/parcel-bundler/parcel), [rollup](https://github.com/rollup/rollup) -and [browserify](https://github.com/browserify/browserify). - -Due to its flexibility, ease of use, relatively low resource consumption, and known compatibility -with k6, it is recommended to use [webpack](https://github.com/webpack/webpack) unless you have a -specific reason to choose something else. - -**Things to consider** - -In general, all external modules added to a test project have a negative impact on performance, as they further increase the memory footprint and CPU usage. - -Usually, this is not a big problem as each application only allocates these resources once. In k6, however, every VU has a separate JavaScript virtual machine (VM), duplicating the resource usage once each. - -By running code requiring additional features on top of ES5.1, we also need additional extensions to the JavaScript VM, further boosting the resource usage. This is the default mode of k6. - -When bundling using the configuration described in this article, babel and corejs automatically adds the features needed, thus allowing us to run our script without these extensions, using `--compatibility-mode=base`. For more details on the performance benefits of running in the base compatibility mode, see [this article](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode#performance-comparison). - -### Setting up the bundler - -Setting up a Babel and Webpack project from scratch might sound like a big undertaking, but -is usually accomplished within minutes. Start by creating a project folder and initializing -npm: - -{{< code >}} - -```bash -$ mkdir ./example-project && \ - cd "$_" && \ - npm init -y -``` - -{{< /code >}} - -#### Installing packages - -Then, install the packages needed: - -{{< code >}} - -```bash -$ npm install --save-dev \ - webpack \ - webpack-cli \ - @types/k6 \ - babel-loader \ - @babel/core \ - @babel/preset-env \ - core-js -``` - -{{< /code >}} +You can also build your custom Javascript libraries and distribute them via a public web hosting. For reference, [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws) and [k6-rollup-example](https://github.com/grafana/k6-rollup-example) host their modules as GitHub release assets. -| Package | Usage | -| :---------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [webpack](https://github.com/webpack/webpack) | The bundler part of Webpack | -| [webpack-cli](https://github.com/webpack/webpack-cli) | The CLI part of Webpack, which allows us to use it from the terminal | -| [@types/k6](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/k6) | k6 Typescript definition | -| [babel-loader](https://github.com/babel/babel-loader) | A loader used by Webpack to leverage babel functionality while bundling | -| [@babel/core](https://github.com/babel/babel/tree/master/packages/babel-core) | The core functionality of Babel | -| [@babel/preset-env](https://github.com/babel/babel/tree/master/packages/babel-preset-env) | A smart preset using [browserlist](https://github.com/browserslist/browserslist), [compat-table](https://github.com/kangax/compat-table) and [electron-to-chromium](https://github.com/Kilian/electron-to-chromium) to determine what code to transpile and polyfill. | -| [core-js](https://github.com/zloirock/core-js) | A modular standard library for JS including polyfills | +### Extension modules -#### Configuring Webpack +Like the [k6 APIs](https://grafana.com/docs/k6//javascript-api), you can build custom modules in Go code and expose them as JavaScript modules. These custom Go-to-JS modules are known as [k6 extensions](https://grafana.com/docs/k6//extensions). -Once these packages have been added, the next step will be to set up a `webpack.config.js` file: - -{{< code >}} +Below is an example that imports the `k6/x/kubernetes` module from the [xk6-kubernetes](https://github.com/grafana/xk6-kubernetes) extension. ```javascript -const path = require('path'); - -module.exports = { - mode: 'production', - entry: { - login: './src/login.test.js', - signup: './src/signup.test.js', +import { Kubernetes } from 'k6/x/kubernetes'; + +const podSpec = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { name: 'busybox', namespace: 'testns' }, + spec: { + containers: [ + { + name: 'busybox', + image: 'busybox', + command: ['sh', '-c', 'sleep 30'], + }, + ], }, - output: { - path: path.resolve(__dirname, 'dist'), // eslint-disable-line - libraryTarget: 'commonjs', - filename: '[name].bundle.js', - }, - module: { - rules: [{ test: /\.js$/, use: 'babel-loader' }], - }, - target: 'web', - externals: /k6(\/.*)?/, }; +export default function () { + const kubernetes = new Kubernetes(); + kubernetes.create(podSpec); + const pods = kubernetes.list('Pod', 'testns'); + pods.map(function (pod) { + console.log(pod.metadata.name); + }); +} ``` -{{< /code >}} - -`Mode` - -Tells Webpack to automatically use the optimizations associated with the `mode`. -Additional details available in [the webpack docs](https://webpack.js.org/configuration/mode/). +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. -`Entry` +To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). -The files Webpack will use as its entry points while performing the bundling. From these points, -Webpack will automatically traverse all imports recursively until every possible dependency path has -been exhausted. For instance: +## Sharing JavaScript modules -{{< code >}} - -```javascript -// login.test.js - -import { SomeService } from './some.service.js'; +As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. -const svc = new SomeService(); -``` - -{{< /code >}} +> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. -and +**As remote modules** -{{< code >}} +You can host your modules in a public webserver like GitHub and any CDN and be imported remotely. ```javascript -// some.service.js - -import * as lodash from 'lodash'; +// As GitHub release assets +import { + WorkloadConfig, + sayHello, +} from 'https://github.com/grafana/k6-rollup-example/releases/download/v0.0.2/index.js'; -export class SomeService { - constructor() { - this._ = lodash; - } -} +// or hosted in a CDN +import { randomIntBetween, randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; ``` -{{< /code >}} - -would result in Webpack bundling `login.test.js`, `some.service.js` and all upstream dependencies -utilized by `lodash`. - -`Output` - -The `path` key takes an absolute path which is where the finished bundle will be placed. In -this example, `path.resolve` is used to concatenate `__dirname` and `'dist'` into an absolute -path. +When the library consists of multiple files and modules, you may want to bundle these modules to create public releases. Here are some examples for reference: -The `libraryTarget` key configures how the library will be exposed. Setting it to `commonjs` -will result in it being exported using `module.exports`. Additional details available in [the -Webpack docs](https://webpack.js.org/configuration/output/#outputlibrarytarget). +- Using Webpack: [k6-jslib-utils](https://github.com/grafana/k6-jslib-utils) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: [test-commons](https://github.com/grafana/k6-rollup-example/). -The `filename` key, as the name suggests, configures the name of the finished bundles. In this -example, the [template string](https://webpack.js.org/configuration/output/#template-strings) `[name]` -is used to add a dynamic part to the output filename. +Be aware that k6 automatically executes remote modules, making it crucial to trust the source code of these remote modules. There is a **risk of altering the remote modules with certain hosting mechanisms**. To mitigate this security risk, some users prefer to download and import the modules locally to ensure full control of the source code. -#### Adding a bundle command +**As local modules** -Open the `package.json` file and add a new script entry, used for running the bundling process. +In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: -```diff -{ - "name": "bundling-example", - "description": "", - "version": "0.1.0", - "private": true, - "scripts": { -+ "bundle": "webpack" - } - ... -} -``` - -### Running the bundling - -Running webpack will now output two different test bundles, that may be executed independently: - -{{< code >}} - -```bash -$ npm run bundle -# ... -$ tree dist - -dist -├── login.bundle.js -└── signup.bundle.js +```javascript +import { WorkloadConfig, sayHello } from './libs/test-commons.js'; -0 directories, 2 files +import { randomIntBetween, randomItem } from './libs/k6-utils.js'; ``` -{{< /code >}} +Another option to distribute libraries is to use a package manager tool like npm, which enables version locking and the linking of local libraries. The latter can be useful during development. -### Running the tests +Although k6 does not resolve node modules, you can utilize a Bundler to load npm dependencies, as shown in the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -{{< code >}} - -```bash -$ npm run bundle -# ... -$ k6 run dist/login.bundle.js -# ... -``` +## Using TypeScript -{{< /code >}} +k6 does not natively support TypeScript. If you wish to write k6 tests in Typescript, you will need a bundler, as demonstrated in the previous examples: -{{< code >}} +- Using Webpack: Refer to [k6-template-typescript](https://github.com/grafana/k6-template-typescript) and [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws). +- Using Rollup: Apply the [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/master/packages/typescript) to the [k6-rollup-example](https://github.com/grafana/k6-rollup-example). -```bash -$ npm run bundle -# ... -$ k6 run dist/signup.bundle.js \ - --vus 10 \ - --duration 10s -# ... -``` +## Using modules with Docker -{{< /code >}} +Built-in and remote modules work out of the box when running k6 in a Docker container like the [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6). -## Using local modules with Docker +### Local modules -When running k6 in a Docker container you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/), so that k6 can see all the JS modules it needs to import. +To run k6 with Docker and import a local module, you must make sure to mount the necessary folders from the host into the container, using [Docker volumes](https://docs.docker.com/engine/admin/volumes/volumes/). Thus, k6 can see all the JS modules it needs to import. For example, say you have the following structure on your host machine: @@ -380,11 +201,42 @@ $ docker run --rm -v /home/k6/example/src:/src -i grafana/k6 run /src/index.js {{< /code >}} Note that on Windows, you also need to make sure that your drive in question, say `C:\`, -has been marked for sharing in the Docker settings: +has been marked for sharing in the Docker Desktop settings. + +### Extension modules -![Running k6 in docker on Windows](/media/docs/k6-oss/running-k6-in-docker-on-windows.png) +The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. + +To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. + +```bash +# Stage 1 - download xk6 and desired extensions, then compile a new binary. +FROM golang:1.20-alpine3.18 as builder +WORKDIR $GOPATH/src/go.k6.io/k6 +COPY . . +RUN apk --no-cache add git=~2 +RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ + && CGO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-output-prometheus-remote=. \ + --output /tmp/k6 + +# Stage 2 - Copy our custom k6 for use within a minimal linux image. +FROM alpine:3.18 +RUN apk add --no-cache ca-certificates && \ + adduser -D -u 12345 -g 12345 k6 +COPY --from=builder /tmp/k6 /usr/bin/k6 + +USER 12345 +WORKDIR /home/k6 + +ENTRYPOINT ["k6"] +``` ## Read more -- [ES6 template](https://github.com/k6io/template-es6): a scaffolding project to use ES6 in your k6 scripts. -- [TypeScript template](https://github.com/k6io/template-typescript): a scaffolding project to use TypeScript in your k6 scripts. +- [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. +- [Extensions directory](https://grafana.com/docs/k6//extensions/explore): A collection of k6 extensions maintained by Grafana Labs and the community. +- [k6-rollup-example](https://github.com/grafana/k6-rollup-example): Example using Rollup and Babel to bundle a common library and testing suite. +- [k6-template-es6](https://github.com/grafana/k6-template-es6): Template using Webpack and Babel to bundle k6 tests into CommonJS modules and polyfill ES+ features. +- [k6-template-typescript](https://github.com/grafana/k6-template-typescript): Template using Webpack and Babel to use TypeScript in your k6 scripts. +- [JavaScript Compatibility Mode](https://grafana.com/docs/k6//using-k6/javascript-compatibility-mode): An option to change the ECMAScript version supported by k6. From 235329fe9486fdb15617ad302829805f236823eb Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:09 +0100 Subject: [PATCH 04/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 29b57dc23b..e5e77618a8 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -16,7 +16,7 @@ You can write k6 scripts in various ECMAScript versions: k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. -Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: +To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. The process is as follows: ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) From 7fabd0922e54867f0dd47a53b66b268ad475488e Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:14 +0100 Subject: [PATCH 05/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index e5e77618a8..9576cb1de3 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -20,7 +20,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: +When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. From 2a6e2e939d0416d171696875ffc1cc3df7259ed0 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:32 +0100 Subject: [PATCH 06/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 9576cb1de3..f5eb777892 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -22,7 +22,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: -- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. When running tests, you can change the mode through the `--compatibility-mode` option: From 43c7cf0a65f83094f65e2ff6c8a14c93df47e7bb Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:37 +0100 Subject: [PATCH 07/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index f5eb777892..17fedbba7c 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -25,7 +25,7 @@ When executing large scripts, the k6 Babel transformation can slightly delay the - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. -When running tests, you can change the mode through the `--compatibility-mode` option: +When running tests, you can change the mode by using the `--compatibility-mode` option: | Env | CLI | Code / Config file | Default | | ----------------------- | ---------------------- | ------------------ | ------------ | From ba310cbb826364e56a82cb6d13d5a9a01eaac16e Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:43 +0100 Subject: [PATCH 08/21] Update docs/sources/next/using-k6/modules.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index 49db2ff989..e4770ab2f3 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -102,7 +102,7 @@ export default function () { } ``` -How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written in Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. That allows you to build your modules in Go code and import them as JavaScript as usual. To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). From 877a7087a88a45cc6987c14bc31efc7b69b20265 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:51 +0100 Subject: [PATCH 09/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 17fedbba7c..4b067f595f 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -37,7 +37,7 @@ By default, k6 uses the `--compatibility-mode=extended` mode: {{< code >}} -```default +```bash $ k6 run script.js ``` From f50eb3dcdaa95e48f01e799434e6d9a1286ec62c Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:56:59 +0100 Subject: [PATCH 10/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 4b067f595f..e075dfd60b 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -61,7 +61,7 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. +The base mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features or were previously transformed by Babel. In general, this mode is not recommended as it offers minor benefits in reducing startup time. From d691a7e98ac227617f47587c1bddebc193940737 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:57:07 +0100 Subject: [PATCH 11/21] Update docs/sources/next/using-k6/javascript-compatibility-mode.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index e075dfd60b..294724869f 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -63,7 +63,7 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js The base mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features or were previously transformed by Babel. -In general, this mode is not recommended as it offers minor benefits in reducing startup time. +Generally, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example From c5c1edd1673b4525c11f3b0cea0bdab3ca2e5a33 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:57:12 +0100 Subject: [PATCH 12/21] Update docs/sources/next/using-k6/modules.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index e4770ab2f3..b96c99ef74 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -108,7 +108,7 @@ To learn more about using or creating k6 extensions, refer to the [Extension doc ## Sharing JavaScript modules -As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. +As mentioned previously, users can import custom JavaScript libraries by loading either local or remote modules. Because of that, we have two options to import JavaScript modules, along with various methods to distribute them. > The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. From 20b2c5367bcb0a36058d429436ab70d20d6c5250 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:57:22 +0100 Subject: [PATCH 13/21] Update docs/sources/next/using-k6/modules.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index b96c99ef74..65209d4bbb 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js From a19b16d43a77f9db4577ed7a9f3afdad285d8733 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:57:32 +0100 Subject: [PATCH 14/21] Update docs/sources/next/using-k6/modules.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/modules.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index 65209d4bbb..6180159659 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -110,7 +110,11 @@ To learn more about using or creating k6 extensions, refer to the [Extension doc As mentioned previously, users can import custom JavaScript libraries by loading either local or remote modules. Because of that, we have two options to import JavaScript modules, along with various methods to distribute them. -> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. +{{< admonition type="note" >}} + +The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. + +{{< /admonition >}} **As remote modules** From ff0175557dfb27ab061e422ffa9b074bf7db7c8a Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:57:36 +0100 Subject: [PATCH 15/21] Update docs/sources/next/using-k6/modules.md Co-authored-by: Heitor Tashiro Sergent --- docs/sources/next/using-k6/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index 6180159659..8c1c3899b0 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -140,7 +140,7 @@ Be aware that k6 automatically executes remote modules, making it crucial to tru **As local modules** -In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: +In this example, the previous remote modules have been downloaded to the `lib` folder of the testing project and imported as follows: ```javascript import { WorkloadConfig, sayHello } from './libs/test-commons.js'; From 3ea11fe9f3c3b8a67c43efdbff132d1f5ec74ed4 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 7 Feb 2024 13:04:50 +0100 Subject: [PATCH 16/21] Port Heitor changes to previous versions --- .../using-k6/javascript-compatibility-mode.md | 14 +++++++------- docs/sources/v0.47.x/using-k6/modules.md | 14 +++++++++----- .../using-k6/javascript-compatibility-mode.md | 14 +++++++------- docs/sources/v0.48.x/using-k6/modules.md | 14 +++++++++----- .../using-k6/javascript-compatibility-mode.md | 14 +++++++------- docs/sources/v0.49.x/using-k6/modules.md | 14 +++++++++----- 6 files changed, 48 insertions(+), 36 deletions(-) diff --git a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md index 29b57dc23b..294724869f 100644 --- a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md @@ -16,16 +16,16 @@ You can write k6 scripts in various ECMAScript versions: k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. -Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: +To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. The process is as follows: ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: +When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: -- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. -When running tests, you can change the mode through the `--compatibility-mode` option: +When running tests, you can change the mode by using the `--compatibility-mode` option: | Env | CLI | Code / Config file | Default | | ----------------------- | ---------------------- | ------------------ | ------------ | @@ -37,7 +37,7 @@ By default, k6 uses the `--compatibility-mode=extended` mode: {{< code >}} -```default +```bash $ k6 run script.js ``` @@ -61,9 +61,9 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. +The base mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features or were previously transformed by Babel. -In general, this mode is not recommended as it offers minor benefits in reducing startup time. +Generally, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example diff --git a/docs/sources/v0.47.x/using-k6/modules.md b/docs/sources/v0.47.x/using-k6/modules.md index 49db2ff989..8c1c3899b0 100644 --- a/docs/sources/v0.47.x/using-k6/modules.md +++ b/docs/sources/v0.47.x/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -102,15 +102,19 @@ export default function () { } ``` -How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written in Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. That allows you to build your modules in Go code and import them as JavaScript as usual. To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). ## Sharing JavaScript modules -As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. +As mentioned previously, users can import custom JavaScript libraries by loading either local or remote modules. Because of that, we have two options to import JavaScript modules, along with various methods to distribute them. -> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. +{{< admonition type="note" >}} + +The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. + +{{< /admonition >}} **As remote modules** @@ -136,7 +140,7 @@ Be aware that k6 automatically executes remote modules, making it crucial to tru **As local modules** -In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: +In this example, the previous remote modules have been downloaded to the `lib` folder of the testing project and imported as follows: ```javascript import { WorkloadConfig, sayHello } from './libs/test-commons.js'; diff --git a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md index 29b57dc23b..294724869f 100644 --- a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md @@ -16,16 +16,16 @@ You can write k6 scripts in various ECMAScript versions: k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. -Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: +To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. The process is as follows: ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: +When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: -- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. -When running tests, you can change the mode through the `--compatibility-mode` option: +When running tests, you can change the mode by using the `--compatibility-mode` option: | Env | CLI | Code / Config file | Default | | ----------------------- | ---------------------- | ------------------ | ------------ | @@ -37,7 +37,7 @@ By default, k6 uses the `--compatibility-mode=extended` mode: {{< code >}} -```default +```bash $ k6 run script.js ``` @@ -61,9 +61,9 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. +The base mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features or were previously transformed by Babel. -In general, this mode is not recommended as it offers minor benefits in reducing startup time. +Generally, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example diff --git a/docs/sources/v0.48.x/using-k6/modules.md b/docs/sources/v0.48.x/using-k6/modules.md index 49db2ff989..8c1c3899b0 100644 --- a/docs/sources/v0.48.x/using-k6/modules.md +++ b/docs/sources/v0.48.x/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -102,15 +102,19 @@ export default function () { } ``` -How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written in Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. That allows you to build your modules in Go code and import them as JavaScript as usual. To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). ## Sharing JavaScript modules -As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. +As mentioned previously, users can import custom JavaScript libraries by loading either local or remote modules. Because of that, we have two options to import JavaScript modules, along with various methods to distribute them. -> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. +{{< admonition type="note" >}} + +The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. + +{{< /admonition >}} **As remote modules** @@ -136,7 +140,7 @@ Be aware that k6 automatically executes remote modules, making it crucial to tru **As local modules** -In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: +In this example, the previous remote modules have been downloaded to the `lib` folder of the testing project and imported as follows: ```javascript import { WorkloadConfig, sayHello } from './libs/test-commons.js'; diff --git a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md index 29b57dc23b..294724869f 100644 --- a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md @@ -16,16 +16,16 @@ You can write k6 scripts in various ECMAScript versions: k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. -Yet, to enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. This process is as follows: +To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to transform ESM to CommonJS. The process is as follows: ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -The k6 Babel transformation may slightly delay the startup for executing large scripts. Thus, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript Compatibility modes: +When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: -- [Extended mode](#extended-mode): The default, supporting ESM and most ES6+ features. +- [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. -When running tests, you can change the mode through the `--compatibility-mode` option: +When running tests, you can change the mode by using the `--compatibility-mode` option: | Env | CLI | Code / Config file | Default | | ----------------------- | ---------------------- | ------------------ | ------------ | @@ -37,7 +37,7 @@ By default, k6 uses the `--compatibility-mode=extended` mode: {{< code >}} -```default +```bash $ k6 run script.js ``` @@ -61,9 +61,9 @@ $ K6_COMPATIBILITY_MODE=base k6 run script.js {{< /code >}} -This mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features, or were previously transformed by Babel. +The base mode omits the Babel transformation step, supporting only ES5.1+ code. You may want to enable this mode if your scripts are already written using only ES5.1 features or were previously transformed by Babel. -In general, this mode is not recommended as it offers minor benefits in reducing startup time. +Generally, this mode is not recommended as it offers minor benefits in reducing startup time. ### CommonJS Example diff --git a/docs/sources/v0.49.x/using-k6/modules.md b/docs/sources/v0.49.x/using-k6/modules.md index 49db2ff989..8c1c3899b0 100644 --- a/docs/sources/v0.49.x/using-k6/modules.md +++ b/docs/sources/v0.49.x/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and does not support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js @@ -102,15 +102,19 @@ export default function () { } ``` -How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. Thus, you can build your modules in Go code and import them as JavaScript as usual. +How do k6 extensions (Go-to-JS modules) work? For enhanced performance, the k6 engine is written in Go and embeds a JavaScript VM ([goja](https://github.com/dop251/goja)) to execute JavaScript test code. That allows you to build your modules in Go code and import them as JavaScript as usual. To learn more about using or creating k6 extensions, refer to the [Extension documentation](https://grafana.com/docs/k6//extensions). ## Sharing JavaScript modules -As mentioned previously, users can import custom Javascript libraries by loading either local or remote modules. Thus, we have two options to import JavaScript modules, along with various methods to distributed them. +As mentioned previously, users can import custom JavaScript libraries by loading either local or remote modules. Because of that, we have two options to import JavaScript modules, along with various methods to distribute them. -> The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. +{{< admonition type="note" >}} + +The following options for distributing and sharing JavaScript libraries are available for both custom and other public libraries. + +{{< /admonition >}} **As remote modules** @@ -136,7 +140,7 @@ Be aware that k6 automatically executes remote modules, making it crucial to tru **As local modules** -In this example, we've downloaded the previous remote modules in the `lib` folder of the testing project and imported them as follows: +In this example, the previous remote modules have been downloaded to the `lib` folder of the testing project and imported as follows: ```javascript import { WorkloadConfig, sayHello } from './libs/test-commons.js'; From 09e692537ac3c25488ca3049a95309ef1b0fa574 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 14 Feb 2024 08:51:37 +0100 Subject: [PATCH 17/21] Remove mention about improving startup time --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 2 +- docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md | 2 +- docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md | 2 +- docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index 294724869f..c1c38a89fb 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -20,7 +20,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: +Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. diff --git a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md index 294724869f..c1c38a89fb 100644 --- a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md @@ -20,7 +20,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: +Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. diff --git a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md index 294724869f..c1c38a89fb 100644 --- a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md @@ -20,7 +20,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: +Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. diff --git a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md index 294724869f..c1c38a89fb 100644 --- a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md @@ -20,7 +20,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to ![Babel transformation in k6](/media/docs/k6-oss/diagram-grafana-k6-babel-pipeline.png) -When executing large scripts, the k6 Babel transformation can slightly delay the startup time. Because of that, some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: +Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. - [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. From 8a367ab803b7364a29eba76e813c9fea17c79a4a Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 14 Feb 2024 09:06:47 +0100 Subject: [PATCH 18/21] Correct the Babel polyfill features --- docs/sources/next/using-k6/javascript-compatibility-mode.md | 6 +++--- .../v0.47.x/using-k6/javascript-compatibility-mode.md | 6 +++--- .../v0.48.x/using-k6/javascript-compatibility-mode.md | 6 +++--- .../v0.49.x/using-k6/javascript-compatibility-mode.md | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/sources/next/using-k6/javascript-compatibility-mode.md b/docs/sources/next/using-k6/javascript-compatibility-mode.md index c1c38a89fb..fa0d8ac68e 100644 --- a/docs/sources/next/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/next/using-k6/javascript-compatibility-mode.md @@ -12,7 +12,7 @@ weight: 19 You can write k6 scripts in various ECMAScript versions: - ES6+ JavaScript with ES modules (ESM). -- Plain old JavaScript (ES5.1+) with CommonJS modules. +- ES6+ JavaScript with CommonJS modules. k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. @@ -23,7 +23,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. -- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. +- [Base mode](#base-mode): Limited to CommonJS, excluding the Babel step. When running tests, you can change the mode by using the `--compatibility-mode` option: @@ -45,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. +Currently, the k6 Babel transformation only adds ESM support and sets `global` (node's global variable) with the value of `globalThis`. ## Base mode diff --git a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md index c1c38a89fb..fa0d8ac68e 100644 --- a/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.47.x/using-k6/javascript-compatibility-mode.md @@ -12,7 +12,7 @@ weight: 19 You can write k6 scripts in various ECMAScript versions: - ES6+ JavaScript with ES modules (ESM). -- Plain old JavaScript (ES5.1+) with CommonJS modules. +- ES6+ JavaScript with CommonJS modules. k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. @@ -23,7 +23,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. -- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. +- [Base mode](#base-mode): Limited to CommonJS, excluding the Babel step. When running tests, you can change the mode by using the `--compatibility-mode` option: @@ -45,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. +Currently, the k6 Babel transformation only adds ESM support and sets `global` (node's global variable) with the value of `globalThis`. ## Base mode diff --git a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md index c1c38a89fb..fa0d8ac68e 100644 --- a/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.48.x/using-k6/javascript-compatibility-mode.md @@ -12,7 +12,7 @@ weight: 19 You can write k6 scripts in various ECMAScript versions: - ES6+ JavaScript with ES modules (ESM). -- Plain old JavaScript (ES5.1+) with CommonJS modules. +- ES6+ JavaScript with CommonJS modules. k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. @@ -23,7 +23,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. -- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. +- [Base mode](#base-mode): Limited to CommonJS, excluding the Babel step. When running tests, you can change the mode by using the `--compatibility-mode` option: @@ -45,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. +Currently, the k6 Babel transformation only adds ESM support and sets `global` (node's global variable) with the value of `globalThis`. ## Base mode diff --git a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md index c1c38a89fb..fa0d8ac68e 100644 --- a/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md +++ b/docs/sources/v0.49.x/using-k6/javascript-compatibility-mode.md @@ -12,7 +12,7 @@ weight: 19 You can write k6 scripts in various ECMAScript versions: - ES6+ JavaScript with ES modules (ESM). -- Plain old JavaScript (ES5.1+) with CommonJS modules. +- ES6+ JavaScript with CommonJS modules. k6 supports both module types and most ES6+ features in all k6 execution modes: local, distributed, and cloud. @@ -23,7 +23,7 @@ To enable ES module support, k6 uses [Babel](https://babeljs.io/) internally to Some users prefer to bundle their test code outside k6. For this reason, k6 offers two JavaScript compatibility modes: - [Extended mode](#extended-mode): The default option, supporting ESM and most ES6+ features. -- [Base mode](#base-mode): Limited to plain old JavaScript (ES5.1) and CommonJS, excluding the Babel step. +- [Base mode](#base-mode): Limited to CommonJS, excluding the Babel step. When running tests, you can change the mode by using the `--compatibility-mode` option: @@ -45,7 +45,7 @@ $ k6 run script.js As illustrated in the previous diagram, if k6 detects unsupported ES+ features while parsing the test script, it then transforms the script with Babel to polyfill the unsupported features. -This k6 Babel transformation enables the k6 JavaScript VM to execute the test. +Currently, the k6 Babel transformation only adds ESM support and sets `global` (node's global variable) with the value of `globalThis`. ## Base mode From 95fb2e43a1cb2d81d37285d54a80c093594fd320 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:02:32 +0100 Subject: [PATCH 19/21] Update `Extension modules` instructions --- docs/sources/next/using-k6/modules.md | 32 ++++++++---------------- docs/sources/v0.47.x/using-k6/modules.md | 32 ++++++++---------------- docs/sources/v0.48.x/using-k6/modules.md | 32 ++++++++---------------- docs/sources/v0.49.x/using-k6/modules.md | 32 ++++++++---------------- 4 files changed, 44 insertions(+), 84 deletions(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index 8c1c3899b0..70d561bc01 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -211,31 +211,21 @@ has been marked for sharing in the Docker Desktop settings. The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. -To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. +To run k6 with extensions in Docker, create a Docker image that includes the k6 binary with any extension you may want to use. Define a `Dockerfile` with the necessary [xk6 build](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) instructions as follows: ```bash -# Stage 1 - download xk6 and desired extensions, then compile a new binary. -FROM golang:1.20-alpine3.18 as builder -WORKDIR $GOPATH/src/go.k6.io/k6 -COPY . . -RUN apk --no-cache add git=~2 -RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ - && CGO_ENABLED=0 xk6 build \ - --with github.com/grafana/xk6-output-prometheus-remote=. \ - --output /tmp/k6 - -# Stage 2 - Copy our custom k6 for use within a minimal linux image. -FROM alpine:3.18 -RUN apk add --no-cache ca-certificates && \ - adduser -D -u 12345 -g 12345 k6 -COPY --from=builder /tmp/k6 /usr/bin/k6 - -USER 12345 -WORKDIR /home/k6 - -ENTRYPOINT ["k6"] +FROM grafana/xk6:latest + +RUN GCO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-kubernetes@latest + +ENTRYPOINT ["./k6"] ``` +After building your custom k6 Docker image, you can [run k6 with Docker](https://grafana.com/docs/k6//get-started/running-k6/) as usual. + +Alternatively, you can implement a multistage Dockerfile build such as shown on this [Dockerfile example](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile). + ## Read more - [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. diff --git a/docs/sources/v0.47.x/using-k6/modules.md b/docs/sources/v0.47.x/using-k6/modules.md index 8c1c3899b0..70d561bc01 100644 --- a/docs/sources/v0.47.x/using-k6/modules.md +++ b/docs/sources/v0.47.x/using-k6/modules.md @@ -211,31 +211,21 @@ has been marked for sharing in the Docker Desktop settings. The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. -To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. +To run k6 with extensions in Docker, create a Docker image that includes the k6 binary with any extension you may want to use. Define a `Dockerfile` with the necessary [xk6 build](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) instructions as follows: ```bash -# Stage 1 - download xk6 and desired extensions, then compile a new binary. -FROM golang:1.20-alpine3.18 as builder -WORKDIR $GOPATH/src/go.k6.io/k6 -COPY . . -RUN apk --no-cache add git=~2 -RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ - && CGO_ENABLED=0 xk6 build \ - --with github.com/grafana/xk6-output-prometheus-remote=. \ - --output /tmp/k6 - -# Stage 2 - Copy our custom k6 for use within a minimal linux image. -FROM alpine:3.18 -RUN apk add --no-cache ca-certificates && \ - adduser -D -u 12345 -g 12345 k6 -COPY --from=builder /tmp/k6 /usr/bin/k6 - -USER 12345 -WORKDIR /home/k6 - -ENTRYPOINT ["k6"] +FROM grafana/xk6:latest + +RUN GCO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-kubernetes@latest + +ENTRYPOINT ["./k6"] ``` +After building your custom k6 Docker image, you can [run k6 with Docker](https://grafana.com/docs/k6//get-started/running-k6/) as usual. + +Alternatively, you can implement a multistage Dockerfile build such as shown on this [Dockerfile example](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile). + ## Read more - [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. diff --git a/docs/sources/v0.48.x/using-k6/modules.md b/docs/sources/v0.48.x/using-k6/modules.md index 8c1c3899b0..70d561bc01 100644 --- a/docs/sources/v0.48.x/using-k6/modules.md +++ b/docs/sources/v0.48.x/using-k6/modules.md @@ -211,31 +211,21 @@ has been marked for sharing in the Docker Desktop settings. The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. -To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. +To run k6 with extensions in Docker, create a Docker image that includes the k6 binary with any extension you may want to use. Define a `Dockerfile` with the necessary [xk6 build](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) instructions as follows: ```bash -# Stage 1 - download xk6 and desired extensions, then compile a new binary. -FROM golang:1.20-alpine3.18 as builder -WORKDIR $GOPATH/src/go.k6.io/k6 -COPY . . -RUN apk --no-cache add git=~2 -RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ - && CGO_ENABLED=0 xk6 build \ - --with github.com/grafana/xk6-output-prometheus-remote=. \ - --output /tmp/k6 - -# Stage 2 - Copy our custom k6 for use within a minimal linux image. -FROM alpine:3.18 -RUN apk add --no-cache ca-certificates && \ - adduser -D -u 12345 -g 12345 k6 -COPY --from=builder /tmp/k6 /usr/bin/k6 - -USER 12345 -WORKDIR /home/k6 - -ENTRYPOINT ["k6"] +FROM grafana/xk6:latest + +RUN GCO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-kubernetes@latest + +ENTRYPOINT ["./k6"] ``` +After building your custom k6 Docker image, you can [run k6 with Docker](https://grafana.com/docs/k6//get-started/running-k6/) as usual. + +Alternatively, you can implement a multistage Dockerfile build such as shown on this [Dockerfile example](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile). + ## Read more - [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. diff --git a/docs/sources/v0.49.x/using-k6/modules.md b/docs/sources/v0.49.x/using-k6/modules.md index 8c1c3899b0..70d561bc01 100644 --- a/docs/sources/v0.49.x/using-k6/modules.md +++ b/docs/sources/v0.49.x/using-k6/modules.md @@ -211,31 +211,21 @@ has been marked for sharing in the Docker Desktop settings. The official [Grafana k6 Docker image](https://hub.docker.com/r/grafana/k6) includes the k6 release binary but lacks additional k6 extensions. Therefore, using the official Docker container to run a k6 test that requires an extension will fail. -To run k6 with any extension in Docker, you must create a custom Docker image that includes the k6 binary with the necessary extensions. To learn building a Docker image with k6 and extensions, refer to the [xk6 command](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) and this [Dockerfile](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile) example. +To run k6 with extensions in Docker, create a Docker image that includes the k6 binary with any extension you may want to use. Define a `Dockerfile` with the necessary [xk6 build](https://grafana.com/docs/k6//extensions/build-k6-binary-using-go#breaking-down-the-xk6-command) instructions as follows: ```bash -# Stage 1 - download xk6 and desired extensions, then compile a new binary. -FROM golang:1.20-alpine3.18 as builder -WORKDIR $GOPATH/src/go.k6.io/k6 -COPY . . -RUN apk --no-cache add git=~2 -RUN CGO_ENABLED=0 go install go.k6.io/xk6/cmd/xk6@latest \ - && CGO_ENABLED=0 xk6 build \ - --with github.com/grafana/xk6-output-prometheus-remote=. \ - --output /tmp/k6 - -# Stage 2 - Copy our custom k6 for use within a minimal linux image. -FROM alpine:3.18 -RUN apk add --no-cache ca-certificates && \ - adduser -D -u 12345 -g 12345 k6 -COPY --from=builder /tmp/k6 /usr/bin/k6 - -USER 12345 -WORKDIR /home/k6 - -ENTRYPOINT ["k6"] +FROM grafana/xk6:latest + +RUN GCO_ENABLED=0 xk6 build \ + --with github.com/grafana/xk6-kubernetes@latest + +ENTRYPOINT ["./k6"] ``` +After building your custom k6 Docker image, you can [run k6 with Docker](https://grafana.com/docs/k6//get-started/running-k6/) as usual. + +Alternatively, you can implement a multistage Dockerfile build such as shown on this [Dockerfile example](https://github.com/grafana/xk6-output-prometheus-remote/blob/main/Dockerfile). + ## Read more - [JSLib](https://grafana.com/docs/k6//javascript-api/jslib): A collection of k6 JavaScript libraries maintained by Grafana Labs and available as remote modules. From 174751f961ad6884c74f987ff5e3126e1d1182d7 Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:03:08 +0100 Subject: [PATCH 20/21] Update docs/sources/next/using-k6/modules.md Co-authored-by: Olha Yevtushenko --- docs/sources/next/using-k6/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/next/using-k6/modules.md b/docs/sources/next/using-k6/modules.md index 70d561bc01..c7f7b6b1d1 100644 --- a/docs/sources/next/using-k6/modules.md +++ b/docs/sources/next/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **browser-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js From 3808deac2a038c83341bb1ef757d88348abe0965 Mon Sep 17 00:00:00 2001 From: Heitor Tashiro Sergent Date: Wed, 14 Feb 2024 10:14:26 -0600 Subject: [PATCH 21/21] Fix brower typo --- docs/sources/v0.47.x/using-k6/modules.md | 2 +- docs/sources/v0.48.x/using-k6/modules.md | 2 +- docs/sources/v0.49.x/using-k6/modules.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sources/v0.47.x/using-k6/modules.md b/docs/sources/v0.47.x/using-k6/modules.md index 70d561bc01..c7f7b6b1d1 100644 --- a/docs/sources/v0.47.x/using-k6/modules.md +++ b/docs/sources/v0.47.x/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **browser-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js diff --git a/docs/sources/v0.48.x/using-k6/modules.md b/docs/sources/v0.48.x/using-k6/modules.md index 70d561bc01..c7f7b6b1d1 100644 --- a/docs/sources/v0.48.x/using-k6/modules.md +++ b/docs/sources/v0.48.x/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **browser-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js diff --git a/docs/sources/v0.49.x/using-k6/modules.md b/docs/sources/v0.49.x/using-k6/modules.md index 70d561bc01..c7f7b6b1d1 100644 --- a/docs/sources/v0.49.x/using-k6/modules.md +++ b/docs/sources/v0.49.x/using-k6/modules.md @@ -32,7 +32,7 @@ import http from 'k6/http'; These modules are stored on the local filesystem, and accessed either through relative or absolute filesystem paths. -k6 adopts a **brower-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. +k6 adopts a **browser-like module resolution** and doesn't support [Node.js module resolution](https://nodejs.org/api/modules.html#modules_all_together). File names for `imports` must be fully specified, such as `./helpers.js`. ```javascript //my-test.js