Gradle, js, browser: fix karma.conf.js writer
#KT-31011
This commit is contained in:
+3
@@ -33,10 +33,13 @@ class NpmPackages {
|
|||||||
|
|
||||||
val karmaMocha = NpmPackageVersion("karma-mocha", "1.3.0")
|
val karmaMocha = NpmPackageVersion("karma-mocha", "1.3.0")
|
||||||
val karmaWebpack = NpmPackageVersion("karma-webpack", "*")
|
val karmaWebpack = NpmPackageVersion("karma-webpack", "*")
|
||||||
|
val karmaCoverage = NpmPackageVersion("karma-coverage", "*")
|
||||||
|
|
||||||
val karmaSourceMapSupport = NpmPackageVersion("karma-source-map-support", "1.4.0")
|
val karmaSourceMapSupport = NpmPackageVersion("karma-source-map-support", "1.4.0")
|
||||||
|
|
||||||
val kotlinNodeJsTestRunner = KotlinGradleNpmPackage("test-nodejs-runner")
|
val kotlinNodeJsTestRunner = KotlinGradleNpmPackage("test-nodejs-runner")
|
||||||
|
|
||||||
|
val istanbulInstrumenterLoader = NpmPackageVersion("istanbul-instrumenter-loader", "*")
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RequiredKotlinJsDependency {
|
interface RequiredKotlinJsDependency {
|
||||||
|
|||||||
+3
-2
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter
|
||||||
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
|
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
|
||||||
|
|
||||||
class KotlinBrowserJs(target: KotlinJsTarget) :
|
class KotlinBrowserJs(target: KotlinJsTarget) :
|
||||||
@@ -25,6 +25,7 @@ class KotlinBrowserJs(target: KotlinJsTarget) :
|
|||||||
|
|
||||||
override fun configureDefaultTestFramework(it: KotlinJsTest) {
|
override fun configureDefaultTestFramework(it: KotlinJsTest) {
|
||||||
it.useKarma {
|
it.useKarma {
|
||||||
|
useMocha()
|
||||||
useWebpack()
|
useWebpack()
|
||||||
useChromeHeadless()
|
useChromeHeadless()
|
||||||
}
|
}
|
||||||
@@ -62,7 +63,7 @@ class KotlinBrowserJs(target: KotlinJsTarget) :
|
|||||||
it.bin = "webpack-dev-server"
|
it.bin = "webpack-dev-server"
|
||||||
it.entry = npmProject.compileOutput(compileKotlinTask)
|
it.entry = npmProject.compileOutput(compileKotlinTask)
|
||||||
|
|
||||||
it.devServer = KotlinWebpackConfig.DevServer(
|
it.devServer = KotlinWebpackConfigWriter.DevServer(
|
||||||
open = true,
|
open = true,
|
||||||
contentBase = listOf(compilation.output.resourcesDir.canonicalPath)
|
contentBase = listOf(compilation.output.resourcesDir.canonicalPath)
|
||||||
)
|
)
|
||||||
|
|||||||
+121
-11
@@ -10,6 +10,7 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.process.ProcessForkOptions
|
import org.gradle.process.ProcessForkOptions
|
||||||
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings
|
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings
|
||||||
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
|
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
|
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmPackageVersion
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmPackageVersion
|
||||||
@@ -17,12 +18,20 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.RequiredKotlinJsDependency
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KarmaConfig.CoverageReporter.Reporter
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter
|
||||||
|
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class KotlinKarma(val project: Project) : KotlinJsTestFramework {
|
class KotlinKarma(val project: Project) : KotlinJsTestFramework {
|
||||||
private val config: KarmaConfig = KarmaConfig()
|
private val config: KarmaConfig = KarmaConfig()
|
||||||
private val requiredDependencies = mutableSetOf<NpmPackageVersion>()
|
private val requiredDependencies = mutableSetOf<NpmPackageVersion>()
|
||||||
|
|
||||||
private val versions = project.nodeJs.versions
|
private val versions = project.nodeJs.versions
|
||||||
|
private val configurators = mutableListOf<(KotlinJsTest) -> Unit>()
|
||||||
|
private val confJsWriters = mutableListOf<(Appendable) -> Unit>()
|
||||||
|
private var sourceMaps = false
|
||||||
|
private var configDirectory: File? = project.projectDir.resolve("karma.config.d").takeIf { it.isDirectory }
|
||||||
|
|
||||||
override val requiredNpmDependencies: Collection<RequiredKotlinJsDependency>
|
override val requiredNpmDependencies: Collection<RequiredKotlinJsDependency>
|
||||||
get() = requiredDependencies.toList()
|
get() = requiredDependencies.toList()
|
||||||
@@ -30,12 +39,20 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework {
|
|||||||
init {
|
init {
|
||||||
requiredDependencies.add(versions.karma)
|
requiredDependencies.add(versions.karma)
|
||||||
|
|
||||||
requiredDependencies.add(versions.karmaTeamcityReporter)
|
useTeamcityReporter()
|
||||||
config.reporters.add("teamcity")
|
|
||||||
|
|
||||||
config.singleRun = true
|
config.singleRun = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun useTeamcityReporter() {
|
||||||
|
requiredDependencies.add(versions.karmaTeamcityReporter)
|
||||||
|
config.reporters.add("teamcity")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useConfigDirectory(dir: File) {
|
||||||
|
configDirectory = dir
|
||||||
|
}
|
||||||
|
|
||||||
fun useChrome() = useBrowser("Chrome", versions.karmaChromeLauncher)
|
fun useChrome() = useBrowser("Chrome", versions.karmaChromeLauncher)
|
||||||
|
|
||||||
fun useChromeCanary() = useBrowser("ChromeCanary", versions.karmaChromeLauncher)
|
fun useChromeCanary() = useBrowser("ChromeCanary", versions.karmaChromeLauncher)
|
||||||
@@ -60,15 +77,85 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework {
|
|||||||
fun useMocha() {
|
fun useMocha() {
|
||||||
requiredDependencies.add(versions.karmaMocha)
|
requiredDependencies.add(versions.karmaMocha)
|
||||||
requiredDependencies.add(versions.mocha)
|
requiredDependencies.add(versions.mocha)
|
||||||
|
config.frameworks.add("mocha")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun useWebpack() {
|
fun useWebpack() {
|
||||||
requiredDependencies.add(versions.karmaWebpack)
|
requiredDependencies.add(versions.karmaWebpack)
|
||||||
|
|
||||||
|
addPreprocessor("webpack")
|
||||||
|
confJsWriters.add {
|
||||||
|
it.appendln()
|
||||||
|
it.appendln("// webpack config")
|
||||||
|
it.appendln("function createWebpackConfig() {")
|
||||||
|
|
||||||
|
KotlinWebpackConfigWriter(
|
||||||
|
sourceMaps = true,
|
||||||
|
export = false
|
||||||
|
).appendTo(it)
|
||||||
|
|
||||||
|
it.appendln(" return config;")
|
||||||
|
it.appendln("}")
|
||||||
|
it.appendln()
|
||||||
|
it.appendln("config.set({webpack: createWebpackConfig()});")
|
||||||
|
it.appendln()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useCoverage(
|
||||||
|
html: Boolean = true,
|
||||||
|
lcov: Boolean = true,
|
||||||
|
cobertura: Boolean = false,
|
||||||
|
teamcity: Boolean = true,
|
||||||
|
text: Boolean = false,
|
||||||
|
textSummary: Boolean = false,
|
||||||
|
json: Boolean = false,
|
||||||
|
jsonSummary: Boolean = false
|
||||||
|
) {
|
||||||
|
if (listOf(
|
||||||
|
html, lcov, cobertura,
|
||||||
|
teamcity, text, textSummary,
|
||||||
|
json, jsonSummary
|
||||||
|
).all { !it }
|
||||||
|
) return
|
||||||
|
|
||||||
|
requiredDependencies.add(versions.karmaCoverage)
|
||||||
|
config.reporters.add("coverage")
|
||||||
|
addPreprocessor("coverage") { !it.endsWith("_test.js") }
|
||||||
|
|
||||||
|
configurators.add {
|
||||||
|
val reportDir = project.reportsDir.resolve("coverage/${it.name}")
|
||||||
|
reportDir.mkdirs()
|
||||||
|
|
||||||
|
config.coverageReporter = KarmaConfig.CoverageReporter(reportDir.canonicalPath).also { coverage ->
|
||||||
|
if (html) coverage.reporters.add(Reporter("html"))
|
||||||
|
if (lcov) coverage.reporters.add(Reporter("lcovonly"))
|
||||||
|
if (cobertura) coverage.reporters.add(Reporter("cobertura"))
|
||||||
|
if (teamcity) coverage.reporters.add(Reporter("teamcity"))
|
||||||
|
if (text) coverage.reporters.add(Reporter("text"))
|
||||||
|
if (textSummary) coverage.reporters.add(Reporter("text-summary"))
|
||||||
|
if (json) coverage.reporters.add(Reporter("json"))
|
||||||
|
if (jsonSummary) coverage.reporters.add(Reporter("json-summary"))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun useSourceMapSupport() {
|
fun useSourceMapSupport() {
|
||||||
config.frameworks.add("source-map-support")
|
config.frameworks.add("source-map-support")
|
||||||
requiredDependencies.add(versions.karmaSourceMapSupport)
|
requiredDependencies.add(versions.karmaSourceMapSupport)
|
||||||
|
|
||||||
|
sourceMaps = true
|
||||||
|
addPreprocessor("sourcemap")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addPreprocessor(name: String, predicate: (String) -> Boolean = { true }) {
|
||||||
|
configurators.add {
|
||||||
|
config.files.forEach {
|
||||||
|
if (predicate(it)) {
|
||||||
|
config.preprocessors.getOrPut(it) { mutableListOf() }.add(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createTestExecutionSpec(
|
override fun createTestExecutionSpec(
|
||||||
@@ -86,19 +173,30 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework {
|
|||||||
|
|
||||||
val npmProject = task.project.npmProject
|
val npmProject = task.project.npmProject
|
||||||
|
|
||||||
config.files.addAll(task.nodeModulesToLoad.map {
|
val files = task.nodeModulesToLoad.map { npmProject.require(it) }
|
||||||
npmProject.require(it)
|
config.files.addAll(files)
|
||||||
})
|
|
||||||
|
|
||||||
config.basePath = npmProject.nodeModulesDir.absolutePath
|
config.basePath = npmProject.nodeModulesDir.absolutePath
|
||||||
|
|
||||||
|
configurators.forEach {
|
||||||
|
it(task)
|
||||||
|
}
|
||||||
|
|
||||||
val karmaConfJs = npmProject.nodeWorkDir.resolve("karma.conf.js")
|
val karmaConfJs = npmProject.nodeWorkDir.resolve("karma.conf.js")
|
||||||
karmaConfJs.printWriter().use {
|
karmaConfJs.printWriter().use { confWriter ->
|
||||||
it.println("module.exports = function(config) {")
|
confWriter.println("module.exports = function(config) {")
|
||||||
it.print(" config.set(")
|
confWriter.println()
|
||||||
GsonBuilder().setPrettyPrinting().create().toJson(config, it)
|
|
||||||
it.println(");")
|
confWriter.print("config.set(")
|
||||||
it.println("}")
|
GsonBuilder().setPrettyPrinting().create().toJson(config, confWriter)
|
||||||
|
confWriter.println(");")
|
||||||
|
|
||||||
|
confJsWriters.forEach { it(confWriter) }
|
||||||
|
|
||||||
|
confWriter.appendFromConfigDir()
|
||||||
|
|
||||||
|
confWriter.println()
|
||||||
|
confWriter.println("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val nodeModules = listOf("karma/bin/karma")
|
val nodeModules = listOf("karma/bin/karma")
|
||||||
@@ -118,4 +216,16 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework {
|
|||||||
clientSettings
|
clientSettings
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendFromConfigDir() {
|
||||||
|
val configDirectory = configDirectory ?: return
|
||||||
|
|
||||||
|
check(configDirectory.isDirectory) {
|
||||||
|
"\"$configDirectory\" is not a directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
appendln()
|
||||||
|
appendConfigsFromDir(configDirectory)
|
||||||
|
appendln()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+12
-1
@@ -14,5 +14,16 @@ class KarmaConfig {
|
|||||||
val frameworks: MutableList<String> = mutableListOf()
|
val frameworks: MutableList<String> = mutableListOf()
|
||||||
val browsers: MutableList<String> = mutableListOf()
|
val browsers: MutableList<String> = mutableListOf()
|
||||||
val reporters: MutableList<String> = mutableListOf()
|
val reporters: MutableList<String> = mutableListOf()
|
||||||
val preprocessors: MutableMap<String, List<String>> = mutableMapOf()
|
val preprocessors: MutableMap<String, MutableList<String>> = mutableMapOf()
|
||||||
|
var coverageReporter: CoverageReporter? = null
|
||||||
|
|
||||||
|
class CoverageReporter(var dir: String) {
|
||||||
|
val reporters = mutableListOf<Reporter>()
|
||||||
|
|
||||||
|
class Reporter(
|
||||||
|
val type: String,
|
||||||
|
val subDir: String? = null,
|
||||||
|
val file: String? = null
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.targets.js
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun Appendable.appendConfigsFromDir(confDir: File) {
|
||||||
|
if (!confDir.isDirectory) return
|
||||||
|
|
||||||
|
confDir.listFiles()
|
||||||
|
?.toList()
|
||||||
|
?.filter { it.name.endsWith(".js") }
|
||||||
|
?.forEach {
|
||||||
|
appendln("// ${it.name}")
|
||||||
|
append(it.readText())
|
||||||
|
appendln()
|
||||||
|
appendln()
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-9
@@ -67,7 +67,7 @@ open class KotlinWebpack : DefaultTask(), RequiresNpmDependencies {
|
|||||||
|
|
||||||
@Input
|
@Input
|
||||||
@Optional
|
@Optional
|
||||||
var devServer: KotlinWebpackConfig.DevServer? = null
|
var devServer: KotlinWebpackConfigWriter.DevServer? = null
|
||||||
|
|
||||||
override val requiredNpmDependencies: Collection<NpmPackageVersion>
|
override val requiredNpmDependencies: Collection<NpmPackageVersion>
|
||||||
get() = mutableListOf<NpmPackageVersion>().also {
|
get() = mutableListOf<NpmPackageVersion>().also {
|
||||||
@@ -93,14 +93,15 @@ open class KotlinWebpack : DefaultTask(), RequiresNpmDependencies {
|
|||||||
configFile,
|
configFile,
|
||||||
execHandleFactory,
|
execHandleFactory,
|
||||||
bin,
|
bin,
|
||||||
KotlinWebpackConfig(
|
KotlinWebpackConfigWriter(
|
||||||
entry,
|
entry = entry,
|
||||||
if (saveEvaluatedConfigFile) evaluatedConfigFile else null,
|
reportEvaluatedConfigFile = if (saveEvaluatedConfigFile) evaluatedConfigFile else null,
|
||||||
outputPath,
|
outputPath = outputPath,
|
||||||
configDirectory,
|
configDirectory = configDirectory,
|
||||||
if (report) reportDir else null,
|
bundleAnalyzerReportDir = if (report) reportDir else null,
|
||||||
devServer,
|
devServer = devServer,
|
||||||
sourceMaps = sourceMaps
|
sourceMaps = sourceMaps,
|
||||||
|
sourceMapsRuntime = sourceMaps
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
-165
@@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
|
||||||
* that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("NodeJsCodingAssistanceForCoreModules", "JSUnresolvedFunction")
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.webpack
|
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder
|
|
||||||
import com.google.gson.stream.JsonWriter
|
|
||||||
import java.io.File
|
|
||||||
import java.io.Serializable
|
|
||||||
import java.io.StringWriter
|
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
class KotlinWebpackConfig(
|
|
||||||
val entry: File,
|
|
||||||
val reportEvaluatedConfigFile: File?,
|
|
||||||
val outputPath: File,
|
|
||||||
val configDirectory: File?,
|
|
||||||
val reportDir: File?,
|
|
||||||
var devServer: DevServer? = null,
|
|
||||||
val showProgress: Boolean = false,
|
|
||||||
val sourceMaps: Boolean = false
|
|
||||||
) {
|
|
||||||
@Suppress("unused")
|
|
||||||
data class BundleAnalyzerPlugin(
|
|
||||||
val analyzerMode: String,
|
|
||||||
val reportFilename: String,
|
|
||||||
val openAnalyzer: Boolean,
|
|
||||||
val generateStatsFile: Boolean,
|
|
||||||
val statsFilename: String
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
data class DevServer(
|
|
||||||
val inline: Boolean = true,
|
|
||||||
val lazy: Boolean = false,
|
|
||||||
val noInfo: Boolean = true,
|
|
||||||
val open: Any = true,
|
|
||||||
val overlay: Any = false,
|
|
||||||
val port: Int = 8080,
|
|
||||||
val proxy: Map<String, Any>? = null,
|
|
||||||
val contentBase: List<String>
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
fun save(configFile: File) {
|
|
||||||
configFile.writeText(build())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun build() = buildString {
|
|
||||||
//language=JavaScript 1.8
|
|
||||||
appendln(
|
|
||||||
"""
|
|
||||||
var config = {
|
|
||||||
mode: 'development',
|
|
||||||
entry: ['${entry.canonicalPath}'],
|
|
||||||
output: {
|
|
||||||
path: '${outputPath.canonicalPath}',
|
|
||||||
filename: '${entry.name}'
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
modules: [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.js${'$'}/,
|
|
||||||
use: ["source-map-loader"],
|
|
||||||
enforce: "pre"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
devtool: 'eval-source-map'
|
|
||||||
};""".trim()
|
|
||||||
)
|
|
||||||
appendln()
|
|
||||||
|
|
||||||
if (sourceMaps) {
|
|
||||||
//language=JavaScript 1.8
|
|
||||||
appendln("""
|
|
||||||
// source maps
|
|
||||||
config.entry.push('source-map-support/browser-source-map-support.js');
|
|
||||||
config.module.rules.push({test: /\.js${'$'}/, use: ['source-map-loader'], enforce: 'pre'});
|
|
||||||
""".trim())
|
|
||||||
appendln()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devServer != null) {
|
|
||||||
appendln("// dev server")
|
|
||||||
appendln("config.devServer = ${json(devServer!!)};")
|
|
||||||
appendln()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reportDir != null) {
|
|
||||||
val reportBasePath = "${reportDir.canonicalPath}/${entry.name}"
|
|
||||||
val config = BundleAnalyzerPlugin(
|
|
||||||
"static",
|
|
||||||
"$reportBasePath.report.html",
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
"$reportBasePath.stats.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
//language=JavaScript 1.8
|
|
||||||
appendln(
|
|
||||||
"""
|
|
||||||
// save webpack-bundle-analyzer report
|
|
||||||
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
||||||
config.plugins.push(new BundleAnalyzerPlugin(${json(config)}));
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configDirectory != null) {
|
|
||||||
appendln()
|
|
||||||
loadConfigs(configDirectory)
|
|
||||||
}
|
|
||||||
|
|
||||||
appendln()
|
|
||||||
|
|
||||||
if (reportEvaluatedConfigFile != null) {
|
|
||||||
val filePath = jsQuotedString(reportEvaluatedConfigFile.canonicalPath)
|
|
||||||
|
|
||||||
//language=JavaScript 1.8
|
|
||||||
appendln(
|
|
||||||
"""
|
|
||||||
// save evaluated config file
|
|
||||||
var util = require('util');
|
|
||||||
var fs = require("fs");
|
|
||||||
var evaluatedConfig = util.inspect(config, {showHidden: false, depth: null, compact: false});
|
|
||||||
fs.writeFile($filePath, evaluatedConfig, function (err) {});
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
appendln()
|
|
||||||
}
|
|
||||||
|
|
||||||
appendln("module.exports = config")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun json(obj: Any) = StringWriter().also {
|
|
||||||
GsonBuilder().setPrettyPrinting().create().toJson(obj, it)
|
|
||||||
}.toString()
|
|
||||||
|
|
||||||
private fun jsQuotedString(str: String) = StringWriter().also {
|
|
||||||
JsonWriter(it).value(str)
|
|
||||||
}.toString()
|
|
||||||
|
|
||||||
private fun StringBuilder.loadConfigs(confDir: File) {
|
|
||||||
if (confDir.isDirectory) confDir
|
|
||||||
.listFiles()
|
|
||||||
?.toList()
|
|
||||||
?.filter { it.name.endsWith(".js") }
|
|
||||||
?.forEach {
|
|
||||||
appendln("// ${it.name}")
|
|
||||||
append(it.readText())
|
|
||||||
appendln()
|
|
||||||
appendln()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+218
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("NodeJsCodingAssistanceForCoreModules", "JSUnresolvedFunction")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.targets.js.webpack
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir
|
||||||
|
import java.io.File
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.io.StringWriter
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class KotlinWebpackConfigWriter(
|
||||||
|
val mode: Mode = Mode.DEVELOPMENT,
|
||||||
|
val entry: File? = null,
|
||||||
|
val outputPath: File? = null,
|
||||||
|
val configDirectory: File? = null,
|
||||||
|
val bundleAnalyzerReportDir: File? = null,
|
||||||
|
val reportEvaluatedConfigFile: File? = null,
|
||||||
|
var devServer: DevServer? = null,
|
||||||
|
val showProgress: Boolean = false,
|
||||||
|
val sourceMaps: Boolean = false,
|
||||||
|
val sourceMapsRuntime: Boolean = false,
|
||||||
|
val export: Boolean = true
|
||||||
|
) {
|
||||||
|
enum class Mode(val code: String) {
|
||||||
|
DEVELOPMENT("development"),
|
||||||
|
PRODUCTION("production")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
data class BundleAnalyzerPlugin(
|
||||||
|
val analyzerMode: String,
|
||||||
|
val reportFilename: String,
|
||||||
|
val openAnalyzer: Boolean,
|
||||||
|
val generateStatsFile: Boolean,
|
||||||
|
val statsFilename: String
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
data class DevServer(
|
||||||
|
val inline: Boolean = true,
|
||||||
|
val lazy: Boolean = false,
|
||||||
|
val noInfo: Boolean = true,
|
||||||
|
val open: Any = true,
|
||||||
|
val overlay: Any = false,
|
||||||
|
val port: Int = 8080,
|
||||||
|
val proxy: Map<String, Any>? = null,
|
||||||
|
val contentBase: List<String>
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
fun save(configFile: File) {
|
||||||
|
configFile.writer().use {
|
||||||
|
appendTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendTo(target: Appendable) {
|
||||||
|
with(target) {
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln(
|
||||||
|
"""
|
||||||
|
var config = {
|
||||||
|
mode: '${mode.code}',
|
||||||
|
resolve: {
|
||||||
|
modules: [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
module: {
|
||||||
|
rules: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
appendEntry()
|
||||||
|
appendSourceMaps()
|
||||||
|
appendSourceMapsRuntime()
|
||||||
|
appendDevServer()
|
||||||
|
appendReport()
|
||||||
|
appendFromConfigDir()
|
||||||
|
appendEvaluatedFileReport()
|
||||||
|
|
||||||
|
if (export) {
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln("module.exports = config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendEvaluatedFileReport() {
|
||||||
|
if (reportEvaluatedConfigFile == null) return
|
||||||
|
|
||||||
|
val filePath = jsQuotedString(reportEvaluatedConfigFile.canonicalPath)
|
||||||
|
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln(
|
||||||
|
"""
|
||||||
|
// save evaluated config file
|
||||||
|
var util = require('util');
|
||||||
|
var fs = require("fs");
|
||||||
|
var evaluatedConfig = util.inspect(config, {showHidden: false, depth: null, compact: false});
|
||||||
|
fs.writeFile($filePath, evaluatedConfig, function (err) {});
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendFromConfigDir() {
|
||||||
|
if (configDirectory == null) return
|
||||||
|
|
||||||
|
appendln()
|
||||||
|
appendConfigsFromDir(configDirectory)
|
||||||
|
appendln()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendReport() {
|
||||||
|
if (bundleAnalyzerReportDir == null) return
|
||||||
|
|
||||||
|
entry ?: error("Entry should be defined for report")
|
||||||
|
|
||||||
|
val reportBasePath = "${bundleAnalyzerReportDir.canonicalPath}/${entry.name}"
|
||||||
|
val config = BundleAnalyzerPlugin(
|
||||||
|
"static",
|
||||||
|
"$reportBasePath.report.html",
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
"$reportBasePath.stats.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln(
|
||||||
|
"""
|
||||||
|
// save webpack-bundle-analyzer report
|
||||||
|
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
||||||
|
config.plugins.push(new BundleAnalyzerPlugin(${json(config)}));
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
appendln()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendDevServer() {
|
||||||
|
if (devServer == null) return
|
||||||
|
|
||||||
|
appendln("// dev server")
|
||||||
|
appendln("config.devServer = ${json(devServer!!)};")
|
||||||
|
appendln()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendSourceMapsRuntime() {
|
||||||
|
if (!sourceMapsRuntime) return
|
||||||
|
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln(
|
||||||
|
"""
|
||||||
|
// source maps runtime
|
||||||
|
if (!config.entry) config.entry = [];
|
||||||
|
config.entry.push('source-map-support/browser-source-map-support.js');
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendSourceMaps() {
|
||||||
|
if (!sourceMaps) return
|
||||||
|
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln(
|
||||||
|
"""
|
||||||
|
// source maps
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /\.js${'$'}/,
|
||||||
|
use: ["source-map-loader"],
|
||||||
|
enforce: "pre"
|
||||||
|
});
|
||||||
|
config.module.rules.push({test: /\.js${'$'}/, use: ['source-map-loader'], enforce: 'pre'});
|
||||||
|
config.devtool = 'eval-source-map';
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendEntry() {
|
||||||
|
if (entry == null || outputPath == null) return
|
||||||
|
|
||||||
|
//language=JavaScript 1.8
|
||||||
|
appendln(
|
||||||
|
"""
|
||||||
|
// entry
|
||||||
|
if (!config.entry) config.entry = [];
|
||||||
|
config.entry.push('${entry.canonicalPath}');
|
||||||
|
config.output = {
|
||||||
|
path: '${outputPath.canonicalPath}',
|
||||||
|
filename: '${entry.name}'
|
||||||
|
};
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun json(obj: Any) = StringWriter().also {
|
||||||
|
GsonBuilder().setPrettyPrinting().create().toJson(obj, it)
|
||||||
|
}.toString()
|
||||||
|
|
||||||
|
private fun jsQuotedString(str: String) = StringWriter().also {
|
||||||
|
JsonWriter(it).value(str)
|
||||||
|
}.toString()
|
||||||
|
}
|
||||||
+5
-5
@@ -25,7 +25,7 @@ internal class KotlinWebpackRunner(
|
|||||||
val configFile: File,
|
val configFile: File,
|
||||||
val execHandleFactory: ExecHandleFactory,
|
val execHandleFactory: ExecHandleFactory,
|
||||||
val bin: String,
|
val bin: String,
|
||||||
val config: KotlinWebpackConfig
|
val configWriter: KotlinWebpackConfigWriter
|
||||||
) {
|
) {
|
||||||
fun execute(): ExecResult {
|
fun execute(): ExecResult {
|
||||||
val exec = start()
|
val exec = start()
|
||||||
@@ -37,20 +37,20 @@ internal class KotlinWebpackRunner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun start(): ExecHandle {
|
fun start(): ExecHandle {
|
||||||
check(config.entry.isFile) {
|
check(configWriter.entry?.isFile == true) {
|
||||||
"${this}: Entry file not existed \"${config.entry}\""
|
"${this}: Entry file not existed \"${configWriter.entry}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
NpmResolver.resolve(project)
|
NpmResolver.resolve(project)
|
||||||
|
|
||||||
val npmProjectLayout = NpmProject[project]
|
val npmProjectLayout = NpmProject[project]
|
||||||
|
|
||||||
config.save(configFile)
|
configWriter.save(configFile)
|
||||||
|
|
||||||
val execFactory = execHandleFactory.newExec()
|
val execFactory = execHandleFactory.newExec()
|
||||||
|
|
||||||
val args = mutableListOf<String>("--config", configFile.absolutePath)
|
val args = mutableListOf<String>("--config", configFile.absolutePath)
|
||||||
if (config.showProgress) {
|
if (configWriter.showProgress) {
|
||||||
args.add("--progress")
|
args.add("--progress")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user