Snowpack 치트시트
Snowpack - The Faster Frontend Build Tool
Snowpack은 현대적 웹을 위해 설계된 번개처럼 빠른 프론트엔드 빌드 도구입니다. JavaScript의 네이티브 모듈 시스템(ESM)을 활용하여 불필요한 작업을 피하고 프로젝트 규모와 상관없이 빠르게 유지합니다.
(No text to translate) ```bash # Install Snowpack globally npm install -g snowpackCheck version
snowpack —version
npm install -g snowpack
```
```bash
# Initialize npm project
npm init -y
# Install Snowpack locally
npm install --save-dev snowpack
# Or with Yarn
yarn add --dev snowpack
``````bash
npm install --save-dev snowpack
```
```bash
# Create new app with template
npx create-snowpack-app my-app --template @snowpack/app-template-react
# Available templates
npx create-snowpack-app my-app --template @snowpack/app-template-vanilla
npx create-snowpack-app my-app --template @snowpack/app-template-react
npx create-snowpack-app my-app --template @snowpack/app-template-vue
npx create-snowpack-app my-app --template @snowpack/app-template-svelte
npx create-snowpack-app my-app --template @snowpack/app-template-preact
npx create-snowpack-app my-app --template @snowpack/app-template-lit-element
``````bash
npx create-snowpack-app my-project
```
```json
{
"scripts": {
"start": "snowpack dev",
"build": "snowpack build",
"test": "web-test-runner \"src/**/*.test.js\"",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
"lint": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\""
}
}
``````json
"scripts": {
"start": "snowpack dev",
"build": "snowpack build"
}
```
```bash
my-snowpack-app/
├── public/
│ ├── index.html
│ └── favicon.ico
├── src/
│ ├── index.js
│ ├── index.css
│ └── logo.svg
├── snowpack.config.js
└── package.json
my-project/ ├── public/ │ └── index.html ├── src/ │ ├── index.js │ └── styles.css └── package.json
```html
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Web site created using Snowpack" />
<title>Snowpack App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.js"></script>
</body>
</html>
``````html
<!DOCTYPE html>
<html>
<head>
<title>My Snowpack App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/index.js"></script>
</body>
</html>
// src/index.js
import './index.css';
console.log('Hello Snowpack!');
// Hot Module Replacement API
if (import.meta.hot) {
import.meta.hot.accept();
}
``````javascript
import './styles.css';
console.log('Hello Snowpack!');
/* src/index.css */
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
``````css
body {
font-family: sans-serif;
}
# Start development server
npm start
# Or directly with Snowpack
npx snowpack dev
# Custom port
npx snowpack dev --port 3000
# Open browser automatically
npx snowpack dev --open
``````bash
npm start
// snowpack.config.js
module.exports = {
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
},
plugins: [
'@snowpack/plugin-react-refresh',
'@snowpack/plugin-dotenv',
],
routes: [
/* Enable an SPA Fallback in development: */
{ match: 'routes', src: '.*', dest: '/index.html' },
],
optimize: {
/* Example: Bundle your final build: */
// "bundle": true,
},
packageOptions: {
/* ... */
},
devOptions: {
/* ... */
},
buildOptions: {
/* ... */
},
};
``````javascript
// snowpack.config.js
module.exports = {
mount: {
public: '/',
src: '/_dist_'
}
}
// snowpack.config.js
module.exports = {
// Mount directories
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
'src/components': { url: '/components' },
'src/assets': { url: '/assets', static: true },
},
// Plugins
plugins: [
'@snowpack/plugin-react-refresh',
'@snowpack/plugin-dotenv',
'@snowpack/plugin-typescript',
'@snowpack/plugin-sass',
'@snowpack/plugin-postcss',
[
'@snowpack/plugin-webpack',
{
extendConfig: (config) => {
config.plugins.push(/* ... */);
return config;
},
},
],
],
// Routes
routes: [
{ match: 'routes', src: '.*', dest: '/index.html' },
{ match: 'routes', src: '/api/.*', dest: '/api/index.js' },
],
// Optimization
optimize: {
bundle: true,
minify: true,
target: 'es2018',
},
// Package options
packageOptions: {
source: 'local',
external: ['fs', 'path'],
env: {
NODE_ENV: true,
},
rollup: {
plugins: [/* ... */],
},
},
// Development options
devOptions: {
port: 8080,
open: 'default',
openUrl: 'http://localhost:8080',
hmr: true,
secure: false,
hostname: 'localhost',
},
// Build options
buildOptions: {
out: 'build',
baseUrl: '/',
clean: true,
sourcemap: true,
metaUrlPath: 'snowpack',
},
// Aliases
alias: {
'@': './src',
'@components': './src/components',
'@utils': './src/utils',
},
};
``````javascript
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-react-refresh',
'@snowpack/plugin-dotenv'
]
}
// snowpack.config.js
module.exports = {
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
},
plugins: [
'@snowpack/plugin-typescript',
'@snowpack/plugin-react-refresh',
],
packageOptions: {
types: true,
},
};
// tsconfig.json
{
"compilerOptions": {
"target": "es2018",
"lib": [
"dom",
"dom.iterable",
"es6"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
}
},
"include": [
"src"
]
}
``````javascript
// snowpack.config.js
module.exports = {
typescript: {
compilerOptions: {
strict: true
}
}
}
# Start development server
snowpack dev
# Custom configuration
snowpack dev --config snowpack.dev.config.js
# Verbose output
snowpack dev --verbose
# Reload on file changes
snowpack dev --reload
``````bash
snowpack dev
// snowpack.config.js
module.exports = {
devOptions: {
// Port number
port: 8080,
// Hostname
hostname: 'localhost',
// Open browser
open: 'default', // 'default', 'none', or browser name
openUrl: 'http://localhost:8080',
// Hot Module Replacement
hmr: true,
hmrDelay: 0,
hmrPort: undefined,
hmrErrorOverlay: true,
// HTTPS
secure: false,
// Output
output: 'stream', // 'stream' or 'dashboard'
// Fallback
fallback: 'index.html',
},
};
``````javascript
// snowpack.config.js
module.exports = {
devOptions: {
port: 8080,
open: 'chrome'
}
}
// snowpack.config.js
module.exports = {
devOptions: {
port: 3000,
},
routes: [
{
src: '/api/.*',
dest: (req, res) => {
// Proxy to backend API
return proxy('http://localhost:8000', {
changeOrigin: true,
})(req, res);
},
},
],
};
``````javascript
// snowpack.config.js
module.exports = {
proxy: {
'/api': 'http://localhost:3000'
}
}
// server.js
const { startServer } = require('snowpack');
async function start() {
const server = await startServer({
config: {
devOptions: {
port: 3000,
},
},
lockfile: null,
});
console.log(`Server started on port ${server.port}`);
}
start();
``````javascript
// snowpack.config.js
module.exports = {
devOptions: {
hmr: true,
hmrDelay: 300
}
}
# Build for production
snowpack build
# Build with custom config
snowpack build --config snowpack.prod.config.js
# Clean build
snowpack build --clean
# Verbose build
snowpack build --verbose
``````bash
snowpack build
The translations maintain the original markdown formatting, keep technical terms in English, and preserve the structure and punctuation of the original text.```javascript // snowpack.config.js module.exports = { buildOptions: { // Output directory out: ‘build’,
// Base URL
baseUrl: '/',
// Clean output directory
clean: true,
// Source maps
sourcemap: true,
// Meta URL path
metaUrlPath: 'snowpack',
// Watch mode
watch: false,
}, };
### Production Optimization
```javascript
// snowpack.config.js
module.exports = {
optimize: {
// Bundle files
bundle: true,
// Minify code
minify: true,
// Target environment
target: 'es2018',
// Tree shaking
treeshake: true,
// Splitting
splitting: true,
// Manifest
manifest: true,
},
buildOptions: {
sourcemap: false, // Disable source maps in production
},
};
Custom Build Script
// build.js
const { build } = require('snowpack');
async function buildApp() {
const result = await build({
config: {
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
},
optimize: {
bundle: true,
minify: true,
},
},
});
console.log('Build completed!');
console.log('Result:', result);
}
buildApp().catch(console.error);
Plugins
Essential Plugins
# Install common plugins
npm install --save-dev @snowpack/plugin-react-refresh
npm install --save-dev @snowpack/plugin-typescript
npm install --save-dev @snowpack/plugin-sass
npm install --save-dev @snowpack/plugin-postcss
npm install --save-dev @snowpack/plugin-dotenv
npm install --save-dev @snowpack/plugin-webpack
React Plugin
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-react-refresh',
],
};
// src/App.jsx
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<header className="App-header">
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</header>
</div>
);
}
export default App;
TypeScript Plugin
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-typescript',
],
};
Sass Plugin
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-sass',
],
};
// src/styles.scss
$primary-color: #007bff;
$secondary-color: #6c757d;
.button {
background-color: $primary-color;
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
&:hover {
background-color: darken($primary-color, 10%);
}
}
PostCSS Plugin
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-postcss',
],
};
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
require('cssnano')({
preset: 'default',
}),
],
};
Webpack Plugin
// snowpack.config.js
module.exports = {
plugins: [
[
'@snowpack/plugin-webpack',
{
extendConfig: (config) => {
config.resolve.alias = {
'@': path.resolve(__dirname, 'src'),
};
return config;
},
},
],
],
optimize: {
bundle: true,
minify: true,
},
};
Custom Plugin
// plugins/custom-plugin.js
module.exports = function (snowpackConfig, pluginOptions) {
return {
name: 'custom-plugin',
resolve: {
input: ['.custom'],
output: ['.js'],
},
async load({ filePath }) {
const contents = await fs.readFile(filePath, 'utf8');
// Transform the file
const result = transformCustomFile(contents);
return {
'.js': result,
};
},
};
};
// snowpack.config.js
module.exports = {
plugins: [
'./plugins/custom-plugin.js',
],
};
Package Management
Installing Packages
# Install packages normally
npm install lodash
npm install react react-dom
# Snowpack will automatically handle ESM conversion
Package Configuration
// snowpack.config.js
module.exports = {
packageOptions: {
// Package source
source: 'local', // 'local', 'remote', or 'remote-next'
// External packages
external: ['fs', 'path', 'crypto'],
// Environment variables
env: {
NODE_ENV: true,
API_URL: true,
},
// Package transformations
knownEntrypoints: [
'react/jsx-runtime',
'react/jsx-dev-runtime',
],
// Rollup options for dependencies
rollup: {
plugins: [
// Custom rollup plugins for dependencies
],
dedupe: ['react', 'react-dom'],
},
},
};
ESM Package Handling
// Snowpack automatically converts CommonJS to ESM
import _ from 'lodash'; // Works even though lodash is CommonJS
import React from 'react';
import { render } from 'react-dom';
// Dynamic imports
const dynamicModule = await import('./dynamic-module.js');
Package Aliases
// snowpack.config.js
module.exports = {
alias: {
// Path aliases
'@': './src',
'@components': './src/components',
'@utils': './src/utils',
// Package aliases
'react': 'preact/compat',
'react-dom': 'preact/compat',
},
};
Hot Module Replacement
Basic HMR
// src/index.js
import './App.js';
// Accept HMR updates
if (import.meta.hot) {
import.meta.hot.accept();
}
Component HMR
// src/App.js
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
export default App;
// HMR for React components (handled by plugin)
if (import.meta.hot) {
import.meta.hot.accept();
}
HMR API
// Advanced HMR usage
if (import.meta.hot) {
// Accept updates to this module
import.meta.hot.accept();
// Accept updates to dependencies
import.meta.hot.accept('./dependency.js', (newModule) => {
// Handle the updated dependency
console.log('Dependency updated:', newModule);
});
// Dispose callback
import.meta.hot.dispose((data) => {
// Cleanup before module is replaced
data.someState = getCurrentState();
});
// Invalidate and force full reload
import.meta.hot.invalidate();
}
CSS HMR
/* src/styles.css */
.app {
background-color: #f0f0f0;
padding: 20px;
}
/* Changes to CSS are automatically hot-reloaded */
// src/index.js
import './styles.css';
// CSS changes are automatically handled by Snowpack
TypeScript Support
Basic TypeScript Setup
# Install TypeScript
npm install --save-dev typescript @snowpack/plugin-typescript
# Create tsconfig.json
npx tsc --init
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-typescript',
],
};
TypeScript Configuration
// tsconfig.json
{
"compilerOptions": {
"target": "es2018",
"lib": ["dom", "dom.iterable", "es6"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
TypeScript with React
// src/App.tsx
import React, { useState } from 'react';
interface Props {
title: string;
}
const App: React.FC<Props> = ({ title }) => {
const [count, setCount] = useState<number>(0);
const handleIncrement = (): void => {
setCount(prev => prev + 1);
};
return (
<div>
<h1>{title}</h1>
<p>Count: {count}</p>
<button onClick={handleIncrement}>
Increment
</button>
</div>
);
};
export default App;
Type Definitions
// src/types/index.ts
export interface User {
id: number;
name: string;
email: string;
}
export interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
export type Theme = 'light' | 'dark';
CSS and Styling
CSS Modules
// snowpack.config.js
module.exports = {
plugins: [
[
'@snowpack/plugin-postcss',
{
config: {
plugins: [
require('postcss-modules')({
generateScopedName: '[name]__[local]___[hash:base64:5]',
}),
],
},
},
],
],
};
/* src/Button.module.css */
.button {
background-color: #007bff;
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
cursor: pointer;
}
.button:hover {
background-color: #0056b3;
}
// src/Button.js
import styles from './Button.module.css';
function Button({ children, onClick }) {
return (
<button className={styles.button} onClick={onClick}>
{children}
</button>
);
}
export default Button;
Sass/SCSS Support
# Install Sass plugin
npm install --save-dev @snowpack/plugin-sass
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-sass',
],
};
// src/styles.scss
$primary-color: #007bff;
$font-size-base: 1rem;
@mixin button-style($bg-color) {
background-color: $bg-color;
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
font-size: $font-size-base;
&:hover {
background-color: darken($bg-color, 10%);
}
}
.primary-button {
@include button-style($primary-color);
}
PostCSS Configuration
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-nested'),
require('autoprefixer'),
require('cssnano')({
preset: 'default',
}),
],
};
/* src/styles.css */
@import 'normalize.css';
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
}
.button {
background-color: var(--primary-color);
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
&:hover {
background-color: color-mod(var(--primary-color) shade(10%));
}
}
Asset Handling
Static Assets
// snowpack.config.js
module.exports = {
mount: {
public: { url: '/', static: true },
'src/assets': { url: '/assets', static: true },
},
};
Image Imports
// src/App.js
import logoUrl from './assets/logo.png';
import iconUrl from './assets/icon.svg';
function App() {
return (
<div>
<img src={logoUrl} alt="Logo" />
<img src={iconUrl} alt="Icon" />
</div>
);
}
Dynamic Imports
// Dynamic asset loading
async function loadImage(imageName) {
const imageModule = await import(`./assets/${imageName}.png`);
return imageModule.default;
}
// Usage
const logoUrl = await loadImage('logo');
document.getElementById('logo').src = logoUrl;
Asset Processing
// snowpack.config.js
module.exports = {
plugins: [
[
'@snowpack/plugin-webpack',
{
extendConfig: (config) => {
config.module.rules.push({
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images',
},
},
],
});
return config;
},
},
],
],
};
Environment Variables
Basic Environment Variables
# .env
SNOWPACK_PUBLIC_API_URL=https://api.example.com
SNOWPACK_PUBLIC_APP_NAME=My App
PRIVATE_KEY=secret123
// src/config.js
export const config = {
apiUrl: import.meta.env.SNOWPACK_PUBLIC_API_URL,
appName: import.meta.env.SNOWPACK_PUBLIC_APP_NAME,
// Private variables are not available in browser
};
Environment Plugin
// snowpack.config.js
module.exports = {
plugins: [
'@snowpack/plugin-dotenv',
],
};
Custom Environment Variables
// snowpack.config.js
module.exports = {
packageOptions: {
env: {
NODE_ENV: true,
API_URL: true,
VERSION: process.env.npm_package_version,
},
},
};
// src/app.js
console.log('Environment:', import.meta.env.NODE_ENV);
console.log('API URL:', import.meta.env.API_URL);
console.log('Version:', import.meta.env.VERSION);
Optimization
Bundle Optimization
// snowpack.config.js
module.exports = {
optimize: {
bundle: true,
minify: true,
target: 'es2018',
treeshake: true,
splitting: true,
manifest: true,
},
};
Webpack Integration
// snowpack.config.js
module.exports = {
plugins: [
[
'@snowpack/plugin-webpack',
{
extendConfig: (config) => {
config.optimization = {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
};
return config;
},
},
],
],
optimize: {
bundle: true,
minify: true,
},
};
Performance Optimization
// src/utils/lazy.js
export const lazyLoad = (importFunc) => {
return React.lazy(importFunc);
};
// src/App.js
import React, { Suspense } from 'react';
import { lazyLoad } from './utils/lazy';
const LazyComponent = lazyLoad(() => import('./components/HeavyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
Code Splitting
// Dynamic imports for code splitting
const loadDashboard = () => import('./pages/Dashboard');
const loadProfile = () => import('./pages/Profile');
// Router with code splitting
const routes = [
{
path: '/dashboard',
component: React.lazy(loadDashboard),
},
{
path: '/profile',
component: React.lazy(loadProfile),
},
];
Deployment
Static Deployment
# Build for production
npm run build
# Deploy build folder to static hosting
# (Netlify, Vercel, GitHub Pages, etc.)
Netlify Deployment
# netlify.toml
[build]
publish = "build"
command = "npm run build"
[build.environment]
NODE_VERSION = "16"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Vercel Deployment
{
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": {
"distDir": "build"
}
}
],
"routes": [
{
"handle": "filesystem"
},
{
"src": "/(.*)",
"dest": "/index.html"
}
]
}
GitHub Pages
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
Docker Deployment
# Dockerfile
FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
마이그레이션
Create React App에서
# Remove react-scripts
npm uninstall react-scripts
# Install Snowpack
npm install --save-dev snowpack @snowpack/plugin-react-refresh
# Update package.json scripts
{
"scripts": {
"start": "snowpack dev",
"build": "snowpack build",
"test": "web-test-runner \"src/**/*.test.js\""
}
}
Webpack에서
// Convert webpack.config.js to snowpack.config.js
module.exports = {
mount: {
public: { url: '/', static: true },
src: { url: '/dist' },
},
plugins: [
'@snowpack/plugin-react-refresh',
// Add other plugins as needed
],
alias: {
// Convert webpack aliases
'@': './src',
},
};
마이그레이션 체크리스트
- Snowpack 설치 및 이전 번들러 제거
- snowpack.config.js 생성
- package.json 스크립트 업데이트
- 구성 옵션 변환
- 필요한 경우 import 경로 업데이트
- 개발 및 빌드 프로세스 테스트
- CI/CD 파이프라인 업데이트
문제 해결
일반적인 문제
모듈 해결
// Issue: Module not found
// Solution: Check mount configuration
module.exports = {
mount: {
src: { url: '/dist' },
// Make sure all source directories are mounted
},
alias: {
// Add aliases for complex paths
'@': './src',
},
};
HMR 작동 안 함
// Issue: Hot reloading not working
// Solution: Ensure HMR is enabled and modules accept updates
if (import.meta.hot) {
import.meta.hot.accept();
}
// In snowpack.config.js
module.exports = {
devOptions: {
hmr: true,
},
};
빌드 오류
# Issue: Build fails
# Solution: Check for unsupported features
snowpack build --verbose
# Clear cache
rm -rf node_modules/.cache
패키지 호환성
// Issue: Package doesn't work with Snowpack
// Solution: Add to external packages or use polyfills
module.exports = {
packageOptions: {
external: ['problematic-package'],
polyfillNode: true,
},
};
디버그 구성
// snowpack.config.js
module.exports = {
devOptions: {
output: 'dashboard', // Better debugging output
},
buildOptions: {
sourcemap: true, // Enable source maps
},
packageOptions: {
source: 'local', // Use local packages for debugging
},
};
모범 사례
프로젝트 구조
# Recommended structure
src/
├── components/ # Reusable components
├── pages/ # Page components
├── hooks/ # Custom hooks
├── utils/ # Utility functions
├── styles/ # Global styles
├── assets/ # Static assets
├── types/ # TypeScript types
└── index.js # Entry point
성능 모범 사례
- ES 모듈 사용으로 더 나은 트리 쉐이킹
- 대규모 애플리케이션을 위한 코드 분할 구현
- 이미지 및 에셋 최적화
- 프로덕션 빌드를 위한 번들링 활성화
- 무거운 컴포넌트에 대해 지연 로딩 사용
개발 모범 사례
- 더 나은 개발 경험을 위해 TypeScript 사용
- 더 빠른 개발을 위해 HMR 활성화
- 더 깔끔한 임포트를 위해 별칭 구성
- 구성을 위해 환경 변수 사용
- 린팅 및 포맷팅 설정
프로덕션 모범 사례
- 프로덕션 빌드를 위한 최적화 활성화
- 정적 에셋에 CDN 사용
- 캐싱 전략 구현
- 번들 크기 및 성능 모니터링
- 배포 전 빌드 테스트
요약
Snowpack은 최적의 개발 경험을 위해 ES 모듈을 활용하는 초고속 프론트엔드 빌드 도구입니다. 주요 기능은 다음과 같습니다:
- 번들되지 않은 개발: 개발 중 개별 파일 서비스로 즉각적인 시작
- ES 모듈 우선: JavaScript 모듈에 대한 네이티브 지원
- 플러그인 생태계: 다양한 프레임워크를 위한 풍부한 플러그인 생태계
- 핫 모듈 교체: 즉각적인 업데이트를 위한 빠른 HMR
- TypeScript 지원: 내장된 TypeScript 컴파일
- 프레임워크 독립적: React, Vue, Svelte 등에서 작동
- 프로덕션 최적화: 프로덕션을 위한 번들 및 최적화
- 간단한 구성: 최소한의 구성 필요
Snowpack의 속도와 단순성을 활용하면 뛰어난 프로덕션 성능을 유지하면서 개발 워크플로우를 크게 개선할 수 있습니다.