최종적인 컴파일 시 서버로 전달하는 url만 변형되면 된다.import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()],
build:{
outDir: "../main/resources/static/frontend", // 빌드 위치 설정
},
experimental: { // 실험적 기능
renderBuiltUrl(filename, { hostId, hostType, type }) { // 빌드시 Url 변형
if (type === 'public') {
return '/static/frontend/' + filename
} else if (path.extname(hostId) === '.js') {
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
} else {
return '/static/frontend/' + filename
}
},
},
})
import com.github.gradle.node.npm.task.NpmTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.3.2"
id("io.spring.dependency-management") version "1.1.6"
kotlin("jvm") version "1.9.24"
kotlin("plugin.spring") version "1.9.24"
id("com.github.node-gradle.node") version "7.0.2"
}
...
kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict")
}
}
...
node {
// 이 설정이 true인 경우 node를 새로 다운 받음
download.set(false)
//download가 true일 경우에만 사용
//version에 명시한 버전으로 Node.js 다운로드 및 설치
//workDir에 설치됨
//version.set('20.12.1')
// npm의 버전
//npmVersion.set('9.2.0')
}
val frontendInitTask = tasks.register<NpmTask>("frontendInitTask") {
// npm install 실행
args.set(listOf("install"))
}
val frontendTask = tasks.register<NpmTask>("frontendTask") {
dependsOn(frontendInitTask)
// npm run build 실행
args.set(listOf("run", "build"))
}
tasks.withType<KotlinCompile>{
dependsOn(frontendTask)
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = java.sourceCompatibility.toString()
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
application.properties에서, spring.mvc.static-path-pattern=이하 도메인을 맞춰준다.static/frontend/산하로 접속하면 되게 했으므로, spring.mvc.static-path-pattern=static/**로 설정했다.import org.springframework.web.bind.annotation.GetMapping
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
@Controller
// 예제이므로 API로 넘기는 부분은 감안하지 않았다.
// 이 wildcard는 `모든` request를 이 핸들러로 넘기므로, 사용시 주의가 필요하다.
// 이 예제에서는 '/' route로 갔을 때 static SPA를 띄우는 것이 목표이다.
@RequestMapping("**")
class RootApiRoot {
@GetMapping("/")
fun root(): String {
return "static/frontend/index.html"
}
}
이러면, RequestMapping이static/frontend/index.html라우터의 내용을 전달해주면서 깔끔한 메인이 나타나게 된다.
하지만 알다시피, SEO측면에서는 딱히 좋은 방법은 아니다. Lazy Loading 문제가 있기 때문이다.
Node.js하자 그러면 꼬이지는 않는다
사실 이걸 응용하면 cdn으로 분산 가능한데 피곤해서 쓰진 않았네요 졸려...