diff --git a/docs/images/tutorials/javascript/js-get-started/js-added-input-element.png b/docs/images/tutorials/javascript/js-get-started/js-added-input-element.png new file mode 100644 index 00000000000..af8c8c47e7a Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-added-input-element.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-continuous-run-config.png b/docs/images/tutorials/javascript/js-get-started/js-continuous-run-config.png new file mode 100644 index 00000000000..b583e6210e5 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-continuous-run-config.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-edit-run-config.png b/docs/images/tutorials/javascript/js-get-started/js-edit-run-config.png new file mode 100644 index 00000000000..21dcf35542d Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-edit-run-config.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-output-gutter-1.png b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-1.png new file mode 100644 index 00000000000..0b28e050003 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-1.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-output-gutter-2.png b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-2.png new file mode 100644 index 00000000000..1b68a395b44 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-2.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-output-gutter-3.png b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-3.png new file mode 100644 index 00000000000..9e61fdbac4d Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-3.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-output-gutter-4.png b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-4.png new file mode 100644 index 00000000000..1fcffee7146 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-4.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-output-gutter-5.png b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-5.png new file mode 100644 index 00000000000..0429e6ef966 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-output-gutter-5.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-run-config.png b/docs/images/tutorials/javascript/js-get-started/js-run-config.png new file mode 100644 index 00000000000..3578c255256 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-run-config.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/js-run-gutter.png b/docs/images/tutorials/javascript/js-get-started/js-run-gutter.png new file mode 100644 index 00000000000..1794cde2c85 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/js-run-gutter.png differ diff --git a/docs/images/tutorials/javascript/js-get-started/load-gradle-changes.png b/docs/images/tutorials/javascript/js-get-started/load-gradle-changes.png new file mode 100644 index 00000000000..e944e16d951 Binary files /dev/null and b/docs/images/tutorials/javascript/js-get-started/load-gradle-changes.png differ diff --git a/docs/images/tutorials/javascript/js-overview/js-get-started-button.svg b/docs/images/tutorials/javascript/js-overview/js-get-started-button.svg new file mode 100644 index 00000000000..051a689ac7a --- /dev/null +++ b/docs/images/tutorials/javascript/js-overview/js-get-started-button.svg @@ -0,0 +1,6 @@ + + + + Get started with Kotlin/JS → + + diff --git a/docs/kr.tree b/docs/kr.tree index a355505abbe..b65eef4868e 100644 --- a/docs/kr.tree +++ b/docs/kr.tree @@ -221,6 +221,7 @@ + diff --git a/docs/topics/js/js-get-started.md b/docs/topics/js/js-get-started.md new file mode 100644 index 00000000000..2bd118d0bf6 --- /dev/null +++ b/docs/topics/js/js-get-started.md @@ -0,0 +1,338 @@ +[//]: # (title: Get started with Kotlin/JS) + +This tutorial demonstrates how to create a Kotlin/JS application targeting a browser. +Choose the tool that works best for you and create your app using: + +* **[The IDE](#in-ide)**. Here, you can clone the project template from a version control system and use it in IntelliJ IDEA. +* **[The Gradle build system](#using-gradle)**. To better understand how things work under the hood, + create build files for your project manually. + +With Kotlin/JS, you can compile for [different environments](js-project-setup.md#execution-environments). + +## In IDE + +In this section, you'll learn how to use IntelliJ IDEA to create a Kotlin/JS application. You can use both +the Community Edition and the Ultimate Edition. + +### Create the project + +1. Download and install the latest version of [IntelliJ IDEA](https://www.jetbrains.com/idea/). +2. [Set up your environment for Kotlin Multiplatform development](https://www.jetbrains.com/help/kotlin-multiplatform-dev/quickstart.html#set-up-the-environment). +3. Clone the [project template](https://github.com/Kotlin/kmp-js-wizard) + by selecting **File** | **New** | **Project from Version Control** in IntelliJ IDEA and using this URL: + + ```none + https://github.com/Kotlin/kmp-js-wizard + ``` + +4. Open the `gradle/libs.versions.toml` file, which is the version catalog for project dependencies. To create Kotlin/JS + applications, you need the Kotlin Multiplatform Gradle plugin, which has the same version as Kotlin. Ensure that you + use the latest Kotlin version: + + ```none + [versions] + kotlin = "%kotlinVersion%" + ``` + +5. Follow the suggestion to reload Gradle files: + + ![Load Gradle changes button](load-gradle-changes.png){width=295} + +For more information about these settings, see the [Multiplatform Gradle DSL reference](https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-dsl-reference.html). + +### Build and run the application + +Open the `Main.kt` file in the `src/jsMain/kotlin/` directory: + +* The `src` directory contains Kotlin source files. +* The `Main.kt` file includes code that renders "Hello, Kotlin/JS!" to the browser page using the [kotlinx.browser](https://github.com/Kotlin/kotlinx-browser) API. + +Press the green icon in the gutter to run the code: + +![Run the application](js-run-gutter.png){width=478} + +IntelliJ IDEA runs the code using the Gradle task and that open application in the browser: + +![Application output](js-output-gutter-1.png){width=331} + +After the first run, the IDE creates the corresponding run configuration at the top: + +![Gradle run configuration](js-run-config.png){width=503} + +> IntelliJ IDEA Ultimate users can use the [JS Debugger](https://www.jetbrains.com/help/idea/configuring-javascript-debugger.html) +> that allows debugging the compiled code directly from IDE + +You can Gradle to re-build your project automatically on changes: + +1. Edit **Gradle run configuration created**. + + ![Gradle edit run configuration](js-edit-run-config.png){width=503} + +2. In the **Run** field, add `--continuous` flag, so the **Run** field value looks like this: + + ![Continuous run configuration](js-continuous-run-config.png){width=503} + +4. Apply the changes. + +Now, when you run the application and make any changes in the class files or save the file (Ctrl + S/Cmd + S), +Gradle automatically performs an incremental build of the project and hot-reloads the browser page with the updated code. + +### Update the application + +Let's add a feature to your application so it can count the number of letters in your name: + +1. In the `Main.kt` file, add code to read the input. To do this, let's create an [HTML input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input) + by declaring the new [extension function](extensions.md#extension-functions): + + ```kotlin + fun Element.appendInput() { + val input = document.createElement("input") + appendChild(input) + } + ``` + +2. Now, we can use this function to add the input to the page + ```kotlin + fun main() { + document.body?.appendInput() + } + ``` + + And our application looks like this: + + ![Application with input element](js-added-input-element.png){width=503} + +3. Then we need to read the input value and assign it to the `name` variable, so let's listen to changes in the input. + To do so, we need to add a listener to the `input` element, inside the `appendInput()` function: + ```kotlin + fun Element.appendInput(onChange: (String) -> Unit = {}) { + val input = document.createElement("input").apply { + addEventListener("change") { event -> + onChange(event.target.unsafeCast().value) + } + } + appendChild(input) + } + ``` + + ```kotlin + fun main() { + // Read the input value. + document.body?.appendInput(onChange = { println(it) }) + } + ``` + +4. Let's add also a text element to show our output. To do this, let's create one more [extension function](extensions.md#extension-functions) + to create a paragraph element: + + ```kotlin + fun Element.appendTextContainer(): Element { + return document.createElement("p").also(::appendChild) + } + ``` + + And call it inside the `main` function: + ```kotlin + fun main() { + // Create a text container for our output. + val output = document.body?.appendTextContainer() + + // Read the input value. + document.body?.appendInput(onChange = { /* ... */ }) + } + + ``` + +5. Eliminate the whitespaces and count the letters: + + * Use the [`replace()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/replace.html) function to remove the + empty spaces in the name. + * Use the scope function [`let`](scope-functions.md#let) to run the function within the object context. + * Use a [string template](strings.md#string-templates) to insert your name length into the string by adding a dollar + sign `$` and enclosing it in curly braces – `${it.length}`. `it` is the default name of a [lambda parameter](coding-conventions.md#lambda-parameters). + + ```kotlin + fun main() { + // Create a text container for our output. + val output = document.body?.appendTextContainer() + + // Read the input value. + document.body?.appendInput(onChange = { name -> + name.replace(" ", "").let { + output?.textContent = "Your name contains ${it.length} letters" + } + }) + } + ``` + +6. Run the application. +7. Put your name, press Enter and enjoy the result: + + ![Application output](js-output-gutter-2.png){width=422} + +As an extra exercise, let's count only the unique letters in your name: + +1. In the `Main.kt` file, declare one more [extension function](extensions.md#extension-functions) + `.countDistinctCharacters()` for `String`: + + * Convert the name to lowercase using the [`.lowercase()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/lowercase.html) function. + * Convert the input string to a list of characters using the [`toList()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/to-list.html) function. + * Select only the distinct characters in your name using the [`distinct()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/distinct.html) function. + * Count the distinct characters using the [`count()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/count.html) function. + + ```kotlin + fun String.countDistinctCharacters() = lowercase().toList().distinct().count() + ``` + +2. Use the `.countDistinctCharacters()` function to count the unique letters in your name: + + ```kotlin + fun String.countDistinctCharacters() = lowercase().toList().distinct().count() + + fun main() { + // Create a text container for our output. + val output = document.body?.appendTextContainer() + + // Read the input value. + document.body?.appendInput(onChange = { name -> + name.replace(" ", "").let { + // Print the number of unique letters. + output?.textContent = "Your name contains ${it.countDistinctCharacters()} unique letters" + } + }) + } + ``` + +3. Run the application. +4. Put your name, press Enter and see the result: + + ![Application output](js-output-gutter-3.png){width=422} + +## Using Gradle + +In this section, you'll learn how to manually create a Kotlin/JS application using [Gradle](https://gradle.org). +It's the default build system for Kotlin/JS and Kotlin Multiplatform projects, which is also commonly used in Java, +Android, and other ecosystems. + +### Create project files + +1. To get started, install a compatible version of [Gradle](https://gradle.org/install/). See the [compatibility table](gradle-configure-project.md#apply-the-plugin) + to check the Kotlin Gradle plugin (KGP) compatibility with available Gradle versions. +2. Create an empty project directory. Inside it, create a `build.gradle(.kts)` file with the following content: + + + + + ```kotlin + // build.gradle.kts + plugins { + kotlin("multiplatform") version "%kotlinVersion%" + } + + repositories { + mavenCentral() + } + + kotlin { + js { + browser() // for running in a browser + // nodejs() // for running in Node.js + binaries.executable() + } + } + ``` + + + + + ```groovy + // build.gradle + plugins { + id 'org.jetbrains.kotlin.multiplatform' version '%kotlinVersion%' + } + + repositories { + mavenCentral() + } + + kotlin { + js { + browser() // for running in a browser + // nodejs() // for running in Node.js + binaries.executable() + } + } + ``` + + + + + You can use different [execution environments](js-project-setup.md#execution-environments), such as `browser` or `nodejs` + to define the environment for which you are compiling your code. + The environment name is used to generate task names in the project. + +3. Create an empty `settings.gradle(.kts)` file in the project directory. +4. Create a `src/jsMain/kotlin` directory and place a `hello.kt` file inside with the following content: + + ```kotlin + fun main() { + println("Hello, Kotlin/JS!") + } + ``` + +5. For the `browser` environment (for `nodjes` this step should be skipped), create also a `src/jsMain/resources/index.html` file with the following content, + and replace the `` placeholder with the name of your project directory: + + ```html + + + + + Application title + + + + + + ``` + +By convention, all sources are located in the `src/[Main|Test]/kotlin` directories, where `Main` is for the +source code and `Test` is for tests. `` corresponds to the target platform (in this case, `js`), +as specified in the build file. + +### Build and run the project + +To run the project, execute the following command from the root project directory, run the build command: + +```bash +gradle jsBrowserDevelopmentRun # for browser +# gradle jsNodeDevelopmentRun # for Node.js +``` + +For `browser` environment, the browser opens the `index.html` file and prints "Hello, Kotlin/JS!" to the browser console (Ctrl + Shift + J/Cmd + Option + J). + +![Application output](js-output-gutter-4.png){width=422} + +If you are using `nodejs` environment, the terminal prints "Hello, Kotlin/JS!" + +![Application output](js-output-gutter-5.png){width=422} + +### Open the project in IDE + +Now, you can open your project in any IDE that supports Gradle. If you use IntelliJ IDEA: + +1. Select **File** | **Open**. +2. Select the project directory and click **Open**. + IntelliJ IDEA automatically detects if it's a Kotlin/JS project. + +If you encounter a problem with the project, IntelliJ IDEA displays the error message in the **Build** tab. + +## What's next? + + + +* Learn how to [debug Kotlin/JS applications](js-debugging.md). +* Learn how to [write and run tests with Kotlin/JS](js-running-tests.md). +* Learn how to [write Gradle build scripts for real-life Kotlin/JS projects](https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-dsl-reference.html). +* Read more about the Gradle build system in the [documentation](gradle.md). \ No newline at end of file diff --git a/docs/topics/js/js-overview.md b/docs/topics/js/js-overview.md index 306b45a13ea..36db571b284 100644 --- a/docs/topics/js/js-overview.md +++ b/docs/topics/js/js-overview.md @@ -85,7 +85,7 @@ Explore the fundamentals and initial steps to start working with Kotlin/JS: useful code snippets and patterns that can help you get started with your projects. * If you’re new to Kotlin/JS, start with the setup guide before exploring more advanced topics: -Set up a Kotlin/JS project +Get started with Kotlin/JS ## Sample projects for Kotlin/JS