Snowpack은 더 빠른 웹 개발을 위한 최신의 프론트엔드 빌드 도구입니다.
기존의 Webpack, Rollup 그리고 Parcel 같은 무겁고 복잡한 번들러의 번들 소요 시간을 획기적으로 절약할 수 있습니다.
Snowpack은 번들러가 아닙니다! 단순히 더 빨리 번들하는 것이 아니라 웹 빌드 시스템에 대한 새로운 접근 방식을 제공합니다.
JavaScript의 ESM(ES Modules)을 활용하여 동일 파일을 다시 빌드하지 않는 최초의 빌드 시스템을 생성해 변경사항을 브라우저에 즉시 적용할 수 있습니다.
번들 없는 개발(Unbundled Development)은 개별 파일을 브라우저에 전달하는 아이디어입니다.
Babel, TypeScript, Sass 같은 자주 사용하는 라이브러리로 파일을 빌드하고,
ESM import/export 구문으로 브라우저에서 개별적으로 로드합니다.
Snowpack은 파일이 변경되면 해당 단일 파일만 다시 빌드합니다.
반면에 Webpack, Rollup 같은 번들러들은 번들 개발(Bundled Development)에 중점을 둡니다.
번들러로 애플리케이션을 실행하면 개발에 추가 작업과 복잡성이 발생합니다.
저장할 때마다 모든 변경사항을 나머지 애플리케이션과 함께 다시 번들해야만 변경사항이 브라우저에 반영됩니다.
이제 ESM이 널리 지원되므로 이런 방식은 불필요합니다.
‘번들 없는 개발’은 기존 방식에 비해 몇 가지 장점이 있습니다.
모든 파일은 개별적으로 빌드되고 지속해서 캐시됩니다.
파일에 변경사항이 없으면 파일을 다시 빌드하지 않고 브라우저에서 다시 다운로드하지 않습니다.
이것이 번들 없는 개발의 핵심입니다.
또한 Snowpack은 즉시(50ms 미만) 시작하여 속도 저하 없이 무한히 큰 프로젝트로 확장할 수 있습니다.
반대로 기존 번들러로 대규모 앱을 빌드할 때는 개발 시작 시간이 30초 이상 걸리는 것이 일반적입니다.
회사에서 관리하는 Webpack 기반의 일부 프론트엔드 개발은 최초 빌드가 4분 정도 걸립니다.
NPM 패키지는 대부분 웹에서 직접 실행할 수 없는 CommonJS를 사용합니다.
브라우저에서 직접 실행할 수 있는 ESM import/export 구문을 사용하여 애플리케이션을 작성하더라도,
NPM 패키지를 가져올 때 번들러가 동작해야 합니다.
Snowpack은 다른 접근 방식을 취합니다.
전체 애플리케이션을 번들로 묶는 대신 Snowpack은 의존성을 별도로 처리합니다.
작동 방식은 다음과 같습니다.
node_modules/react => http://localhost:8080/web_modules/react.js
node_modules/vue => http://localhost:8080/web_modules/vue.js
<body>
<script type="module">
import React from 'react'
import Vue from 'vue'
console.log(React)
console.log(Vue)
</script>
</body>
Skypack를 통해 Snowpack에서 사용할 ESM 지원 패키지를 쉽게 검색하고 테스트할 수 있습니다.
Snowpack의 기본 구조를 이해하기 위해서,
Vue.js 템플릿(@snowpack/app-template-vue)을 최대한 간소화하고 핵심 내용만 정리했습니다.
mount
: Snowpack 빌드에 사용할 ‘현재 경로‘와 빌드 결과로 연결할 ‘빌드 경로‘를 지정합니다.plugins
: Snowpack에서 사용할 플러그인 목록을 지정합니다.연결 옵션은 CONFIG.MOUNT 파트에서 확인할 수 있습니다.
기타 모든 옵션은 CONFIG 파트에서 확인할 수 있습니다.
mount: {
현재_경로: 빌드_경로
}
현재 프로젝트 구조에서 public/
(디렉토리)을 루트 경로로 사용하고,src/
를 지정한(/_dist_
) 경로로 사용하도록 지정합니다.
module.exports = {
mount: {
public: '/',
src: '/_dist_'
},
plugins: [
'@snowpack/plugin-vue'
]
};
snowpack dev
명령으로 개발 서버를 준비하고,snowpack build
명령으로 제품을 빌드를 할 수 있습니다.
설치할 개발 의존성은 snowpack과 Vue 구성을 위한 @snowpack/plugin-vue입니다.
설치할 일반 의존성으론 실제 사용할 vue만 있으면 충분합니다.
{
"scripts": {
"dev": "snowpack dev",
"build": "snowpack build"
},
"devDependencies": {
"@snowpack/plugin-vue": "^2.2.4",
"snowpack": "^2.15.1"
},
"dependencies": {
"vue": "^3.0.2"
}
}
snowpack.config.js
에서 src: '/_dist_'
을 통해 어느 경로에 빌드 결과가 저장되는지 지정했습니다.
이 Vue 프로젝트의 진입점은 src/main.js
입니다.
<body>
<script type="module" src="/_dist_/main.js"></script>
</body>
만약 진입점이 src/index.js
인 경우, 경로를 다음과 같이 수정해야 합니다.
<script type="module" src="/_dist_/index.js"></script>
프로젝트를 다음과 같이 빌드하면, build/
디렉토리가 생성됩니다.
$ npm run build
## or
$ snowpack build
__snowpack__
: Snowpack의 메타 데이터(HMR, ENV..)가 출력되는 디렉토리입니다. buildOptions.metaDir
옵션으로 이름을 수정할 수 있습니다._dist_
: src/
의 파일이 빌드 후 출력되는 디렉토리입니다.web_modules
: 사용할 웹 모듈의 디렉토리입니다. 이 프로젝트에서는 vue가 웹 모듈로 사용됩니다. buildOptions.webModulesUrl
옵션으로 이름을 수정할 수 있습니다.빌드 옵션은 CONFIG.BUILDOPTIONS 파트에서 확인할 수 있습니다.
옵션 | 설명 | 타입 |
---|---|---|
mount | 빌드에 포함될 디렉토리와 연결될 URL을 지정 | object |
plugins | 기능을 확장할 플러그인을 연결 | string[] | [string, object][] |
alias | 앱에서 사용할 경로 별칭 지정 | object |
devOptions | 개발 서버의 작동 방식을 지정 | object |
buildOptions | 최종 빌드를 처리하는 방법을 지정 | object |
installOptions | 외부 모듈을 처리하는 방법을 지정 | object |
testOptions | 테스트 환경의 작동 방식을 지정 | object |
proxy | 개발 서버의 프록시 동작을 지정 | object |
exclude | 지정된 파일을 빌드에서 제외 | string[] |
install | 자동으로 감지되지 않는 설치할 모듈을 지정 | string[] |
extends | 지정된 별도의 기본 구성 옵션을 상속해 병합 | string |
snowpack dev
를 통한 개발 서버의 작동 방식을 지정합니다.
module.exports = {
devOptions: {
port: 8080, // 개발 서버를 실행할 포트 번호
fallback: 'index.html', // SPA인 경우 제공할 모든 사용자 경로
open: 'default', // 새 브라우저 탭에 개발 서버를 열기, "default" | "none" | "BROWSER_NAME"
output: 'dashboard', // 콘솔의 출력 모드를 지정, "stream" | "dashbaord"
hostname: 'localhost', // 브라우저가 열리는 호스트 이름
hmr: true, // Hot Module Replacement(HMR, 수정사항을 즉시 반영) 활성화
hmrErrorOverlay: true, // HMR 활성화시 자바스크립트 오류 표시 여부
secure: false, // HTTP2 활성화 상태에서 HTTPS 사용 여부
// out: 'build' // Deprecated!
}
}
snowpack build
를 통해 최종 빌드를 처리하는 방법을 지정합니다.
module.exports = {
buildOptions: {
out: 'build', // 최종 빌드를 출력하는 로컬 디렉토리 이름
baseUrl: '/', // 제품 모드의 기본 URL 지정, 현재 앱이 하위 디렉토리로 배포되는 경우 유용
clean: false, // 빌드 전 기존 데이터 제거
metaDir: '__snowpack__', // HMR 및 ENV 등의 정보를 출력할 디렉토리 이름
sourceMap: false, // 소스 맵 사용 여부
webModulesUrl: 'web_modules' // 사용하는 웹 모듈이 저장될 디렉토리 이름
}
}
설치하는 외부 모듈을 처리하는 방법을 지정합니다.
module.exports = {
installOptions: {
dest: 'web_modules', // 사용하는 웹 모듈이 저장될 디렉토리 이름
sourceMap: false, // 설치된 모듈의 소스맵 사용
env: {}, // 환경 변수 지정
treeshake: false, // 의존성 모듈의 트리쉐이킹 여부(제품 모드만 동작)
installType: false, // 모듈 설치 시 타입 정의를 함께 설치(타입스크립트)
namedExports: [], // `Uncaught SyntaxError: The requested module '/web_modules/XX.js' does not provide an export named 'YY'` 에러가 발생하는 경우, `namedExports: ['XX']`
externalPackage: [], // 무시할 외부 모듈의 목록, E.g. 'fs'
packageLookupFields: [], // ??
rollup: { // Snowpack이 내부적으로 사용하는 Rollup을 더욱 세부적으로 제어하기 위한 옵션
plugins: [], // Rollup 플러그인을 지정
dedupe: [], // 중복 번들을 방지하기 위한 외부 모듈 이름을 지정(rollup-plugin-node-resolve)
context: [] // 최상위 `this`를 지정, 최상위 변수를 참조하는 레거시 CJS 모듈의 오류 해결에 유용
},
}
}
주요 프레임워크의 공식 템플릿을 지원합니다.
Snowpack을 이해하는 데 많은 도움이 됩니다.
더 많은 템플릿을 확인하세요!
Snowpack 기반의 Svelte 템플릿을 만들었습니다.
별도의 구성 없이 바로 프로젝트를 시작할 수 있습니다.
템플릿에서 지원하는 내용은 크게 다음과 같습니다.
다음과 같이 설치합니다.
## Install template
$ npx degit ParkYoungWoong/svelte-snowpack-template DIR_NAME
## Change directory
$ cd DIR_NAME
## Install dependencies
$ npm i
## Start dev server
$ npm run dev
타입스크립트를 사용하는 경우 다음과 같이 작성할 수 있습니다.
<script lang="ts">
let count: number = 0
</script>
SCSS를 사용하는 경우 다음과 같이 작성할 수 있습니다.
<style lang="scss">
$color--primary: royalblue;
h1 {
color: $color--primary;
}
</style>