From 95d33da10d4e4ccc78106426c53f375f9cc2b711 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 28 Mar 2023 14:39:10 +0000 Subject: [PATCH] [Gradle, JS] Watch options ignore kt file to not trigger webpack [Gradle, JS] Webpack prod dist not in default dist dir ^KT-57629 fixed ^KT-57630 fixed --- .../kotlin/gradle/Kotlin2JsGradlePluginIT.kt | 15 ++- .../gradle/KotlinJsLibraryGradlePluginIT.kt | 23 ++-- .../app/build.gradle.kts | 5 +- .../gradle/targets/js/dsl/Distribution.kt | 4 + .../kotlin/gradle/targets/js/ir/JsBinaries.kt | 2 +- .../gradle/targets/js/ir/KotlinBrowserJsIr.kt | 7 +- .../js/subtargets/DefaultDistribution.kt | 3 +- .../targets/js/webpack/KotlinWebpack.kt | 9 +- .../targets/js/webpack/KotlinWebpackConfig.kt | 104 ++++++++---------- 9 files changed, 92 insertions(+), 80 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt index 5f326df9a0e..28dc6297977 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt @@ -12,6 +12,7 @@ import org.gradle.api.logging.LogLevel import org.gradle.testkit.runner.BuildResult import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType +import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution import org.jetbrains.kotlin.gradle.targets.js.ir.KLIB_TYPE import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectModules @@ -361,7 +362,7 @@ class Kotlin2JsIrGradlePluginIT : AbstractKotlin2JsGradlePluginIT(true) { fun testKotlinJsPackageModuleName(gradleVersion: GradleVersion) { project("kotlin-js-package-module-name", gradleVersion) { build("assemble") { - assertFileInProjectExists("build/distributions/kotlin-js-package-module-name.js") + assertFileInProjectExists("build/${Distribution.JS_DIST}/productionExecutable/kotlin-js-package-module-name.js") assertFileInProjectExists("build/js/packages/@foo/bar/kotlin/@foo/bar.js") } } @@ -1147,7 +1148,11 @@ abstract class AbstractKotlin2JsGradlePluginIT(protected val irBackend: Boolean) assertDirectoryInProjectExists("build/js/packages/kotlin-js-browser-lib") assertDirectoryInProjectExists("build/js/packages/kotlin-js-browser-app") - assertFileInProjectExists("app/build/distributions/app.js") + if (irBackend) { + assertFileInProjectExists("app/build/${Distribution.JS_DIST}/productionExecutable/app.js") + } else { + assertFileInProjectExists("app/build/distributions/app.js") + } if (!irBackend) { assertTasksExecuted(":app:processDceKotlinJs") @@ -1169,7 +1174,11 @@ abstract class AbstractKotlin2JsGradlePluginIT(protected val irBackend: Boolean) if (irBackend) ":app:browserProductionExecutableDistributeResources" else ":app:browserDistributeResources" ) - assertFileInProjectExists("app/build/distributions/index.html") + if (irBackend) { + assertFileInProjectExists("app/build/${Distribution.JS_DIST}/productionExecutable/index.html") + } else { + assertFileInProjectExists("app/build/distributions/index.html") + } } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJsLibraryGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJsLibraryGradlePluginIT.kt index f36c3b400e0..890b34f1fad 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJsLibraryGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJsLibraryGradlePluginIT.kt @@ -9,6 +9,7 @@ import com.google.gson.Gson import com.google.gson.JsonObject import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType +import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution.Companion.JS_DIST import org.jetbrains.kotlin.gradle.testbase.* import org.junit.jupiter.api.DisplayName import java.util.zip.ZipFile @@ -31,10 +32,10 @@ abstract class KotlinJsIrLibraryGradlePluginITBase : KGPBaseTest() { fun testSimpleJsBinaryLibrary(gradleVersion: GradleVersion) { project("simple-js-library", gradleVersion) { build("build") { - assertFileInProjectExists("build/productionLibrary/js-library.js") - assertFileInProjectExists("build/productionLibrary/package.json") - assertFileInProjectExists("build/productionLibrary/main.js") - projectPath.resolve("build/productionLibrary/package.json").reader() + assertFileInProjectExists("build/$JS_DIST/productionLibrary/js-library.js") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/package.json") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/main.js") + projectPath.resolve("build/$JS_DIST/productionLibrary/package.json").reader() .use { Gson().fromJson(it, JsonObject::class.java) } .getAsJsonObject("dependencies") ?.entrySet()?.associate { (k, v) -> k to v.asString } @@ -51,9 +52,9 @@ abstract class KotlinJsIrLibraryGradlePluginITBase : KGPBaseTest() { fun testJsBinaryLibraryAndExecutable(gradleVersion: GradleVersion) { project("js-library-with-executable", gradleVersion) { build("build") { - assertFileInProjectExists("build/productionLibrary/js-library.js") - assertFileInProjectExists("build/productionLibrary/package.json") - assertFileInProjectExists("build/productionLibrary/main.js") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/js-library.js") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/package.json") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/main.js") } } } @@ -63,11 +64,11 @@ abstract class KotlinJsIrLibraryGradlePluginITBase : KGPBaseTest() { fun testJsBinaryLibraryAndExecutableForBrowserAndNodejs(gradleVersion: GradleVersion) { project("js-library-with-executable-browser-nodejs", gradleVersion) { build("build") { - assertFileInProjectExists("build/productionLibrary/js-library.js") - assertFileInProjectExists("build/productionLibrary/package.json") - assertFileInProjectExists("build/productionLibrary/main.js") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/js-library.js") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/package.json") + assertFileInProjectExists("build/$JS_DIST/productionLibrary/main.js") - assertFileInProjectExists("build/distributions/js-library.js") + assertFileInProjectExists("build/$JS_DIST/productionExecutable/js-library.js") } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts index 6c16784eaaf..1403ef6bc32 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts @@ -60,11 +60,12 @@ rootProject.plugins.withType() tasks.register("runWebpackResult") { - dependsOn(tasks.named("browserProductionWebpack")) + val webpackTask = tasks.named("browserProductionWebpack") + dependsOn(webpackTask) executable(kotlinNodeJs.requireConfigured().nodeExecutable) - workingDir = File("${buildDir}").resolve("distributions") + workingDir(webpackTask.flatMap { it.outputDirectory.asFile }) args("./${project.name}.js") } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt index 4c108081ac7..b621ebb4932 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt @@ -19,4 +19,8 @@ interface Distribution { var directory: File val outputDirectory: DirectoryProperty + + companion object { + const val JS_DIST = "js-dist" + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt index 52cac6abe3f..159b6adb920 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt @@ -95,7 +95,7 @@ class Executable( override val distribution: Distribution = createDefaultDistribution( compilation.target.project, - if (mode == KotlinJsBinaryMode.PRODUCTION) null else super.distribution.distributionName + super.distribution.distributionName ) val executeTaskBaseName: String = diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt index 4acd47517cc..1068869fa0a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory import org.jetbrains.kotlin.gradle.report.BuildMetricsService import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode @@ -114,7 +113,6 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : binary as Executable val mode = binary.mode - val distsDirectory = project.distsDirectory val archivesName = project.archivesName val runTask = registerSubTargetTask( @@ -125,7 +123,6 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : listOf(compilation) ) { task -> task.dependsOn(binary.linkSyncTask) - task.outputDirectory.convention(distsDirectory).finalizeValueOnRead() task.args.add(0, "serve") task.description = "start ${mode.name.toLowerCaseAsciiOnly()} webpack dev server" @@ -145,6 +142,10 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : ) ) + task.watchOptions = KotlinWebpackConfig.WatchOptions( + ignored = arrayOf("*.kt") + ) + task.doNotTrackStateCompat("Tracked by external webpack tool") diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt index 597808a81b7..790762379db 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt @@ -10,6 +10,7 @@ import org.gradle.api.file.DirectoryProperty import org.gradle.api.provider.Property import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution +import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution.Companion.JS_DIST import org.jetbrains.kotlin.gradle.utils.property import java.io.File @@ -42,6 +43,6 @@ class DefaultDistribution( } override val outputDirectory: DirectoryProperty = project.objects.directoryProperty().convention( - distributionName.flatMap { project.layout.buildDirectory.dir(it) }.orElse(project.distsDirectory) + distributionName.flatMap { project.layout.buildDirectory.dir("$JS_DIST/$it") }.orElse(project.distsDirectory) ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt index 850720a1ff4..38dc381279d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporterImpl import org.jetbrains.kotlin.build.report.metrics.BuildPerformanceMetric import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType -import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService @@ -34,7 +33,6 @@ import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webpackRulesContainer -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject @@ -148,6 +146,7 @@ constructor( } @get:OutputDirectory + @get:Optional abstract val outputDirectory: DirectoryProperty @get:Internal @@ -195,6 +194,10 @@ constructor( @Optional var devServer: KotlinWebpackConfig.DevServer? = null + @Input + @Optional + var watchOptions: KotlinWebpackConfig.WatchOptions? = null + @Input var devtool: String = WebpackDevtool.EVAL_SOURCE_MAP @@ -223,7 +226,7 @@ constructor( mode = mode, entry = if (forNpmDependencies) null else entry.get().asFile, output = output, - outputPath = if (forNpmDependencies) null else outputDirectory.get().asFile, + outputPath = if (forNpmDependencies) null else outputDirectory.getOrNull()?.asFile, outputFileName = mainOutputFileName.get(), configDirectory = configDirectory, rules = rules, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt index 91efa050a4f..e2356ba03b7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt @@ -8,11 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.js.webpack import com.google.gson.GsonBuilder -import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer -import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Provider -import org.gradle.api.tasks.* -import org.gradle.work.NormalizeLineEndings import org.jetbrains.kotlin.gradle.targets.js.NpmVersions import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir @@ -27,66 +23,34 @@ import java.io.StringWriter @Suppress("MemberVisibilityCanBePrivate") data class KotlinWebpackConfig( - @Internal val npmProjectDir: Provider? = null, - @Input var mode: Mode = Mode.DEVELOPMENT, - @Internal var entry: File? = null, - @Nested - @Optional var output: KotlinWebpackOutput? = null, - @Internal var outputPath: File? = null, - @Input - @Optional var outputFileName: String? = entry?.name, - @get:PathSensitive(PathSensitivity.NAME_ONLY) - @get:Optional - @get:IgnoreEmptyDirectories - @get:NormalizeLineEndings - @get:InputDirectory var configDirectory: File? = null, - @Internal var reportEvaluatedConfigFile: File? = null, - @Input - @Optional var devServer: DevServer? = null, - @Input + var watchOptions: WatchOptions? = null, var experiments: MutableSet = mutableSetOf(), - @Nested override val rules: KotlinWebpackRulesContainer, - @Input - @Optional var devtool: String? = WebpackDevtool.EVAL_SOURCE_MAP, - @Input var showProgress: Boolean = false, var optimization: Optimization? = null, - @Input var sourceMaps: Boolean = false, - @Input var export: Boolean = true, - @Input var progressReporter: Boolean = false, - @Internal - @Optional var progressReporterPathFilter: File? = null, - @Input var resolveFromModulesFirst: Boolean = false ) : WebpackRulesDsl { - @get:Input - @get:Optional val entryInput: String? get() = npmProjectDir?.get()?.let { npmProjectDir -> entry?.relativeOrAbsolute(npmProjectDir) } - @get:Input - @get:Optional val outputPathInput: String? get() = npmProjectDir?.get()?.let { npmProjectDir -> outputPath?.relativeOrAbsolute(npmProjectDir) } - @get:Input - @get:Optional val progressReporterPathFilterInput: String? get() = npmProjectDir?.get()?.let { npmProjectDir -> progressReporterPathFilter?.relativeOrAbsolute(npmProjectDir) } @@ -148,6 +112,12 @@ data class KotlinWebpackConfig( var splitChunks: Any ) : Serializable + @Suppress("unused") + data class WatchOptions( + var aggregateTimeout: Int? = null, + var ignored: Any? = null + ) : Serializable + fun save(configFile: File) { configFile.writer().use { appendTo(it) @@ -206,11 +176,21 @@ data class KotlinWebpackConfig( } private fun Appendable.appendDevServer() { - if (devServer == null) return + if (devServer != null) { - appendLine("// dev server") - appendLine("config.devServer = ${json(devServer!!)};") - appendLine() + appendLine("// dev server") + appendLine("config.devServer = ${json(devServer!!)};") + appendLine() + } + + if (watchOptions == null) return + + //language=JavaScript 1.8 + appendLine( + """ + config.watchOptions = ${json(watchOptions!!)}; + """.trimIndent() + ) } private fun Appendable.appendExperiments() { @@ -257,25 +237,25 @@ data class KotlinWebpackConfig( } private fun Appendable.appendEntry() { - if ( - entry == null - || outputPath == null - || output == null - ) - return - - val multiEntryOutput = "${outputFileName!!.removeSuffix(".js")}-[name].js" - - //language=JavaScript 1.8 - appendLine( - """ + if (entry != null) { + //language=JavaScript 1.8 + appendLine( + """ // entry config.entry = { main: [require('path').resolve(__dirname, ${entryInput!!.jsQuoted()})] }; - + """.trimIndent() + ) + } + + if (output != null) { + val multiEntryOutput = "${outputFileName!!.removeSuffix(".js")}-[name].js" + + //language=JavaScript 1.8 + appendLine( + """ config.output = { - path: require('path').resolve(__dirname, ${outputPathInput!!.jsQuoted()}), filename: (chunkData) => { return chunkData.chunk.name === 'main' ? ${outputFileName!!.jsQuoted()} @@ -285,7 +265,19 @@ data class KotlinWebpackConfig( ${output!!.libraryTarget?.let { "libraryTarget: ${it.jsQuoted()}," } ?: ""} globalObject: "${output!!.globalObject}" }; - + """.trimIndent() + ) + } + + if ( + outputPath == null + ) + return + + //language=JavaScript 1.8 + appendLine( + """ + config.output.path = require('path').resolve(__dirname, ${outputPathInput!!.jsQuoted()}) """.trimIndent() ) }