首页 > 解决方案 > Webpack 不为​​ Kotlin 多平台 React-JS 应用程序提供服务

问题描述

我正在尝试使用jetbrains 团队的 Kotlin 类型安全包装器为ktor在后端和前端运行的 Kotlin Multiplatform 项目配置模板。react要在前端和后端之间共享代码,我需要使用 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

我认为问题出在自动生成的webpack.config.js . 我在互联网上搜索了一下,发现您可以在项目中包含自己的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

[编辑]

该问题已过时,因为 Intellij IDEA 现在包含用于 kotlin 多平台项目的项目向导。

标签: reactjsgradlekotlinwebpack

解决方案


由于直接在 Intellij IDEA 中引入了 kotlin 多平台项目的项目向导,因此问题似乎已过时

此项目向导生成的模板项目可在此处访问: https ://github.com/jaro2gw/kotlin-multiplatform-full-stack


推荐阅读