Skip to content

Snowpack Cheatsheet

Snowpack - The Faster Frontend Build Tool

Snowpack is a lightning-fast frontend build tool, designed for the modern web. It leverages JavaScript's native module system (ESM) to avoid unnecessary work and stay fast no matter how big your project grows.

Table of Contents

Installation

Global Installation

# Install Snowpack globally
npm install -g snowpack

# Check version
snowpack --version
# Initialize npm project
npm init -y

# Install Snowpack locally
npm install --save-dev snowpack

# Or with Yarn
yarn add --dev snowpack

Create Snowpack App

# 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

Package.json Scripts

{
  "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}\""
  }
}

Getting Started

Basic Project Structure

my-snowpack-app/
├── public/
   ├── index.html
   └── favicon.ico
├── src/
   ├── index.js
   ├── index.css
   └── logo.svg
├── snowpack.config.js
└── package.json

Basic HTML Entry Point

<!-- 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>

Basic JavaScript Entry

// src/index.js
import './index.css';

console.log('Hello Snowpack!');

// Hot Module Replacement API
if (import.meta.hot) {
  import.meta.hot.accept();
}

Basic CSS

/* 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;
}

Start Development

# 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

Configuration

Basic Configuration

// 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: {
    /* ... */
  },
};

Advanced Configuration

// 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',
  },
};

TypeScript Configuration

// 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"
  ]
}

Development Server

Basic Development Server

# 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

Development Server Options

// 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',
  },
};

Proxy Configuration

// 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);
      },
    },
  ],
};

Custom Server

// 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();

Build Process

Basic Build

# 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

Build Configuration

// 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

// 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;"]

Migration

From 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\""
  }
}

From 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',
  },
};

Migration Checklist

  • Install Snowpack and remove old bundler
  • Create snowpack.config.js
  • Update package.json scripts
  • Convert configuration options
  • Update import paths if needed
  • Test development and build processes
  • Update CI/CD pipelines

Troubleshooting

Common Issues

Module Resolution

// 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 Not Working

// 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,
  },
};

Build Errors

# Issue: Build fails
# Solution: Check for unsupported features
snowpack build --verbose

# Clear cache
rm -rf node_modules/.cache

Package Compatibility

// Issue: Package doesn't work with Snowpack
// Solution: Add to external packages or use polyfills
module.exports = {
  packageOptions: {
    external: ['problematic-package'],
    polyfillNode: true,
  },
};

Debug Configuration

// 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
  },
};

Best Practices

Project Structure

# 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

Performance Best Practices

  • Use ES modules for better tree shaking
  • Implement code splitting for large applications
  • Optimize images and assets
  • Enable bundling for production builds
  • Use lazy loading for heavy components

Development Best Practices

  • Use TypeScript for better development experience
  • Enable HMR for faster development
  • Configure aliases for cleaner imports
  • Use environment variables for configuration
  • Set up linting and formatting

Production Best Practices

  • Enable optimization for production builds
  • Use CDN for static assets
  • Implement caching strategies
  • Monitor bundle size and performance
  • Test builds before deployment

Summary

Snowpack is a lightning-fast frontend build tool that leverages ES modules for optimal development experience. Key features include:

  • Unbundled Development: Serves individual files during development for instant startup
  • ES Module First: Native support for JavaScript modules
  • Plugin Ecosystem: Rich ecosystem of plugins for various frameworks
  • Hot Module Replacement: Fast HMR for instant updates
  • TypeScript Support: Built-in TypeScript compilation
  • Framework Agnostic: Works with React, Vue, Svelte, and more
  • Production Optimization: Bundle and optimize for production
  • Simple Configuration: Minimal configuration required

By leveraging Snowpack's speed and simplicity, you can significantly improve your development workflow while maintaining excellent production performance.