이 글의 내용 중 SvelteKit Docs 문서 부분은 Sveltekit가 Release 되기 전 문서 내용입니다.
글 작성 이후 session이 삭제되고, +접두사로 파일 이름 규칙이 변경되는 등 대대적인 변경이 있었습니다.
따라서 SvelteKit Docs 내용 부분은 현재 도움이 되지 않습니다.
SvelteKit을 공부하기 전에 Svelte 부터 공부해야 합니다.
2022.06.23 - [Study/JavaScript] - Svelte 공부하기
Svelte는 tutorial 사이트에서 직접 예제를 테스트해볼 수 있어서 공부하기 편했다.
SvelteKit은 예제를 테스트 해볼 수 있는 사이트 제공이 없다.
따라서 로컬에 설치하고 개인적인 프로젝트를 만들면서 나한테 필요한 설정들에 대해서 정리해 보고 tutorial의 내용을 정리해 보았다.
자세한 내용은 SvelteKit 문서를 참고하면 된다.
SvelteKit 문서의 경우 Configuration까지만 적어두었다.
(Types, SEO, Asset Handling, Migrating from sapper, Additional Resources, Appendix는 적지 않음)
SvelteKit 프로젝트 만들기
만드는 건 SvelteKit 홈페이지 첫 화면에 안내되어 있다.
다만 npm이 아닌 pnpm으로 만들었다.
pnpm create svelte bluesky-project-front-sveltekit
선택지를 묻는 항목에서 순서대로 Skelection project, TypeScript, ESLint 사용, Prettier 사용, Playwright 미사용을 선택하고 생성하였다.
다음으로 생성된 프로젝트로 들어가서 install을 실행하고 Visual Studio Code를 연다.
cd bluesky-project-front-sveltekit
pnpm install
code .
만약 Visual Studio Code에 Vite 확장이 설치되어 있으면 알아서 다음 명령을 수행하여 서버를 port 4000으로 실행한다.
npx vite --port=4000
따로 실행하고자 한다면 다음과 같이 실행해도 된다.
pnpm run dev
package.json에 최초 설정되는 내용은 다음과 같다.
{
"name": "bluesky-project-front-sveltekit",
"version": "0.0.1",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"package": "svelte-kit package",
"preview": "vite preview",
"prepare": "svelte-kit sync",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check --plugin-search-dir=. . && eslint .",
"format": "prettier --write --plugin-search-dir=. ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"@typescript-eslint/eslint-plugin": "^5.27.0",
"@typescript-eslint/parser": "^5.27.0",
"eslint": "^8.16.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-svelte3": "^4.0.0",
"prettier": "^2.6.2",
"prettier-plugin-svelte": "^2.7.0",
"svelte": "^3.44.0",
"svelte-check": "^2.7.1",
"svelte-preprocess": "^4.10.6",
"tslib": "^2.3.1",
"typescript": "^4.7.4",
"vite": "^2.9.13"
},
"type": "module"
}
개인 프로젝트 설정
Proxy 설정하기 (vite.config.js 설정)
proxy 설정은 해당 프로젝트에서 특정 주소에 대해서 api호출을 다른 대상으로 호출하도록 처리하여 따로 별도의 BE framework과 연동할 수 있게 하는 설정이다.
내 경우 api를 제공하는 부분은 java Spring Boot로 만든 서버를 사용하고 웹페이지 구성을 위해 SvelteKit을 사용하기 때문에 SvelteKit에서 proxy 설정이 필요하다.
vue의 경우 vue가 자체적으로 설정할 수 있도록 vue.config.js (nuxt 사용 시엔 nuxt.config.js)에 devServer.proxy 옵션이 있었다.
https://cli.vuejs.org/config/#devserver-proxy
해당 설정은 webpack.config.js의 설정을 vue나 nuxt config.js에서 할 수 있게 지원하는 설정인 듯하다.
https://webpack.js.org/configuration/dev-server/
vite를 사용하는 경우에도 proxy 설정이 있다.
https://vitejs.dev/config/#server-proxy
해당 설정을 추가해 본다.
import { sveltekit } from '@sveltejs/kit/vite';
/** @type {import('vite').UserConfig} */
const config = {
plugins: [sveltekit()],
server: {
proxy: {
'/api': {
target: 'http://localhost:8084/',
changeOrigin: true
}
}
}
};
export default config;
해당 설정이 잘 동작하는지 ajax 호출을 테스트해 보면 된다.
<script>
$: userInfo = fetch('/api/user/loginInfo', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
}
}).then((response) => response.json());
</script>
{#await userInfo}
<p>...Loading</p>
{:then userInfo}
id : {userInfo.id}<br />
name : {userInfo.name}
{:catch error}
<p>오류가 발생했습니다.</p>
{/await}
sveltestrap 사용하기
sveltestrap은 bootstrap을 svelte component 형태로 사용할 수 있게 해주는 라이브러리이다.
bootstrap을 사용하길 원하는 경우 bootstrap을 직접 사용하는 것보다 더 효과적으로 사용할 수 있다.
초반에 bootstrap을 사용하려다가 tailwind css로 변경하였지만 설정하던 과정은 적어둔다.
pnpm i sveltestrap
공통 사용 영역이므로 __layout.svelte
에 다음과 같이 설정
<script>
import { Styles } from 'sveltestrap';
</script>
<Styles />
<slot />
다음과 같이 설정해서 사용한다.
<script>
import { Button } from 'sveltestrap';
</script>
<Button>test</Button>
tailwindcss 사용해 보기
이제까진 계속 bootstrap관련 라이브러리를 사용했었는데 요즘은 tailwindcss도 많은 관심을 받고 있다.
한번 써보기로 한다.
tailwindcss의 경우 각 라이브러리 별 설정 방법을 자세히 안내하고 있다.
Install Tailwind CSS with SvelteKit
해당 가이드를 그대로 따라만 하면 된다.
관련 라이브러리 들을 아래와 같이 추가하고
pnpm install -D tailwindcss postcss autoprefixer
npx tailwindcss init tailwind.config.cjs -p
svelte.config.js에 preprocess를 다음과 같이 설정하고
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
},
preprocess: vitePreprocess()
};
export default config;
tailwind.config.cjs에 content 설정을 다음과 같이 하고 (이 부분은 아마 설정이 되어 있을 것이다.)
module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: []
};
./src/app.css 파일을 만들어 다음과 같이 설정한다.
@tailwind base;
@tailwind components;
@tailwind utilities;
이제 사용하는 설정을 ./src/routes/+layout.svelte에 다음과 같이 추가한다.
<script>
import "../app.css";
</script>
<slot />
여기까지 진행하였으면 모든 svelte 파일에서 tailwindcss를 사용할 수 있게 된다.
<h1 class="text-3xl font-bold underline">
Hello world!
</h1>
style을 굳이 선언 안 해도 되는 장점이 있고 쓰다 보면 CSS에 대해 자연스럽게 공부할 수 있는 장점도 있지만 극단적으로 class를 도배해야 하는 단점이 있다.
그래도 공부할 땐 bootstrap보다 이걸 사용하는 게 더 좋을 것 같다.
무료 template을 공개한 사이트를 몇 군데 찾아서 적당히 사용하면 되지 않을까 싶다. (어디가 더 좋은지 모름)
- Tailwind Toolbox
- Tailwind CSS Templates
- Tailwind Awesome
- 30 Free Tailwind CSS Templates To Kick Start Your Next Project
- 10+ Free Tailwind CSS Templates & Resources for 2022
fontawesome 사용하기
fontawesome은 수많은 아이콘을 쉽게 사용할 수 있게 해 준다.
유료 및 무료 버전이 있고 각 패키지 별 설치가 가능하지만 간단하게 사용하기 위해 다음과 같이 추가하였다.
pnpm install @fortawesome/fontawesome-free
최상위 __layout.svelte에 다음과 같이 추가한다.
<script>
import '@fortawesome/fontawesome-free/js/all.min.js';
</script>
이제 손쉽게 아이콘을 사용할 수 있다.
<i class="fa-brands fa-facebook" />
date-fns 사용하기
한동안 사용하던 moment js가 maintenance mode가 되어 더 이상 개발되지 않는다.
대체 라이브러리로 date-fns, dayjs, luxon 등이 있는데 이중 date-fns가 가장 많이 사용하고 있어 사용해 보았다.
설치는 다음과 같다.
pnpm i date-fns
사용은 다음과 같다.
import { format, formatDistanceToNow } from 'date-fns';
import { ko } from 'date-fns/locale';
const targetDate = new Date(dateStr);
formatDistanceToNow(targetDate, { addSuffix: true, locale: ko }); // *초 전, *일 전, *년 전...
toast ui editor
toast ui editor는 naver에서 제공하는 라이브러리이다.
markdown으로 작성할 수 있다.
vue를 사용할 때엔 제공하는 vue-editor wrapper를 사용하였지만 svelte를 사용할 경우 wrapper 없이 사용해야 한다.
설치는 다음과 같다.
pnpm i @toast-ui/editor
사용은 다음과 같다.
<script type="ts">
import { onMount } from 'svelte';
import Editor from '@toast-ui/editor';
import '@toast-ui/editor/dist/toastui-editor.css';
onMount(async () => {
var targetEl = document.querySelector('#editor');
if (targetEl != null) {
const editor = new Editor({
el: targetEl,
height: '500px',
initialEditType: 'markdown',
previewStyle: 'vertical'
});
}
});
</script>
<div id="editor" />
navigation을 통한 접근은 정상 호출되지만 현재 해당 페이지 호출 시 아래와 같은 에러가 발생한다.
ReferenceError: self is not defined
빌드 설정하기 (adapter-static SPA mode 사용하기)
내 경우 백엔드 서버는 java Spring Boot를 사용하고 있다.
sveltekit로 빌드한 정적 페이지를 java 서버에 올려서 사용하게 된다.
https://kit.svelte.dev/docs/adapter-static#spa-mode
이를 위한 설정은 다음과 같다.
먼저 adapter-static을 설치한다.
pnpm i -D @sveltejs/adapter-static
svelte.config.js를 다음과 같이 설정한다.
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
adapter: adapter({
fallback: 'sveltekit.html'
}),
prerender: { entries: [] }
}
};
export default config;
src/routes/+layout.js에 ssr false 설정을 다음과 같이 한다.
export const ssr = false;
이제 빌드를 한다.
pnpm run build
빌드된 결과물은 ./build 하위에 생성된다.
설정한 주소마다 html 페이지가 만들어지는게 아니고 단일 html 페이지가 생성된다.
요청 주소가 다르더라도 모두 이 페이지를 호출하면 요청한 주소에 따라 개발한대로 처리가 된다.
Spring Boot 기반 프로젝트의 /src/main/resources/static 하위에 위 파일을 넣어두고
java controller 설정에서 sveltekit.html를 바라보도록 호출할 주소들을 설정한다.
@Controller
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public class IndexController {
@GetMapping({"/", "/index", "접근하는 모든 주소..."})
public String index() {
return "forward:sveltekit.html";
}
}
이렇게 설정하면 sveltekit으로 FE 개발, java Spring Boot로 BE 개발을 분리 할 수 있게 된다.
SvelteKit Docs 내용
Project structure
Project files
src
src
디렉터리에는 project의 핵심이 들어있다.
lib
에는 $lib alias를 통해 가져올 수 있거나 svelte-kit package를 사용하여 배포할 수 있는 라이브러리 코드가 포함되어 있다.params
에는 app에 필요한 모든 param matcher가 포함되어 있다.routes
에는 application의 pages 및 endpoints 가 포함되어 있다.app.html
은 다음 placeholder를 포함하는 HTML 문서인 page template이다.%sveltekit.head%
- app에 필요한<link>
및<script>
element 및<svelte:head>
content%sveltekit.body%
- 렌더링 된 page의 markup%sveltekit.assets%
- page에서 paths.assets path로의 상대 경로%sveltekit.nonce%
- 수동으로 포함된 link 및 script에 대한 CSP nonce (사용되는 경우)
hook.js
(선택 사항) application의 hooks가 포함되어 있다.service-worker.js
(선택 사항) service worker가 포함되어 있다.
TypeScript를 사용하는 경우 .js
파일 대신 .ts
파일을 사용할 수 있다.
static
robots.txt
또는 favicon.png
같이 제공되어야 하는 static asset은 여기에 포함된다.
package.json
package.json
파일은 @sveltejs/kit
, svelte
및 vite
를 devDependencies
에 포함해야 한다.
npm create svelte
로 프로젝트를 만들면 package.json
에 "type" : "module"
이 포함되어 있다.
즉 .js
파일은 import
및 export
keyword가 있는 기본 JavaScript module로 해석된다.
legacy CommonJS 파일에는 .cjs
file 확장자가 필요하다.
svelte.config.js
이 파일에는 Svelte 및 SvelteKit configuration이 포함되어 있다.
tsconfig.json
이 파일(또는 .ts
파일보다 type-checked .js
파일을 선호하는 경우 jsconfig.json
)은 npm create svelte@latest
동안 typechecking을 추가한 경우 TypeScript를 구성한다.
SvelteKit는 특정 구성이 특정 방식으로 설정되어 있기 때문에 자체 configuration이 extends
되는 자체 .svelte-kit/tsconfig.json
파일을 생성한다.
vite.config.js
SvelteKit 프로젝트는 실제로 다른 Vite configuration과 함께 @sveltejs/kit/vite plugin을 사용하는 Vite 프로젝트이다.
Other files
test
npm create svelte@latest
동안 테스트를 추가하도록 선택하면 test
디렉터리가 생성된다.
.svelte-kit
프로젝트를 개발하고 빌드할 때 SvelteKit는 .svelte-kit
디렉토리 (outDir로 구성 가능)에 파일을 생성한다.
언제든지 내용을 무시하고 삭제할 수 있다.
다음 dev
또는 build
시 재 성성된다.
Web standards
Fetch APIs
SvelteKit는 network에서 data를 가져오기 위해 fetch를 사용한다.
브라우저뿐만 아니라 hook과 endpoint에서도 사용할 수 있다.
credential을 유지하면서 HTTP 호출을 사용하지 않고 server-side 렌더링 중에 endpoint를 직접 호출하기 위해
load
function에서 특별한 버전의fetch
를 사용할 수 있다.
(load
외부의 server-side code에서 credential이 있는 fetch를 수행하려면cookie
및/또는autorization
header를 명시적으로 전달해야 한다.)
또한 relative 요청을 수행할 수 있는 반면 server-sidefetch
에는 일반적으로 정규화된 URL이 필요하다.
fetch
자체 외에도 Fetch API에는 다음 interface가 포함된다.
Request
Request
의 instance는 hook 및 endpoint에서 event.request
로 액세스 할 수 있다.
예를 들어 request.json()
및 request.formData()
와 같은 유용한 method가 포함되어 있다.
endpoint에 게시된 데이터를 가져온다.
Response
Response
의 instance는 await fetch(…)
에서 반환된다.
기본적으로 SvelteKit app은 request
을 response
로 바꾸는 machine이다.
Headers
Header
interface는 들어오는 request.headers
를 읽고 나가는 response.headers
를 설정할 수 다.
src/routes/what-is-my-user-agent.js :
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get(event) {
// log all headers
console.log(...event.request.headers);
return {
body: {
// retrieve a specific header
userAgent: event.request.headers.get('user-agent')
}
};
}
Stream APIs
대부분의 경우 endpoint는 userAgent
example과 같이 완전한 data를 반환한다.
때로는 너무 커서 한 번에 memory에 담을 수 없거나 chunk로 전달되는 response를 반환해야 할 수 있으며 이를 위해 platform은 stream(ReadableStream, WritableStream 및 TransformStream)을 제공한다.
URL APIs
URL은 URL
interface로 표시되며 여기에는 origin
및 pathname
(browser의 hash
)과 같은 유용한 properties가 포함된다.
이 interface는 hook 및 endpoint의 event.url
, page의 $page.url
, beforeNavigate
및 afterNavigate
의 from
및 to
등 다양한 위치에 표시된다.
URLSearchParams
URL이 있는 곳마다 URLSearchParams
의 instance인 url.searchParams
를 통해 query paramete에 액세스 할 수 있다.
const foo = url.searchParams.get('foo');
Web Crypto
Web Crypto API는 crypto
global을 통해 제공된다.
콘텐츠 보안 정책 헤더에 내부적으로 사용되지만 UUID 생성과 같은 작업에도 사용할 수 있다.
Routing
Pages
page 구성은 src/routes 하위에 .svelte
파일을 만들면 된다.
예를 들어 src/routes/about.svelte
파일을 만들면 /about
으로 접근을 할 수 있다.
또한 폴더를 만들어도 동일하게 path로 구성된다.
예를 들어 src/routes/about/index.svelte
파일을 만들면 /about
으로 접근을 할 수 있다.
src/routes/index.svelte :
<svelte:head>
<title>Welcome</title>
</svelte:head>
<h1>Hello and welcome to my site!</h1>
<a href="/about">About my site</a>
src/routes/about.svelte
와 /src/routes/about/index.svelte
가 동시에 존재하면 src/routes/about.svelte
를 우선한다.
동적 파라미터를 path 주소로 가지는 경우 대괄호 [path]
를 사용한다.
예를 들어 src/routes//blog/[blogId]/list.svelte
와 같이 사용할 수 있다.
route에는 src/routes/[category]/[item].svelte
같이 여러 dynamic parameter를 가질 수 있고 또는 src/routes/[category]-[item].svelte
처럼 -로 구분 지어 지정할 수도 있다.
Endpoints
endpoint는 HTTP method에 해당하는 request handler function을 내보내는 .js
(또는 .ts
) 파일로 작성된 module이다.
Request handler를 사용하면 server (예: database 또는 filesystem)에서만 사용할 수 있는 데이터를 읽고 쓸 수 있다.
response를 나타내는 { status, headers, body }
object를 반환해야 한다.
src/routes/random.js :
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function GET() {
return {
status: 200,
headers: {
'access-control-allow-origin': '*'
},
body: {
number: Math.random()
}
};
}
status
는 HTTP status code이다.2xx
- successful response (default는200
)3xx
- redirection (location
header가 함께 있어야 함)4xx
- client error5xx
- server error
header
는 위와 같이 plain object이거나 header class의 instance일 수 있다.body
는 plain object일 수도 있고 오류가 발생할 경우 Error일 수도 있다.
JSON으로 serialized 된다.
GET
또는 HEAD
response는 body
를 포함해야 하지만 이 제한을 벗어나는 세 가지 properties는 모두 선택사항이다.
Page endpoints
endpoint의 page와 filename (확장자 제외)이 동일한 경우 페이지는 client-side navigation 동안 fetch
를 통해 또는 SSR 동안 직접 function 호출을 통해 endpoint에서 props를 가져온다.
(page가 filename에서 named layouts 또는 matchers에 대한 구문을 사용하는 경우 해당 page endpoint의 filename에도 해당 layout이 포함되어야 한다. )
예를 들어 src/routes/items/[id].svelte
page의 경우
src/routes/items/[id].svelte :
<script>
// populated with data from the endpoint
export let item;
</script>
<h1>{item.title}</h1>
src/routes/items/[id].js
endpoint와 짝을 이룬다.
($lib
import에 대해서는 이후에 설명함)
src/routes/items/[id].js :
import db from '$lib/database';
/** @type {import('./__types/[id]').RequestHandler} */
export async function GET({ params }) {
// `params.id` comes from [id].js
const item = await db.get(params.id);
if (item) {
return {
status: 200,
headers: {},
body: { item }
};
}
return {
status: 404
};
}
위의
GET
function의 type은./__types/[id].d.ts
에서 가져온 것으로 이 파일은 SvelteKit (outDir
내부,rootDirs
옵션 사용)에서 생성한 파일로param
에 액세스 할 때 type 안정성을 제공한다.
자세한 내용은 generated types section을 참고하면 된다.
page 대신 raw data를 가져오려면 request에 accept: application/json
header를 포함하거나 편의상 URL에 /__data.json
을 추가한다. (예: /items/[id]/__data.json
)
Standalone endpoints
일반적으로 endpoint는 해당 endpoint가 쌍으로 구성된 페이지에 데이터를 제공하기 위해 존재한다.
그러나 페이지와 별도로 존재할 수 있다.
standalone endpoint는 반환된 body
type에 비해 약간 더 유연하다.
object 및 Error
instance 외에도 Uint8Array
또는 ReadableStream
을 반환할 수 있다.
standalone endpoint는 원하는 경우 파일 확장자를 제공할 수 있으며 그렇지 않은 경우 직접 액세스 할 수 있다.
filename | endpoint |
---|---|
src/routes/data/index.json.js | /data.json |
src/routes/data.json.js | /data.json |
src/routes/data/index.js | /data |
src/routes/data.js | /data |
POST, PUT, PATCH, DELETE
endpoint는 해당 function을 export 함으로써 모든 HTTP method를 처리할 수 있다.
export function POST(event) {...}
export function PUT(event) {...}
export function PATCH(event) {...}
export function DELETE(event) {...}
이러한 function은 get
과 마찬가지로 page로 전달될 body
를 props로 반환할 수 있다.
get
의 4xx / 5xx response는 error page 렌더링을 초래하지만 비 GET request에 대한 유사한 response는 렌더링 form validation error와 같은 작업을 수행할 수 없다.
src/routes/items.js :
import * as db from '$lib/database';
/** @type {import('./__types/items').RequestHandler} */
export async function GET() {
const items = await db.list();
return {
body: { items }
};
}
/** @type {import('./__types/items').RequestHandler} */
export async function POST({ request }) {
const [errors, item] = await db.create(request);
if (errors) {
// return validation errors
return {
status: 400,
body: { errors }
};
}
// redirect to the newly created item
return {
status: 303,
headers: {
location: `/items/${item.id}`
}
};
}
src/routes/items.svelte :
<script>
// The page always has access to props from `GET`...
export let items;
// ...plus props from `post` when the page is rendered
// in response to a POST request, for example after
// submitting the form below
export let errors;
</script>
{#each items as item}
<Preview item={item}/>
{/each}
<form method="post">
<input name="title">
{#if errors?.title}
<p class="error">{errors.title}</p>
{/if}
<button type="submit">Create item</button>
</form>
Body parsing
request
object는 standard Request clsss의 instance이다.
따라서 request body에 쉽게 액세스 할 수 있다.
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function POST({ request }) {
const data = await request.formData(); // or .json(), or .text(), etc
await create(data);
return { status: 201 };
}
Setting cookies
Endpoint는 set-cookies
와 함께 headers
object를 반환하여 cookie를 설정할 수 있다.
여러 cookie를 동시에 설정하려면 배열을 반환한다.
/** @type {import('@sveltejs/kit').RequestHandler} */
export function GET() {
return {
headers: {
'set-cookie': [cookie1, cookie2]
}
};
}
HTTP method overrides
HTML
HTML <Form>
element는 기본적으로 GET
및 POST
method만 지원한다.
configuration에서 PUT
및 DELETE
같은 다른 method를 지정하고 form의 action에 \_method-VERB
parameter(name을 설정할 수 있음)를 추가하여 사용할 수 있다.
svelte.config.js :
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
methodOverride: {
allowed: ['PUT', 'PATCH', 'DELETE']
}
}
};
export default config;
<form method="post" action="/todos/{id}?_method=PUT">
<!-- form elements -->
</form>
native
<form>
behavior를 사용하면 JavaScript가 실패하거나 비활성화되어도 app이 계속 동작한다.
private modules
.well-known
이 아닌 _
또는 .
이 있는 파일 및 디렉터리는 기본적으로 비공개이며, 즉 routes를 만들지 않는다.
(그러나 routes를 생성하는 파일에서 import 할 수 있음)routes
configuration을 사용하여 공개 또는 비공개로 간주되는 모듈을 구성할 수 있다.
Advanced routing
Rest parameters
route segment의 수를 알 수 없는 경우 rest 구문을 사용할 수 있다.
예를 들어 Github의 file viewer를 다음과 같이 구현할 수 있다.
/[org]/[repo]/tree/[branch]/[...file]
이 경우 /sveltejs/kit/tree/master/documentation/docs/01-routing.md
에 대한 요청은 다음 parameter를 페이지에서 사용할 수 있다.
{
org: 'sveltejs',
repo: 'kit',
branch: 'master',
file: 'documentation/docs/01-routing.md'
}
/src/routes/a/[…rest]/z.svelte
는/a/z
(parameter가 없을 경우),/a/b/z
및/a/b/c/z
등과 일치한다.
예를 들어 matcher를 사용하는 경우와 같이 rest parameter의 값이 valid 한 지 확인한다.
Matching
/src/routes/archive/[page]
와 같은 route는 /archive/3
과 일치하지만 /archive/potato
와도 일치한다.
이를 원하지 않을 때 parameter string ("3"
또는 "potato"
)를 사용하는 matcher를 추가하여 route parameter가 잘 구성되어 있는지 확인하고 valid 한 경우 true
를 params 디렉터리로 반환한다.
src/params/integer.js :
/** @type {import('@sveltejs/kit').ParamMatcher} */
export function match(param) {
return /^\d+$/.test(param);
}
src/routes/archive/[page=integer]
pathname이 일치하지 않으면 SvelteKit은 다른 routes와 일치한 지 확인하고 없으면 404를 반환한다.
Sorting
여러 route가 지정된 path와 일치할 수 있다.
예를 들어 각 경로는 /foo-abc
와 일치한다.
src/routes/[...catchall].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/foo-[c].svelte
SvelteKit은 어떤 route가 요청되는지 알아야 한다.
다음과 같은 규칙에 따라 찾는다.
- 더 구체적인 route가 우선순위
- standalone endpoint가 동일한 page 보다 우선순위 높음
- matcher를 사용한 parameter(
[name=type]
가 없는 parameter ([name]
) 보다 우선순위 높음 - rest parameter가 우선 순위 낮음
- 동등한 경우 알파벳 순으로 우선 순위 높음
위 우선순위에 따라 /foo-abc
호출은 src/routes/foo-abc.svelte
를 호출하고/foo-dev
는 덜 구체적인 경로가 아닌 /src/routes/foo-[c].svelte
를 호출한다.
src/routes/foo-[c].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/[...catchall].svelte
Encoding
file 이름은 URI로 디코딩된다.
예를 들어 %40[username].svelte
와 같은 파일 이름을 @
로 시작하는 문자와 일치한다.
assert.equal(
decodeURIComponent('%40[username].svelte'),
'@[username].svelte'
);
%
문자를 표현하려면 %25
를 사용한다.
Layouts
모든 페이지에 적용되는 레이아웃을 만들려면 src/routes/__layout.svelte
파일을 만들면 된다.
기본 layout (따로 layout을 설정하지 않을 경우 SvelteKit에서 사용하는 layout)은 다음과 같다.
<slot></slot>
Nested layouts
단일 /settings
page가 아니라 /settings/profile
및 /settings/notifications
와 같이 공유 하위 메뉴가 는 중첩된 페이지가 있는 경우 /settings
하위 페이지에만 적용되는 layout을 만들 수 있다.
src/routes/settings/__layout.svelte :
<h1>Settings</h1>
<div class="submenu">
<a href="/settings/profile">Profile</a>
<a href="/settings/notifications">Notifications</a>
</div>
<slot></slot>
Named layouts
app의 일부는 기본 layout 이외의 다른 것이 필요할 수 있다.
이러한 경우 이름이 지정된 layout을 만들 수 있다.
src/routes/__layout-foo.svelte :
<div class="foo">
<slot></slot>
</div>
해당 레이아웃을 사용할 파일의 이름을 다음과 같이 만든다.
src/routes/my-special-page@foo.svelte :
<h1>I am inside __layout-foo</h1>
Scoping
named layout은 어느 depth에서도 만들 수 있고 동일한 하위 트리의 모든 component에 적용된다.
예를 들어 __layout-foo
는 /x/one
과 /x/two
에 적용되지만 /x/three
나 /four
에는 적용되지 않는다.
src/routes/
├ x/
│ ├ __layout-foo.svelte
│ ├ one@foo.svelte # ✅ page has `@foo`
│ ├ two@foo.svelte # ✅ page has `@foo`
│ └ three.svelte # ❌ page does not have `@foo`
└ four@foo.svelte # ❌ page has `@foo`, but __layout-foo is not 'in scope'
Inheritance chains
layout은 named layout, 동일한 디렉터리 또는 상위 디렉터리에서 상속하도록 선택할 수 있다.
예를 들어 x/y/__layout@root.svelte
는 /x/y
(/x/y/one
, /x/y/two
및 /x/y/three
가 모두 이 layout에서 상속됨)에 대해 이름이 없으므로 default layout이다.@root
를 지정하였기 때문에 __layout.svelte
및 x/__layout.svelte
를 건너뛰고 가장 가까운 __layout-root.svelte
에서 직접 상속한다.
src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
└ __layout-root.svelte
__layout-root.svelte
에 하나의<slot />
이 포함된 경우 이는@root
를 추가하여 app의 모든 페이지 또는 중첩 layout에 대해 빈 layout으로 '재설정(reset)' 할 수 있음을 의미한다.
parent가 지정되지 않은 경우 layout은 tree에서 제일 가까운 default(즉, 이름이 지정되지 않은) layout을 상속한다.__layout.svelte
에서 상속하는 __layout-root.svelte
와 같이 tree의 default layout에서 상속하는 것이 유용하다.
명시적으로 @default
를 지정하여 /x/y/one
및 형제가 x/__layout.svelte
를 사용하지 않고 app의 default layout 사용하도록 허용하여 이를 수행할 수 있다.
src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
└ __layout-root@default.svelte
default
는 예약된 이름이다. 즉,__layout-default.svelte
파일을 가질 수 없다.
Error pages
page가 로드되지 않으면 (Loading 참조) SvelteKit은 error page를 렌더링 한다.
layout 및 page와 함께 __error.svelte
component를 만들어 이 페이지를 customize 할 수 있다.
예를 들어 src/routes/settings/notifications/index.svelte
가 로드에 실패하면 SvelteKit은 동일한 레이아웃에 src/routes/settings/notifications/__error.svelte
를 렌더링 한다. (존재하는 경우)
그렇지 않으면 부모 layout에서 src/routes/settings/__error.svelte
를 렌더링 하거나 root layout에서 src/routes/__error.svelte
를 렌더링 한다.
SvelteKit은
src/routes/__error.svelte
가 없으면 기본 error page를 제공하지만 직접 만들어 사용하는 게 좋다.
error component에 load
function이 있는 경우 error
및 status
properties가 함께 호출된다.
<script context="module">
/** @type {import('@sveltejs/kit').Load} */
export function load({ error, status }) {
return {
props: {
title: `${status}: ${error.message}`
}
};
}
</script>
<script>
export let title;
</script>
<h1>{title}</h1>
layout은 page store를 통해
error
및status
에 액세스 할 수 있다.서버 측 stack trace는 사용자에게 권한 있는 정보가 노출되는 것을 방지하기 위해 production
error
에서 제거된다.
404s
nested error page는 특정 page를 렌더링 하는 동안 오류가 발생한 경우에만 렌더링 된다.
기존 경로와 일치하지 않는 요청의 경우 SvelteKit은 대신 일반 404를 렌더링 한다.
예를 들어 이러한 경로가 주어지면
src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
/marx-brothers/karl
을 방문하면 /marx-brothers/__error.svelte
가 렌더링 되지 않는다.
Nested error page를 렌더링 하려면 /marx-brothers/\*
요청과 일치하는 경로를 만들고 404를 반환해야 한다.
src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
│ ├ [...path].svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
src/routes/marx-brothers/[...path].svelte :
<script context="module">
/** @type {import('./__types/[...path]').Load} */
export function load({ params }) {
return {
status: 404,
error: new Error(`Not found: /marx-brothers/${params.path}`)
};
}
</script>
Loading
page 또는 layout을 정의하는 component는 component가 생성되기 전에 실행되는 load
function을 export할 수 있다.
이 function은 server-side rendering과 client 양쪽 다 실행되며 page가 rendering 되기 전에 data를 가져오고 처리하여 loading spinner를 방지할 수 있다.
page의 data가 endpoint에서 오는 경우 load
function이 필요하지 않을 수 있다.
예를 들어 다음과 같은 외부 API에서 data를 가져오는 경우와 같이 더 많은 유연성이 필요할 때 유용하다.
src/routes/blog/[slug].svelte :
<script context="module">
/** @type {import('./__types/[slug]').Load} */
export async function load({ params, fetch, session, stuff }) {
const url = `https://cms.example.com/article/${params.slug}.json`;
const response = await fetch(url);
return {
status: response.status,
props: {
article: response.ok && (await response.json())
}
};
}
</script>
<script context="module">
- 이 component가 rendering되기 전에 load
가 실행되기 때문에 필요하다.
component 별 instance인 code는 두 번째 <script>
tag로 이동해야 한다.
endpoints와 마찬가지로 page는 generated type (위의 예에서 ./[slug]
)을 가져와 params
가 올바르게 입력되었는지 확인할 수 있다.
load
는 server와 client 모두에서 load가 실행된다는 점을 제외하고 next.js의 getStaticProps
또는 getServerSideProps
와 유사하다.
위의 예에서 사용자가 이 페이지에 대한 link를 클릭하면 data는 서버를 거치지 않고 cms.example.com
에서 가져온다.
SvelteKit의 load
는 다음과 같은 special properties가 있는 fetch
implementation을 전달받는다.
- server의 cookie에 엑세스 할 수 있다.
- HTTP 호출을 실행하지 않고 app의 자체 endpoint에 대해 요청을 할 수 있다.
- 사용할 때 response의 복사본을 만든 다음 hydration을 위해 initial page load에 포함된 상태로 보낸다.
load
는 page및 layout component(import component가 아님)에만 적용되며 기본 rendering option을 사용하여 server와 browser 모두에서 실행된다.
load block 내에서 호출되는 code :
- native fetch를 사용하는 대신 SvelteKit에서 제공하는 fetch wrapper를 사용해야 한다.
- window, document 또는 browser-specific object를 참조해선 안된다.
- client에 노출될 API key 또는 secret을 직접 참조해서는 안되며 대신 필요한 secret을 사용하는 endpoint를 호출해야 한다.
request 별 state를 global variable에 저장하지 않고 대신 database connection caching 및 holding 같은 cross-cutting에만 사용하는 것이 좋다.
Server의 shared state를 변경하면 현재 client 뿐만 아니라 모든 client에 영향을 미친다.
Input
load
function은 8개의 field (url
, params
, props
, fetch
, session
, stuff
, status
, error
)를 포함하는 object를 전달받는다.load
function은 반응적(reactive)이며 parameter가 변경되면 다시 실행되지만 function에서 사용되는 경우에만 해당한다.
특히 url
, session
또는 stuff
가 function에서 사용되면 값이 변경될 때마다 다시 실행되며 params
의 개별 property들도 마찬가지이다.
function 선언의 구조화 parameter를 사용하는 것으로 간주하기에 충분하다.
Url
url
은 origin
, hostname
, pathname
및 searchParams
(parsed query string을 URLSearchParams
object로 포함)와 같은 property들을 포함하는 URL
의 instance이다.url.hash
는 server에서 사용할 수 없으므로 load
하는 동안 엑세스 할 수 없다.
일부 환경에서는 server-side rendering 중 request header에서 파생된다.
예를 들어 adapter-node를 사용하는 경우 URL이 정확하도록 adapter를 구성해야 할 수 있다.
params
params
는 url.pathname
및 route filename에서 파생된다.
src/routes/a/[b]/[…c]
와 같은 route filename과 /a/x/y/z
의 url.pathname
의 경우 params
object는 다음과 같다.
{
"b": "x",
"c": "y/z"
}
props
load하는 page에 endpoint가 있는 경우 해당 page에서 반환된 data는 leaf component의 load
function 내에서 props
로 엑세스할 수 있다.
endpoint가 없는 layout component 및 page의 경우 props
는 empty object가 된다.
fetch
fetch
는 몇 가지 추가 기능이 있고 native fetch web API와 동일합니다.
- page request에 대한
cooke
및authorization
header를 상속하므로 server에서 자격 증명 요청 만드는데 사용할 수 있다. - server에서 relative request를 할 수 있다. (일반적으로
fetch
는 server context에서 사용될 때 origin이 있는 URL이 필요하다.) - endpoint에 대한 request는 HTTP 호출의 overhead 없이 server-side rendering 중에 handler function으로 직접 이동한다.
- server-side rendering 중에 response가 capture되어 rendering된 HTML에 inline 된다.
- hydration 동안 HTML에서 response를 읽어 일관성을 보장하고 추가 network request를 방지한다.
cookie는 대상 host가 SvelteKit application 또는 해당 application의 보다 구체적인 subdomain 동일한 경우에만 전달된다.
Session
session
은 현재 request와 관련된 server (예 : 현재 사용자)의 data를 전달할 수 있다.
default는 undefined
이다.
사용법을 배우려면 getSession
을 참조한다.
stuff
stuff
는 layout에서 하위 layout 및 page로 전달되며 사용가능하게 만드는데 필요한 다른 모든 것으로 채워질 수 있다.
root __layout.svelte
component의 경우 {}
와 동일하지만 해당 component의 load
function이 stuff
property가 있는 object를 반환하면 후속 load
function에서 사용할 수 있다.
status
status
는 error page를 rendering 할 때 HTTP status code이고 그렇지 않으면 null
이다.
error
error
는 error page를 rendering 할 때 throw 된 (또는 이전 load
에서 반환된) error이고 그렇지 않으면 null
이다.
Output
load
에서 Promise를 반환하면 SvelteKit는 promise가 해결될 때까지 rendering을 지연한다.
return value에는 아래에 나열된 여러 property들이 있으며 모두 선택사항이다. (return value도 마찬가지임)
status
,error
,redirect
및cache
는 error page를 rendering할 때 무시된다.
status
page의 HTTP status code이다.error
를 반환하는 경우 4xx
또는 5xx
응답이어야 한다.redirect
를 반환하는 경우 3xx
응답이어야 한다.
기본값은 200
이다.
error
load
중에 문제가 발생하면 4xx
또는 5xx
status code와 함께 error를 설명하는 string
또는 Error
object를 반환한다.
redirect
page를 redirect 해야 하는 경우 (page가 더 이상 사용되지 않거나 사용자가 로그인해야 하는 경우 등) 3xx
status code와 함께 redirect 되어야 하는 위치가 포함된 string
을 반환한다.
redirect
문자열은 올바르게 인코딩된 URI여야 한다.
absolute URI와 relative URI 모두 허용된다.
cache
cache: {
"maxage": 300,
"private": false
}
page가 cache
되도록 하려면 page의 max age(second)를 설명하는 number
로 설정된 maxage
property를 포함하는 cache object를 반환한다.
선택적으로 resulting Cache-Control
header가 비공개 또는 공개여야 하는지 여부를 나타내는 boolean
private
property도 포함한다. (즉 개별 브라우저와 함께 CDN에서 cache 할 수 있음)
cache.private
가 정의되지 않은 경우 SvelteKit은 다음과 같이 경험적 방법을 사용하여 자동으로 설정한다.load
function가 credentialledfetch
를 수행하거나 page에서session
을 사용하는 경우 page는 private로 간주된다.
이것은 layout이 아닌 page에만 적용된다.
props
load
function이 props
object를 반환하면 props는 렌더링 될 때 component에 전달된다.
stuff
이것은 기존 stuff
와 병합되고 후속 layout및 page component의 load
funcion으로 전달된다.
결합된 stuff
는 page store를 $page.stuff
로 사용하는 component에서 사용할 수 있으며 page가 data를 layout으로 '상향'으로 전달할 수 있는 mechanism을 제공한다.
dependencies
page가 의존하는 URL을 나타내는 문자열 배열로, 이후에 invalidate
와 함께 사용하여 load
를 다시 실행할 수 있다.
custom API client를 사용하는 경우에만 dependencies
에 추가하면 된다.
제공된 fetch function으로 로드된 URL은 자동으로 추가된다.
URL은 로드되는 page에 대해 absolute 또는 relative일 수 있으며 encoded 되어야 한다.
Hooks
optional src/hook.js
(또는 src/hook.ts
또는 src/hook/index.js
) 파일은 서버에서 실행되는 4개의 function (모두 optional)을 export 한다. - handle
, handleError
, getSession
및 exteralFetch
이 파일의 위치는 config.kit.files.hooks로 구성할 수있다.
handle
이 function은 SvelteKit 서버가 request를 수신할 때마다 실행된다. (app이 실행되는 동안 또는 사전 렌더링 중에 발생).
그리고 response를 결정한다.
request를 나타내는 event
object와 SvelteKit의 router를 호출하고 그에 따라 response (페이지 렌더링 또는 endpoint 호출)을 생성하는 resolve
라는 function을 receive 한다.
이를 통해 response header 또는 body를 수정하거나 SvelteKit를 완전히 우회할 수 있다. (예: 프로그래밍 방식으로 endpoint 구현)
src/hook.js :
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
if (event.url.pathname.startsWith('/custom')) {
return new Response('custom response');
}
const response = await resolve(event);
return response;
}
이미 사전 렌더링 된 page를 포함하는 static asset에 대한 요청은 SvelteKit에서 처리되지 않는다.
구현되지 않은 경우 기본 값은 ({event, resolve}) => resolve(event)
이다.
endpoint로 전달되는 요청에 custom data를 추가하려면 아래와 같이 event.locals
Object를 채운다.
src/hook.js :
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
event.locals.user = await getUserInformation(event.request.headers.get('cookie'));
const response = await resolve(event);
response.headers.set('x-custom-header', 'potato');
return response;
}
sequence
helper function을 사용하여 multiple handle
function을 추가할 수 있다.
resolve
는 또한 response가 렌더링되는 방식을 더 잘 제어할 수 있는 두 번째 optional parameter 지원한다.
해당 parameter는 다음 field를 가질 수 있는 object이다.
- `ssr : boolean` (default `true` ) `false` 인 경우 server-side rendering 대신 empty 'shell' page를 렌더링한다.
- `transformPage(opts: { html: string }): string` - HTML에 custom transform 적용
src/hook.js :
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
const response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/admin'),
transformPage: ({ html }) => html.replace('old', 'new')
});
return response;
}
server-side rendering을 비활성화 하면 SvelteKit app이 single-page app 또는 SPA로 효과적으로 바뀐다.
대부분의 경우 이는 권장되지 않는다. (부록 참조)
비활성화하는 것이 정말 적절한지 고려하고 모든 request에 대해가 아니라 선택적으로 비활성화 한다.
handleError
렌더링 중에 error가 발생하면 이 function은 error
및 error를 발생시킨 event
와 함께 호출된다.
이를 통해 data를 tracking service로 보내거나 error를 console에 print하기 전에 formatting을 customize 할 수 있다.
개발 중에 Svelte code의 구문 오류로 error가 발생하면 error 위치를 강조 표시하는 frame
property가 추가된다.
구현되지 않은 경우 SvelteKit은 default formatting으로 error를 기록한다.
src/hook.js :
/** @type {import('@sveltejs/kit').HandleError} */
export async function handleError({ error, event }) {
// example integration with https://sentry.io/
Sentry.captureException(error, { event });
}
handleError
는 uncaught exception의 경우에만 호출된다.
page와 endpoint가 4xx 및 5xx status code로 명시적으로 response할 때는 호출되지 않는다.
getSession
이 function은 event
object를 가져와 client에서 엑세스 할 수 있는 session
object를 반환하므로 사용자에게 안전하게 노출되어야 한다.
SvelteKit server가 page를 렌더링 할 때마다 실행된다.
구현되지 않은 경우 session은 {}
이다.
src/hook.js :
/** @type {import('@sveltejs/kit').GetSession} */
export function getSession(event) {
return event.locals.user
? {
user: {
// only include properties needed client-side —
// exclude anything else attached to the user
// like access tokens etc
name: event.locals.user.name,
email: event.locals.user.email,
avatar: event.locals.user.avatar
}
}
: {};
}
session
은 serializable 해야 한다.
즉, function 또는 custom class와 같은 것을 포함해서는 안되며 built-in JavaScript data type만 포함해야 한다.
externalFetch
이 function을 사용하면 server에서 (또는 pre-rendering 중에) 실행되는 load
function 내에서 발생하는 외부 resource에 대한 fetch
request를 modify (또는 replace) 할 수 있다.
예를 들어 load
function은 사용자가 각 page로 client-side navigation을 수행할 때 https://api.yourapp.com
과 같은 public URL에 요청을 할 수 있지만 SSR 중에는 API와 public internet 사이에 있는 proxy 및 load balancer를 포함하여 API를 직접 호출 하는 것이 합리적일 수 있다.
/** @type {import('@sveltejs/kit').ExternalFetch} */
export async function externalFetch(request) {
if (request.url.startsWith('https://api.yourapp.com/')) {
// clone the original request, but change the URL
request = new Request(
request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
request
);
}
return fetch(request);
}
Modules
SvelteKit은 application에서 사용할 수 있는 많은 module을 만든다.
$app/env
import { browser, dev, prerendering } from '$app/env';
browser
app이 브라우저에서 실행 중인 경우 true이다.
dev
dev server가 실행 중인지 여부.
이는 NODE_ENV
또는 MODE
에 해당한다고 보장되지 않는다.
const dev: boolean;
prerendering
prerendering인 경우 true
, 그 외엔 false
이다.
const prerendering: boolean;
$app/navigation
import {
afterNavigate,
beforeNavigate,
disableScrollHandling,
goto,
invalidate,
prefetch,
prefetchRoutes
} from '$app/navigation';
afterNavigate
page가 mount 되고 SvelteKit이 새 URL로 이동하지만 해당 component가 남아있을 때마다 실행되는 lifecycle function이다.
function afterNavigate(
fn: (navigation: { from: URL | null; to: URL }) => void
): void;
beforeNavigate
링크를 클릭하거나 goto
를 호출하거나 브라우저의 뒤로/앞으로 컨트롤을 사용하여 새 URL(내부 또는 외부)로 이동하기 전에 트리거하는 navigation interceptor
이는 탐색이 완료되거나 예정된 URL을 조회하는 것을 조건부로 방지하려는 경우 유용하다.
function beforeNavigate(
fn: (navigation: { from: URL; to: URL | null; cancel: () => void }) => void
): void;
disableScrollHandling
page가 탐색 후 업데이트 될 때 호출되는 경우(예: onMount
또는 aftgerNavigate
또는 action) 이는 SvelteKit 의 built-in scroll handling을 비활성화 한다.
이는 사용자의 기대치를 깨트리기 때문에 일반적으로 권장하지 않는다.
function disableScrollHandling(): void;
goto
SvelteKit이 지정된 url
을 탐색할 때 (또는 탐색에 실패하는 경우 Promise가 거부할 때) 해결되는 Promise를 반환한다.
function goto(
url: string | URL,
opts?: {
replaceState?: boolean;
noscroll?: boolean;
keepfocus?: boolean;
state?: any;
}
): Promise<void>;
invalidate
현재 active page에 속한 load
function이 문제의 resource를 fetch
하는 경우 다시 실행하거나 invalidated resource가 page 자체인 경우 page endpoint에서 데이터를 다시 가져온다.
이후에 page가 업데이트 될 때 resolve하는 Promise
를 반환한다.
function invalidate(
dependency: string | ((href: string) => boolean)
): Promise<void>;
prefetch
프로그래밍 방식으로 주어진 page를 미리 가져온다.
- page의 code가 load되었는지 확인하고
- 적절한 옵션으로 page의 load function을 호출한다.
이것은 사용자가 sveltekit:prefetch
를 사용하여 <a>
element를 탭하거나 마우스를 over할 때 SvelteKit이 trigger하는 것과 동일한 동작이다.
다음 navigation이 href
인 경우 load에서 반환된 값이 사용되어 navigation이 즉시 이루어진다.
prefetch가 완료되면 resolve하는 Promise를 반환한다.
function prefetch(href: string): Promise<void>;
prefetchRoutes
아직 가져오지 않은 route에 대한 code를 프로그래밍 방식으로 미리 가져온다.
일반적으로 subsequent navigation 속도를 높이기 위해 이것을 호출할 수 있다.
argument가 제공되지 않으면 모든 route를 fetch하고 그렇지 않으면 /about
(src/routes/about.svelte
와 일치) 또는 /blog/*
(/routes/blog/[slug].svelte
와 일치)와 같은 일치하는 pathname으로 route를 지정할 수 있다.
prefetch와 달리 개별 page에 대해 load를 호출하지 않는다.
route가 prefetch 되었을 때 resolve되는 Promise를 반환한다.
function prefetchRoutes(routes?: string[]): Promise<void>;
$app/paths
import { base, assets } from '$app/paths';
assets
config.kit.paths.assets
와 일치하는 absolute path이다.
config.kit.paths.assets
값이 지정되면 asset이 최종 URL에 아직 존재하지 않기 때문에vite dev
또는vite preview
중에/_svelte_kit_assets
로 대체된다.
const assets: `https://${string}` | `http://${string}`;
base
config.kit.paths.base
와 일치하는 문자열이다.
빈 문자열이 아닌 한 /
로 시작되어야 하지만 /
로 끝나지 않아야 한다. (예: /base-path
)
const base: `/${string}`;
$app/stores
import { getStores, navigating, page, session, updated } from '$app/stores';
store는 context의 역할을 한다.
root component의 context에 추가된다.
즉, session
과 page
는 동일한 서버에서 동시에 처리되는 여러 request 간에 공유되는 것이 아니라 서버의 각 request에 고유하므로 session
에 사용자별 데이터를 포함하는것이 안전하다.
그 때문에 component 초기화 중에 store를 subscribe 해야 한다. (component에서 $page
처럼 store 값을 참조하는 경우 자동으로 발생함)
getStores
getContext
관련 편의 function.
component 초기화 중에 호출해야 한다.
어떤 이유로 component가 mount 될 때까지 store subscription을 연기해야 하는 경우에만 이것을 사용한다.
function getStores(): {
navigating: typeof navigating;
page: typeof page;
session: typeof session;
updated: typeof updated;
};
navigating
readable store.
navigation이 시작되면 그 값은 { from: URL, to: URL }
이고 navigating이 끝나면 null로 되돌아간다.
const navigating: Readable<Navigation | null>;
page
값에 page data가 포함된 readable store.
const page: Readable<Page>;
session
초기 값이 getSession
에서 반환된 값인 writable store.
쓸 수는 있지만 변경 사항이 서버에 유지되지는 않는다.
사용자가 직접 구현해야 함.
const session: Writable<App.Session>;
updated
초기 값이 false
인 readable store.version.pollInterval
이 0이 아닌 값이면 SvelteKit은 app의 새 버전을 polling하고 하나를 감지하면 store 값을 true
로 업데이트한다.update.check()
는 polling에 관계없이 즉시 check를 강제 실행한다.
const updated: Readable<boolean> & { check: () => boolean };
$lib
이는 src/lib
또는 config.kit.files.lib
으로 지정된 디렉토리에 대한 간단한 alias이다.../../../../
같은 처리 없이 일반 component 및 utility module에 엑세스 할 수 있다.
$service-worker
import { build, files, prerendered, version } from '$service-worker';
이 module은 service worker만 사용할 수 있다.
build
Vite에서 생성된 파일을 나타내는 URL string array로 cache.addAll(build)
로 캐싱하기에 적합하다.
const build: string[];
files
static
directory 또는 config.kit.files.assets
에 의해 지정된 모든 디렉토리의 파일을 나타내는 URL string array이다.config.kit.serviceWorker.files
를 사용하여 static directory에서 포함한 파일을 customize 할 수 있다.
const files: string[];
prefendered
미리 렌더링된 page 및 endpoint에 해당하는 pathname의 array.
const prerendered: string[];
version
config.kit.version
을 참조한다.
service worker 내부에 고유한 cache name을 생성하는데 유용하므로 나중에 app을 배포하면 이전 cache를 무효화할 수 있다.
const version: string;
@sveltejs/kit/hooks
sequence
middleware 같은 방식으로 여러 handle
호출을 sequencing하기 위한 helper function이다.
src/hook.js :
import { sequence } from '@sveltejs/kit/hooks';
/** @type {import('@sveltejs/kit').Handle} */
async function first({ event, resolve }) {
console.log('first pre-processing');
const result = await resolve(event);
console.log('first post-processing');
return result;
}
/** @type {import('@sveltejs/kit').Handle} */
async function second({ event, resolve }) {
console.log('second pre-processing');
const result = await resolve(event);
console.log('second post-processing');
return result;
}
export const handle = sequence(first, second);
위의 예는 다음과 같이 print 된다.
first pre-processing
second pre-processing
second post-processing
first post-processing
function sequence(...handlers: Handle[]): Handle;
@sveltejs/kit/node
node와 유사한 환경의 adapter에서 사용하는 utility들.
getRequest
function getRequest(
base: string,
request: import('http').IncomingMessage
): Promise<Request>;
setResponse
function setResponse(
res: import('http').ServerResponse,
response: Response
): void;
@sveltejs/kit/node/polyfills
native implementation을 제공하지 않는 환경의 adapter에서 사용하는 fetch
및 관련 interface용 polyfill이다.
installPolyfills
다양한 web API를 전역으로 사용할 수 있도록 한다.
crypto
fetch
Headers
Request
Response
function installPolyfills(): void;
@sveltejs/kit/vite
sveltekit
SvelteKit Vite plugin을 반환한다.
function sveltekit(): Plugin[];
Service workers
service worker는 app 내에서 network request를 처리하는 proxy server 역할을 한다.
이렇게 하면 app을 offline에서 작동할 수 있지만 offline 지원이 필요하지 않더라도 (또는 구축 중인 app type 때문에 현실적으로 구현할 수 없는 경우에도) service worker를 사용하여 구축된 JS 및 CSS를 prefetch하여 navigation 속도를 높일 수 있다.
SvelteKit에서 src/service-worker.js
file (또는 src/service-worker.ts
또는 src/service-worker/index.js
등)이 면 Vite로 빌드되고 자동으로 등록된다.
service worker를 고유한 logic으로 등록해야 하는 경우 자동 등록을 비활성화 할 수 있다.
(예: 사용자에게 업데이트 요청, 정기적 업데이트 구성, workbox
사용 등)
service worker의 위치를 변경하고 프로젝트 구성에서 자동 등록을 비활성화할 수 있다.
service worker 내에서 $service-worker
module에 엑세스할 수 있다.
(브라우저는 아직 이 context에서 import
를 지원하지 않기 때문에) bundle로 제공되어야 하고 client-side app의 build manifest에 따라 달라지기 때문에 service worker는 development가 아닌 production guild에서만 작동한다.
로컬에서 테스트하려면 vite preview
를 사용한다.
Anchor options
sveltekit:prefetch
SvelteKit은 코드 분할을 사용하여 app을 작은 chunk로(route당 하나씩) 분할하여 빠른 시작시간을 보장한다.
src/routes/blog/[slug].svelte
예제와 같이 dynamic route의 경우 충분하지 않다.
blog post를 렌더링 하려면 해당 데이터를 가져와야 하며 slug가 무엇인지 알기전까지는 그렇게 할 수 없다.
최악의 경우 브라우저가 서버에서 데이터가 돌아올 때까지 대기할 때 지연이 발생할 수 있다.
데이터를 미리 가져옴으로써 이를 완화할 수 있다.
link에 sveltekit:prefetch
attribute를 추가하면…
<a sveltekit:prefetch href="blog/what-is-sveltekit">What is SvelteKit?</a>
… click
event가 navigation을 trigger 할 때까지 기다리지 않고 사용자가 (데스크톱에서) link 위로 mouse를 가져가거나 (모바일에서) link를 터치하면 SvelteKit이 이 page의 load
function을 실행하도록 한다.
일반적으로 이것은 우리에게 몇 백 millisecond를 추가로 소비한다.
이는 lag을 느끼는 user interface와 빠르게 느껴지는 user interface의 차이이다.
router
setting이 false
이면 prefetch가 동작하지 않는다.
$app/navigation
에서 프로그래밍 방식으로 prefetch
를 호출할 수도 있다.
sveltekit:reload
기본적으로 SvelteKit runtime은 <a>
element에 대한 click을 가로채고 page route 중 하나와 일치하는 상대 (same-origin) URL에 대한 normal browser navigation을 우회한다.
때때로 SvelteKit에 특정 link가 normal browser navigation에 의해 처리되어야 한다고 알려야 한다.
예를 들어 SvelteKit app의 일부가 아닌 domain의 다른 page에 연결하거나 endpoint에 연결하는 경우가 있다.
link에 sveltekit:reload
attribute를 추가하면…
<a sveltekit:reload href="path">Path</a>
…link를 클릭하면 브라우저가 전체 page를 다시 load하여 navigate 한다.
rel="external"
attribute가 있는 link는 동일한 처리를 받는다.
또한 prerendering 중에는 무시된다.
sveltekit:noscroll
internal link로 이동할 때 SvelteKit는 브라우저의 기본 navigation 동작을 반영한다.
사용자가 page의 맨 위에 있도록 scroll 위치를 0.0으로 변경한다.
(link에 #hash
가 포함되어 있지 않으면 일치하는 ID가 있는 요소로 scroll 된다.)
경우에 따라 이 동작을 비활성화할 수 있다.
link에 sveltekit:noscroll
attribute를 추가하면…
<a href="path" sveltekit:noscroll>Path</a>
...link를 클릭한 후 scroll을 방지한다.
Events
SvelteKit는 app이 hydrate 되면 window
object에서 sveltekit:start
CustomEvent를 emit한다.
아마도 사용할 필요는 없지만 (예를 들어) integration test의 맥락에서 유용할 수 있다.
Adapters
SvelteKit app을 배포하려면 먼저 배포 대상에 맞게 조정해야 한다.
apapter는 빌드된 app을 input으로 사용하고 배포를 위한 output을 생성하는 작은 plugin이다.
기본적으로 프로젝트는 production environment를 감지하고 가능한 경우 적절한 adapter를 선택하는 @sveltejs/adapter-auto
를 사용하도록 구성된다.
platform이 (아직) 지원되지 않는 경우 custom adapter 를 설치하거나 작성해야 할 수 있다.
새로운 environment에 대한 지원 추가 정보는 adapter-auto README를 참조하면 된다.
Supported environments
SvelteKit는 공식적으로 지원되는 여러 adapter를 제공한다.
default adapter인 adapter-auto
를 사용하여 다음 platform에 deploy할 수 있다.
adapter-cloudflare
로 Cloudflare Pagesadapter-netlify
로 Netlifyadapter-vercel
로 Vercel
Node.js
간단한 node server를 생성하려면 @sveltejs/adapter-node
package를 설치하고 svelte.config.js
를 업데이트 한다.
import adapter from '@sveltejs/adapter-node';
이를 통해 vite build
는 build
directory 내부에 자체 포함된 node app을 생성한다.
custom output directory 같은 옵션을 adapter에 전달할 수 있다.
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
adapter: adapter({ out: 'my-output-directory' })
}
};
####Static sites
대부분의 adapter는 site의 prerendering 가능한 page에 대해 static HTML을 생성한다.
경우에 따라 전체 app을 prerendering 할 수 있다.
이 경우 @sveltejs/adapter-static
을 사용하여 모든 page에 대한 static HTML을 생성할 수 있다.
fully static site는 GitHub Pages와 같은 static host를 포함하여 다양한 platform에서 호스팅 될 수 있다.
import adapter from '@sveltejs/adapter-static';
또한 adapter-static
을 사용하여 fallback page를 지정하여 single-page apps (SPAs)을 생성할 수 있다.
trailingSlash가 환경에 적절하게 설정되어 있는지 확인해야 한다.
host가/a
에 대한 요청을 받았을 때/a.html
을 렌더링하지 않으면 대신/a/index.html
을 생성하기 위해trailingSlash: 'always'
를 설정해야 한다.
Platform-specific context
일부 adapter는 request에 대한 추가 정보에 엑세스할 수 있다.
예를 들어 Cloudflare worker는 KV namespace 등이 포함된 env
object에 엑세스할 수 있다.
이것은 platform
property로 hook 및 endpoint에서 사용되는 RequestEvent
에 전달할 수 있다.
자세한 내용은 각 adapter의 documentation을 참조하면 된다.
Community adapters
다른 platform을 위한 추가 community-provided adapter가 있다.
package manager로 관련 adapter를 설치한 후 svelte.config.js
를 업데이트 하면 된다.
import adapter from 'svelte-adapter-[x]';
Writing custom adapters
사용하려는 것과 유사한 platform에 대한 adapter source를 보고 starting point로 복사하는 것이 좋다.
adapter
package는 adapter를 생성하는 다음 API를 구현해야 한다.
/** @param {AdapterSpecificOptions} options */
export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
const adapter = {
name: 'adapter-package-name',
async adapt(builder) {
// adapter implementation
}
};
return adapter;
}
Adapter
type및 해당 parameter는 types/config.d.ts에서 사용할 수 있다.
adapt
method 내에는 adapter가 수행해야 하는 여러 가지 작업이 있다.
- build directory 지우기
builder.writeClient
,builder.writePrerendered
,builder.writeServer
및builder.writeStatic
을 사용하여 SvelteKit output 작성- ouput code
${builder.getServerDirectory()}/index.js
에서Server
importbuilder.generateManifest({ relativePath })
로 생성된 manifest를 사용하여 app을 instance화- platform의 request를 listen 하고 필요한 경우 standard request로 변환하고
server.respond(request, { getClientAddress })
function을 호출하여 response를 생성하고 이에 응답 server.respond
에 전달된platform
option을 통해 platform별 정보를 SvelteKit에 노출- 필요한 경우 대상 platform에서 작동하도록 globally shims
fetch
를 수행
SvelteKit은node-fetch
를 사용할 수 있는 platform에@sveltejs/kit/install-fetch
helper를 제공함 - 필요한 경우 대상 platform의 dependencies를 설치할 필요가 없도록 output을 bundle로 묶는다.
- 사용자가 static file과 생성된 JS/CSS를 대상 platform의 올바른 위치에 둔다.
가능한 경우 .svelte-kit/[adapter-name]
아래에 중간 output을 두고 build/
directory 아래에 adapter output을 두는 것이 좋다.
adapter API는 1.0전에 변경될 수도 있다.
Page options
기본적으로 SvelteKit는 서버에서 먼저 모든 component를 렌더링하고 HTML로 client에 보낸다.
그런 다음 브라우저에서 component를 다시 렌더링하여 hydration이라는 프로세스에서 interactive로 만든다.
이러한 이유로 component가 두 위치에서 모두 실행될 수 있는지 확인해야 한다.
그런 다음 SvelteKit는 subsequent navigation을 가지는 router를 초기화한다.
app별 또는 page 별로 이들 각각을 제어할 수 있다.
각 page별 설정은 context="module"
을 사용하여 layout이 아닌 페이지에만 적용된다.
둘 다 지정하면 충돌 시 page별 설정이 app별 설정보다 우선 적용된다.
router
SvelteKit에는 navigation(사용자가 링크를 클릭하거나 뒤로/앞으로 버튼과 상호작용)을 가로채고 브라우저가 reload하여 navigation을 처리하도록 하는 대신 page 내용을 업데이트 하는 client-side router가 포함되어 있다.
특정 상황에서는 app-wide browser.router
config option 또는 page-level router
export를 사용하여 client-side routing을 비활성화해야 할 수 있다.
<script context="module">
export const router = false;
</script>
router가 이미 active 상태인지 여부에 관계없이 이 page의 navigation에 대해 client-side routing이 비활성화된다.
hydrate
일반적으로 SvelteKit는 서버에서 렌더링된 HTML을 interactive page로 hydrate 한다.
일부 page에는 JavaScript가 전혀 필요하지 않다.
많은 블로그 게시물과 '정보' 페이지가 이 범주에 속한다.
이러한 경우 app-wide browser.hydrate
config option또는 page 수준의 hydrate
export를 사용하여 app이 boot up 할 때 hydrate를 건너뛸 수 있다.
<script context="module">
export const hydrate = false;
</script>
hydrate와 router가 모두 false이면 SvelteKit은 page에 JavaScript를 전혀 추가하지 않는다.
handle에서 server-side rendering이 비활성화 된 경우 hydrate는 true여야 하며 그렇지 않으면 content가 rendering되지 않는다.
prerender
최소한 app의 일부 page는 빌드시 생성된 간단한 HTML 파일로 표시될 수 있다.
이러한 page는 미리 렌더링할 수 있다.
prerender
annotation이 있는 모든 page에 대해 prerendering이 자동으로 발생한다.
<script context="module">
export const prerender = true;
</script>
또는 config.kit.prerender.default
를 true
로 설정하고 prerendering 불가로 명시적으로 표시된 page를 제외한 모든 것을 prerendering 할 수 있다.
script context="module">
export const prerender = false;
</script>
전체 app이 prerendering에 적합한 경우
adapter-static
을 사용할 수 있다.
그러면 모든 static webserver에서 사용하기에 적합한 파일이 출력된다.
reprenderer는 app의 root에서 시작하여 찾은 prerendering 가능한 page에 대한 HTML을 생성한다.
각 page는 prerendering 후보인 다른 page를 가리키는 <a>
element를 검색한다.
이 때문에 일반적으로 엑세스 해야 하는 page를 지정할 필요가 없다.
prerenderer가 엑세스해야 하는 page를 지정해야 하는 경우 prerender configuration의 entries
option 사용하여 지정할 수 있다.
when not to prerender
기본 규칙은 다음과 같다.
page를 prerendering 할 수 있으려며 page를 직접 방문하는 두명의 사용자가 server에서 동일한 contents를 가져와야한다.
모든 page가 prerendering에 적합한 것은 아니다.
rerendering된 모든 contents는 모든 사용자에게 표시된다.
물론 prerendering 된 page의onMount
에서 개인화된 data를 가져올 수 있지만 빈 초기 content 또는 load indicator가 포함되므로 사용자 경험이 저하될 수 있다.
이전의 src/routes/blog/[slug].svelte
예제와 같이 page parameter를 기반으로 data를 로드하는 page를 prerendering 할 수 있다.
prerenderer는 load
내부에서 이루어진 request를 가로채므로 src/routes/blog/[slug].json.js
에서 제공되는 data도 capture 된다.
prerendering 중에 url.searchParams
에 엑세스하는 것은 금지되어 있다.
사용해야 하는 경우 browser (예: onMount
)에서만 사용해야 한다.
Route conflicts
prerendering은 filesystem에 쓰기 때문에 directory와 file이 같은 이름을 갖도록 하는 두 개의 endpoint를 가질 수 없다.
예를 들어 src/routes/foo/index.js
및 src/routes/foo/bar.js
는 foo
및 foo/bar
를 생성하려고 시도하지만 이는 불가능하다.
이러한 이유로 항상 file extension을 포함하는 것이 좋다./src/routes/foo/index.json.js
및 src/routes/foo/bar.json.js
는 foo.json
및 foo/bar.json
이 된다.
json 파일이 조화롭게 나란히 존재한다.
page의 경우 foo
대신 foo/index.html
을 작성하여 이 문제를 우회한다.
packaging
svelte-kit package
는 현재 실험적인 기능이며 semantic versioning 규칙이 적용되지 않는다.
이전 버전과 호환되지 않는 변경 사항 향후 release에서 발생할 수 있다.
SvelteKit을 사용하여 component와 app을 빌드할 수 있다.
app을 만들 때 src/routes
의 내용은 공개 대상이다.src/lib
에는 app의 내부 라이브러리가 포함되어 있다.
SvelteKit component library는 src/lib
이 공개 비트라는 점을 제외하고 SveltKit app과 구조가 정확히 동일하다.src/routes
는 library와 함께 제공되는 document 또는 demo site일 수 있고 개발 중에 사용하는 sandbox일 수도 있다.
svelte-kit package
를 실행하면 src/lib
의 내용을 가져와 다음을 포함하는 (configure 가능한) package directory를 생성한다.
- custom
include
/exclude
option을 구성하지 않는 한src/lib
의 모든 파일.
component는 사전 처리되고 TypeScript 파일은 JavaScript로 변환된다. - Svelte, JavaScript 및 TypeScript file에 대해 생성되는 Type definition (
d.ts
file)
이를 위해typescript >= 4.0.0
및svelte2tsx >= 0.4.1
을 설치해야 한다.
type definition은 implementation 옆에 배치되고 직접 작성한 d.ts file은 그대로 복사된다.
생성을 비성화 할 수 있지만 권장하지 않는다. "script"
field를 제외한 모든 field가 있는 project root에서 복사한package.json
"dependencies"
field가 포함되어 있다.
즉 document 또는 demo site 에만 필요한 package를"devDependencies"
에 추가해야 한다."type": "module"
및"exports"
field가 원본 파일에 정의되지 않은 경우 추가된다.
"export"
field에는 package의 entry point가 포함된다.
기본적으로 src/lib
에 있는 모든 파일은 underscore로 시작하지 않는 한 (또는 underscore로 시작하는 디렉토리에 있지 않는 한) entry point로 처리되지만 이 동작을 구성할 수 있다.src/lib/index.js
또는 src/lib/index.svelte
파일이 있는 경우 package root로 처리된다.
예를 들어 src/lib/Foo.svelte
component와 이를 re-export한 src/lib/index.js
module이 있는 경우 library consumer는 다음 중 하나를 수행할 수 있다.
import { Foo } from 'your-library';
import Foo from 'your-library/Foo.svelte';
Publishing
생성된 package를 publish하려면
npm publish ./package
위의 ./package
는 생성된 디렉토리 이름을 참조하므로 custom package.dir
을 구성하는 경우 그에 따라 변경한다.
Caveats
이것은 비교적 실험적인 기능이며 아직 완전히 구현되지 않았다.
Svelte 파일 (사전처리됨) 및 TypeScript 파일 (JavaScript로 변환됨)을 제외한 모든 파일은 있는 그대로 복사된다.
Command Line Interface
SvelteKit project는 Vite를 사용한다.
즉, 대부분의 경우 해당 CLI를 사용한다. (npm run dev/build/preview
script를 통해서지만)
vite dev
- development server 시작vite build
- app의 production version 빌드vite preview
- production version을 로컬에서 실행
그러나 SvelteKit에는 배포 가능한 package를 만들고 초기화하기 위한 자체 CLI가 포함되어 있다.
svelte-kit package
svelte-kit package
는 현재 실험적인 기능이며 Semantic Versioning 규칙이 적용되지 않는다.
이전 버전과 호환되지 않는 변경 사항은 향후 release에서 발생할 수 있다.
packaging을 참조하세요. svelte-kit package
는 다음 option을 허용한다.
-w
/--watch
-src/lib
의 파일에서 변경 사항을 확인하고 package를 다시 빌드한다.
svelte-kit sync
svelte-kit sync
는 type 및 tsconfig.json
과 같은 project에 대해 생성된 파일을 만든다.
새 프로젝트를 만들면 prepare
script로 목록화되고 npm lifecycle의 일부로 자동으로 실행되므로 일반적으로 이 명령을 실행할 필요가 없다.
Configuration
project configuration은 svelte.config.js
파일에 있다.
모든 값은 optional이다.
default 값이 있는 전체 option list는 다음과 같다.
svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
// options passed to svelte.compile (https://svelte.dev/docs#compile-time-svelte-compile)
compilerOptions: {},
// an array of file extensions that should be treated as Svelte components
extensions: ['.svelte'],
kit: {
adapter: undefined,
alias: {},
appDir: '_app',
browser: {
hydrate: true,
router: true
},
csp: {
mode: 'auto',
directives: {
'default-src': undefined
// ...
}
},
moduleExtensions: ['.js', '.ts'],
files: {
assets: 'static',
hooks: 'src/hooks',
lib: 'src/lib',
params: 'src/params',
routes: 'src/routes',
serviceWorker: 'src/service-worker',
template: 'src/app.html'
},
inlineStyleThreshold: 0,
methodOverride: {
parameter: '_method',
allowed: []
},
outDir: '.svelte-kit',
package: {
dir: 'package',
emitTypes: true,
// excludes all .d.ts and files starting with _ as the name
exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
files: () => true
},
paths: {
assets: '',
base: ''
},
prerender: {
concurrency: 1,
crawl: true,
default: false,
enabled: true,
entries: ['*'],
onError: 'fail',
origin: 'http://sveltekit-prerender'
},
routes: (filepath) => !/(?:(?:^_|\/_)|(?:^\.|\/\.)(?!well-known))/.test(filepath),
serviceWorker: {
register: true,
files: (filepath) => !/\.DS_Store/.test(filepath)
},
trailingSlash: 'never',
version: {
name: Date.now().toString(),
pollInterval: 0
}
},
// options passed to svelte.preprocess (https://svelte.dev/docs#compile-time-svelte-preprocess)
preprocess: null
};
export default config;
adapter
vite build
를 실행할 때 실행하고 출력이 다른 platform에 대해 변환되는 방식을 결정한다.
adapter 문서를 참조하면 된다.
alias
import
문의 값을 바꾸는 데 사용되는 0 개 이상의 alias를 포함하는 object이다.
이러한 alias는 Vite 및 TypeScript에 자동으로 전달된다.
예를 들어 다음과 같이 component
및 utils
folder alias를 추가할 수 있다.
svelte.config.js :
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
alias: {
$components: 'src/components',
$utils: 'src/utils'
}
}
};
built-in
$lib
alias는 packaging에 사용되므로config.kit.files.lib
에 의해 제어된다.
appDir
빌드된 JS 및 CSS (및 imported assets)가 제공되는 path.assets
에 대한 relative direcotry이다.
(파일 이름에는 content-based hash가 포함되어 있어 무기한 캐시될 수 잇다.)/
로 시작하거나 끝나서는 안된다.
browser
다음 boolean
value 중 0개 이상을 포함하는 object
hydrate
- client-side app으로 server rendering HTML을 hydrate 할지 여부.
(app 전체에서 이것을false
로 설정하는 경우는 드물다.)router
- client-side router app 전체를 활성화하거나 비활성화
csp
다음 값 중 0개 이상을 포함하는 object
mode
- 'hash', 'nonce' 또는 'auto'directives
-[directive]: value[]
object 쌍reportOnly
- CSP report-only mode에 대한[directive]: value[]
object 쌍
Content Security Policy configuration.
CSP resource를 로드할 수 있는 위치를 제한하여 cross-site scripting (XSS) 공격으로부터 사용자를 보호하는데 도움이 된다.
예를 들어 아래와 같이 구성하면…
svelte.config.js :
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
csp: {
directives: {
'script-src': ['self']
},
reportOnly: {
'script-src': ['self']
}
}
}
};
export default config;
...외부 사이트에서 script loading을 방지한다.
SvelteKit는 생성하는 모든 inline style 및 script에 대해 (mode
로 지정된) nonce 또는 hash 로 지정된 지시문을 보강한다.
page가 prerendering 되면 CSP header가 <meta http-equiv>
tag를 통해 추가된다.
(이 경우 frame-ancestors
, report-uri
및 sandbox
지시문은 무시된다.)
mode
가'auto'
면 SvelteKit은 동적으로 rendering된 page를 nonces로 사용하고 미리 prerendering된 page에 hash를 사용한다.
reprendering 된 page에 nonce를 사용하는 것은 안전하지 않으므로 금지된다.
대부분의 Svelte transition은 inline
<style>
element를 생성하여 작동한다.
app에서 이를 사용하는 경우style-src
지시문을 지정하지 않은 상태로 두거나unsafe-inline
을 추가해야 한다.
modeExtensions
SvelteKit이 module로 취급할 파일 확장자의 배열이다.config.extension
또는 config.kit.moduleExtensions
와 일치하지 않는 확장자를 가진 파일은 router에서 무시된다.
files
다음 string
value 중 0 개 이상을 포함하는 object
assets
-favicon.ico
또는manifest.json
과 같이 stable URL을 갖고 처리를 거치지 않아야 하는 static file을 넣을 장소hooks
- hook module의 위치lib
- codebase 전체에서$lib
로 엑세스 할 수 있는 app의 내부 libraryparams
- parameter matcher를 포함하는 디렉토리routes
- app의 구조를 정의하는 파일serviceWorker
- service worker의 entry point 위치template
- HTML response를 위한 template의 위치
inlineStyleThreshold
HTML head의 <style>
block 내부에 CSS를 inline 한다.
이 옵션은 inline 할 CSS 파일의 최대 길이를 지정하는 숫자이다.
page에 필요하고 이 값보다 작은 모든 CSS 파일은 <style>
block에 병합되고 inline된다.
그 결과 초기 요청이 줄어들고 First Contentful Paint score가 향상될 수 있다.
그러나 더 큰 HTML output을 생성하고 browser cache의 효율성을 감소시킨다.
사용하는 것이 좋다.
methodOverride
HTTP Method Override를 참고.
다음 중 0 개 이상을 포함하는 object
parameter
- 의도한 method value를 전달하는데 사용할 query parameter 이름allowed
- 원래 request method를 override 할 때 사용할 수 있는 HTTP method array
outDir
SvelteKit이 dev
및 build
중에 파일을 쓰는 디렉토리이다.
version control에서 이 디렉토리를 제외해야 한다.
package
package 생성과 관련된 옵션
dir
- output directoryemitTypes
- 기본적으로svelte-kit package
는.d.ts
파일 형식으로 package type을 자동으로 생성한다.
type 생성은 configurable하지만 ecosystem quality를 위해서는 항상 type을 생성하는 것이 좋다.false
로 설정할 때 타당한 이유가 있는지 확인해야 한다. (예를 들어 handwritten type definition을 제공하려는 경우)exports
-(filepath: string) => boolean
type의 function.true
이면 filepath가package.json
의export
field에 포함된다.package.json
source의 기존 값은 우선적으로 원래export
field의 값과 병합된다.files
-(filepath: string) => boolean
type의 function.true
인 경우 file이 처리되고dir
에 지정된 최종 output folder로 복사된다.
advanced filepath
matching을 위해 globbing library와 함께 export
및 file
option을 사용할 수 있다.
svelte.config.js :
import mm from 'micromatch';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
package: {
exports: (filepath) => {
if (filepath.endsWith('.d.ts')) return false;
return mm.isMatch(filepath, ['!**/_*', '!**/internal/**']);
},
files: mm.matcher('!**/build.*')
}
}
};
export default config;
paths
다음 string
값 중 0개 이상을 포함하는 object
assets
- app의 파일이 제공되는 absolute path.
이는 파일이 일종의 storage bucket에서 제공되는 경우에 유용하다.base
- 빈 문자열이 아닌 한 시작해야 하지만/
로 끝나지 않는 root-relative path (예:/base-path
).
이는 app이 제공는 위치를 지정하고 app이 root가 아닌 경로에 있도록 허용한다.
prerender
다음 중 0개 이상을 포함하는 object
concurrency
- 동시에 prerendering할 수 있는 page 수.
JS는 single-thread이지만 prerendering 성능이 network에 종속된 경우 (예: 원격 CMS에서 content load) network response를 기다리는 동안 다른 작업을 처리하여 속도를 높일 수 있다.crawl
- SvelteKit이 seed page의 link를 따라 prerendering 할 page를 찾아야 하는지 여부를 결정한다.default
- 포함하지 않은 page를 prerendering하려면true
로 설정한다.export const prerender = false
enabled
- prerendering을 완전히 비활성화 하려면false
로 설정한다.entries
- prerendering하거나 crowling을 시작할 page의 배열 (crawl: true
인 경우).*
string은 모든 non-dynamic routes (즉,[parameters]
가 없는 page)를 포함다.onError
'fail'
- (기본값) link를 따라갈 때 routing error가 발생하면 build에 실패한다.'continue'
- routing error가 발생해도 빌드를 계속한다.function
- crawling 세부 정보를 기반으로 빌드를 기록,throw
및 실패하거나 선택한 다른 작업을 수행할 수 있는 custom error handler
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter(),
prerender: {
onError: ({ status, path, referrer, referenceType }) => {
if (path.startsWith('/blog')) throw new Error('Missing a blog page!');
console.warn(
`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`
);
}
}
}
};
export default config;
origin
- prerendering 중url.origin
의 값.
렌더링된 content에 포함된 경우 유용하다.
routes
어떤 파일이 경로를 생성하고 어떤 파일이 private module로 취급되는지를 결정하는 (filepath => string) => boolean
function.
serviceWorker
다음 값 중 0 개 이상을 포함하는 object
register
-false
로 설정하면 automatic service worker 등록이 비활성화 됨files
-(filepath: string) => boolean
type의 functiontrue
면 지정된 파일을$service-worker.files
에서 사용할 수 있으며 그렇지 않으면 제외됨
trailingSlash
URL을 확인할 때 후행(trailing) slash를 제거, 추가 또는 무시할 지 여부
(이는 endpoint가 아니니 page에만 적용됨)
'never'
-/x/
를/x
로 redirect'always'
-/x
를/x/
로 redirect'ignore'
- 후행 slash를 자동으로 추가하거나 제거하지 않음./x
및/x/
는 동등하게 처리됨
이 옵션은 prerendering에도 영향을 준다.trailingSlah
가 always
이면 /about
과 같은 route는 about/index.html
파일을 생성하고 그렇지 않으면 static webserver convention을 미러링하는 about.html
을 생성한다.
후행 slash를 ignore 하는 것은 권장되지 않는다.
relative path의 의미는 두 경우 (/x
의./y
는/y
이지만/x/
에선/x/y
)가 다르며/x
및/x/
는 SEO에 유해한 별도의 URL로 취급된다.
이 옵션을 사용하는 경우handle
function 내부의request.path
에서 후행 slash를 조건부로 추가하거나 제거하는 logic을 구현해야 한다.
version
다음 값 중 0개 이상을 포함하는 개체:
name
- 현재 app version 문자열pollInterval
- version 변경을 polling 하는 간격 (milliseconds)
사람들이 사용하는 동안 새 버전의 app을 배포하면 client-size navigation에 버그가 있을 수 있다.
새 page의 code가 이미 load된 경우 오래된 content가 있을 수 있다.
그렇지 않은 경우 app의 route manifest가 더 이상 존재하지 않는 JavaScript file을 가리킬 수 있다.
SvelteKit은 여기에 지정된 이름(기본적으로 빌드의 timestamp)을 사용하여 새 버전이 배포되었음을 감지한 후 기존 full-page navigation으로 falling back하여 이 문제를 해결한다.
pollInterval
이 0이 아닌 값으로 설정하면 SvelteKit은 background에서 새 버전을 polling화고 업데이트 된 저장소를 감지하면 updated
store의 값을 true
로 설정한다.
'Study > JavaScript' 카테고리의 다른 글
browser에서 dayjs 사용해 보기 (0) | 2024.03.28 |
---|---|
Lua data를 json으로 변환하기 (0) | 2023.09.27 |
Svelte 공부하기 (0) | 2022.06.23 |
corepack, pnpm, vite 사용해보기 (0) | 2022.06.22 |
vue 3 release 이후 javascript 생태계 변화 알아보기 (0) | 2022.06.20 |
vue 3 프로젝트 typescript 사용해보기 (0) | 2021.12.23 |
vue 로 만든 웹을 desktop app으로 사용하기 (electron builder 소개) (0) | 2021.12.23 |
내가 보려고 만든 디아블로2 룬워드 검색 페이지 (0) | 2021.10.12 |
npmtrends.com 소개 (0) | 2021.10.03 |
vue 3 사용해보기 (0) | 2021.09.29 |