Webpack не обслуживает Kotlin Мультиплатформенное приложение React- JS - PullRequest
1 голос
/ 16 февраля 2020

Я пытаюсь настроить шаблон для Kotlin Мультиплатформенного проекта, выполняющего ktor на бэкэнде и react на веб-интерфейсе с Kotlin типобезопасной оболочкой от команды jetbrains. Для совместного использования кода между внешним и внутренним интерфейсом мне нужно использовать gradle

build.gradle.kts:

val kotlin_version: String by project

val ktor_version: String by project
val logback_version: String by project

val annotations_version: String by project

val kotlin_react_version: String by project
val kotlin_react_dom_version: String by project
val kotlin_extensions_version: String by project
val kotlin_css_version: String by project
val kotlin_css_js_version: String by project
val kotlin_styled_version: String by project

val kotlinx_serialization_version: String by project
val kotlinx_html_version: String by project

plugins {
    kotlin("multiplatform") version "1.3.61"
    kotlin("kapt") version "1.3.61"
    kotlin("plugin.serialization") version "1.3.61"
}

apply {
    plugin("kotlin-dce-js")
}

group = "com.jaro2gw"
version = "0.0.1"

repositories {
    mavenCentral()
    mavenLocal()
    maven(url = "https://kotlin.bintray.com/kotlin-eap")
    maven(url = "https://kotlin.bintray.com/js-externals")
    maven(url = "https://kotlin.bintray.com/kotlin-js-wrappers")
    maven(url = "https://dl.bintray.com/kotlinx/kotlinx")
    jcenter()
}


kotlin {
    js("frontend") {
        useCommonJs()
        nodejs()
        browser {
            compilations.all {
                kotlinOptions {
                    metaInfo = true
                    sourceMap = true
                    sourceMapEmbedSources = "always"
                    moduleKind = "commonjs"
                    main = "call"
                }
            }
        }
    }

    jvm("backend")

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(kotlin("stdlib-common"))
            }
        }

        val frontendMain by getting {
            dependsOn(commonMain)
            dependencies {
                implementation(kotlin("stdlib-js", kotlin_version))

                implementation(kotlinDependency("react", kotlin_react_version))
                implementation(kotlinDependency("react-dom", kotlin_react_dom_version))
                implementation(kotlinDependency("extensions", kotlin_extensions_version))
                implementation(kotlinDependency("css", kotlin_css_version))
                implementation(kotlinDependency("css-js", kotlin_css_js_version))
                implementation(kotlinDependency("styled", kotlin_styled_version))

                implementation(kotlinxDependency("html-js", kotlinx_html_version))
                implementation(kotlinxDependency("serialization-runtime-js", kotlinx_serialization_version))

                implementation("org.jetbrains:annotations:$annotations_version")

                implementation(npm("webpack"))
                implementation(npm("webpack-cli"))
                implementation(npm("webpack-dev-server"))

                implementation(npm("react"))
                implementation(npm("react-dom"))
                implementation(npm("react-draggable"))
                implementation(npm("react-list"))
                implementation(npm("react-is"))

                implementation(npm("inline-style-prefixer"))
                implementation(npm("core-js"))
                implementation(npm("styled-components"))
                implementation(npm("jquery"))
            }

        }

        val backendMain by getting {
            dependsOn(commonMain)
            dependencies {
                implementation(kotlin("stdlib-jdk8", kotlin_version))
                implementation(ktorDependency("server-netty"))
                implementation(ktorDependency("server-core"))
                implementation(ktorDependency("locations"))
                implementation(ktorDependency("server-sessions"))
                implementation(ktorDependency("websockets"))
                implementation(ktorDependency("gson"))
                implementation("ch.qos.logback:logback-classic:$logback_version")
            }
        }
    }
}

fun ktorDependency(name: String, version: String = ktor_version) = "io.ktor:ktor-$name:$version"
fun kotlinDependency(name: String, version: String) = "org.jetbrains:kotlin-$name:$version"
fun kotlinxDependency(name: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$name:$version"

gradle.properties:

kotlin.code.style=official

kotlin_version=1.3.61

ktor_version=1.3.0
logback_version=1.2.1

kotlin_react_version=16.9.0-pre.90-kotlin-1.3.61
kotlin_react_dom_version=16.9.0-pre.90-kotlin-1.3.61
kotlin_extensions_version=1.0.1-pre.90-kotlin-1.3.61
kotlin_css_version=1.0.0-pre.90-kotlin-1.3.61
kotlin_css_js_version=1.0.0-pre.90-kotlin-1.3.61
kotlin_styled_version=1.0.0-pre.90-kotlin-1.3.61

annotations_version=16.0.2

kotlinx_serialization_version=0.11.1
kotlinx_html_version=0.6.12

Внешний вид структуры проекта как это:

/src    
    /backendMain (ktor kotlin code)
    /commonMain
        /kotlin
            /model
                >User.kt
    /frontendMain
        /kotlin
            >index.kt
        /resources
            /public
                >index.html
/webpack.config.d
    >webpack.config.js

User.kt

package model

data class User(val ID: Long, val name: String)

index.kt

import kotlinext.js.require
import kotlinext.js.requireAll
import react.dom.render
import kotlin.browser.document
import model.User

fun main() {
    requireAll(require.context("kotlin", true, js("/\\.css$/")))

    val user = User(1, "ReactUser")
    render(document.getElementById("root")) {
        +"Hello, $user!"
    }
}

index.html

<!doctype html>
<html lang="en">
<head>
<!-- some meta information, shortcut icon and title -->
</head>
<body>
<noscript>
    You need to enable JavaScript to run this app.
</noscript>
<div>Hello</div>
<div id="root"></div>
</body>
</html>


webpack.config.js:

path = require("path")

config = config || {};
config.devServer = config.devServer || {};
config.devServer = {
    "hot": true,
    "open": false,
    "port": 3000,
    contentBase: [
        path.resolve(__dirname, "..\\..\\..\\processedResources\\frontend\\main\\public")
    ]
}
config.devServer.proxy = config.devServer.proxy || {};
config.devServer.proxy = {
    "/api": "https://localhost:8080"
}
config.devServer.watchOptions = config.devServer.watchOptions || {};
config.devServer.watchOptions = {
    "aggregateTimeout": 5000,
    "poll": 1000
};

module.exports = {
    entry: {
        main: path.resolve(__dirname, "kotlin\\kotlin-fullstack-mpp-frontend.js")
    }
}

Бэкэнд работает гладко, однако веб-интерфейсу не удается загрузить сгенерированный файл. js (я думаю?).

Ожидаемая страница html при доступе к localhost:3000 должна выглядеть примерно так:

Hello

Hello, (ID=1, name="ReactUser")!

, но я получаю только первые Hello

I думаю, что проблема с автоматически сгенерированным webpack.config.js. Я немного искал inte rnet и обнаружил, что вы можете включить свой собственный файл webpack.config.js в проект. Мне удалось установить contentBase, proxy и другие параметры, но, похоже, не удалось правильно настроить параметр entry.main? Я думаю, что структура проекта также может играть здесь роль. Структура папок build выглядит следующим образом:

/build
    /js
        /node_modules (project dependencies)
        /packages
            /kotlin-fullstack-mpp-frontend
                /kotlin
                    /kotlin-fullstack-mpp-frontend (compiled common code)
                    >kotlin-fullstack-mpp-frontend.js (compiled frontend code)
                /node-modules (not sure what is here)
                >package.json
                >webpack.config.js
        /packages_imported (kotlin wrapper for react)
        >package.json
        >yarn.lock
    /processedResources
        /frontend
            /main
                /public
                    >index.html
    /reports
        /webpack
            /kotlin-fullstack-mpp-frontend
                >webpack.config.evaluated.js

Для создания и запуска приложения реагирования я использую gradlew frontendBrowserRun -t

Весь проект доступен здесь: https://github.com/jaro2gw/kotlin-fullstack-mpp

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...