Home » Как собирать веб-приложение с Parcel.js
Как собирать веб-приложение с Parcel.js

Как собирать веб-приложение с Parcel.js

Если вы долго мучались с настройкой сложных сборщиков типа Webpack, заплутавшись в десятках конфигов, то Parcel.js станет для вас глотком свежего воздуха. Этот современный сборщик обещает “zero configuration” — просто укажите входной файл, и он сам разберется с остальным. Звучит слишком хорошо, чтобы быть правдой? Давайте разберемся, действительно ли все так просто, и стоит ли переходить на Parcel для ваших проектов.

В этой статье мы пройдем путь от полного нуля до готового веб-приложения, развернутого на продакшене. Вы узнаете, как быстро настроить Parcel, какие подводные камни вас ждут, и получите готовые команды для автоматизации процесса сборки. Особое внимание уделим деплою на VPS и оптимизации для продакшена.

Как работает Parcel.js под капотом

Parcel использует подход, кардинально отличающийся от Webpack. Вместо огромного конфига он анализирует ваш код и автоматически определяет, какие трансформации нужны. Основные принципы:

  • Asset-oriented — каждый файл рассматривается как ресурс (asset) с определенным типом
  • Dependency graph — автоматически строит граф зависимостей, начиная с entry point
  • Multi-core — параллельная обработка файлов на всех доступных ядрах
  • Caching — агрессивное кэширование для ускорения повторных сборок

Интересный факт: Parcel написан на Rust (версия 2.x), что дает ему значительное преимущество в скорости по сравнению с JavaScript-решениями.

Быстрая настройка с нуля

Начнем с создания проекта и установки Parcel. Никаких сложных конфигов — только практика:


# Создаем новый проект
mkdir my-parcel-app
cd my-parcel-app

# Инициализируем npm
npm init -y

# Устанавливаем Parcel
npm install --save-dev parcel

# Создаем базовую структуру
mkdir src
touch src/index.html src/index.js src/styles.css

Теперь создадим минимальный HTML-файл (src/index.html):


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Parcel App</title>
    <link rel="stylesheet" href="./styles.css">
</head>
<body>
    <h1>Hello Parcel!</h1>
    <script src="./index.js"></script>
</body>
</html>

Добавим немного JavaScript (src/index.js):


import './styles.css';

console.log('Parcel is working!');

// ES6+ синтаксис работает из коробки
const greeting = (name) => {
    return `Hello, ${name}!`;
};

document.addEventListener('DOMContentLoaded', () => {
    document.body.innerHTML += `<p>${greeting('Developer')}</p>`;
});

И стили (src/styles.css):


body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    margin: 0;
    padding: 20px;
}

h1 {
    text-align: center;
    margin-bottom: 30px;
}

Обновляем package.json, добавляя скрипты:


{
  "name": "my-parcel-app",
  "version": "1.0.0",
  "scripts": {
    "dev": "parcel src/index.html",
    "build": "parcel build src/index.html",
    "preview": "parcel src/index.html --no-hmr"
  },
  "devDependencies": {
    "parcel": "^2.10.0"
  }
}

Запускаем dev-сервер:


npm run dev

Вуаля! Приложение доступно по адресу http://localhost:1234 с hot reload из коробки.

Продвинутая настройка и конфигурация

Хотя Parcel позиционируется как zero-config решение, иногда нужна тонкая настройка. Создадим файл .parcelrc для кастомизации:


{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"]
  },
  "optimizers": {
    "*.{js,mjs,jsm,jsx,ts,tsx}": ["@parcel/optimizer-terser"],
    "*.css": ["@parcel/optimizer-css"]
  },
  "packagers": {
    "*.html": "@parcel/packager-html",
    "*.css": "@parcel/packager-css",
    "*.js": "@parcel/packager-js"
  }
}

Для работы с TypeScript добавим зависимости:


npm install --save-dev typescript @parcel/transformer-typescript-tsc

Создадим tsconfig.json:


{
  "compilerOptions": {
    "target": "es2020",
    "module": "es2020",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Интеграция с популярными фреймворками

Parcel отлично работает с современными фреймворками. Рассмотрим интеграцию с React:


# Устанавливаем React
npm install react react-dom
npm install --save-dev @types/react @types/react-dom

# Создаем React компонент (src/App.tsx)

Код компонента (src/App.tsx):


import React, { useState } from 'react';

const App: React.FC = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>React + Parcel</h1>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
};

export default App;

Обновляем index.js:


import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const container = document.getElementById('root');
const root = createRoot(container!);
root.render(<App />);

Оптимизация для продакшена

Для продакшена нужно настроить оптимизацию. Создадим отдельную конфигурацию:


# Билд для продакшена
npm run build

# Результат будет в папке dist/

Parcel автоматически применяет оптимизации:

  • Минификация JavaScript и CSS
  • Tree shaking для удаления неиспользуемого кода
  • Сжатие изображений
  • Генерация source maps
  • Кэширование с хэшами в именах файлов

Для тонкой настройки создадим файл package.json с дополнительными опциями:


{
  "scripts": {
    "build:prod": "parcel build src/index.html --no-source-maps --public-url ./",
    "build:analyze": "parcel build src/index.html --reporter @parcel/reporter-bundle-analyzer"
  }
}

Сравнение с другими сборщиками

Характеристика Parcel Webpack Vite Rollup
Конфигурация Zero-config Сложная Минимальная Средняя
Скорость dev Быстрая Средняя Очень быстрая Медленная
Скорость build Быстрая Медленная Быстрая Быстрая
Размер bundle Оптимальный Очень хороший Хороший Отличный
Экосистема Растущая Огромная Быстро растущая Специализированная

Деплой на VPS

Теперь развернем приложение на сервере. Если у вас еще нет VPS, можете заказать VPS или выделенный сервер для более требовательных проектов.

Создаем скрипт для автоматического деплоя (deploy.sh):


#!/bin/bash

# Переменные
SERVER_USER="root"
SERVER_IP="your-server-ip"
SERVER_PATH="/var/www/html"
BUILD_DIR="dist"

echo "Building application..."
npm run build

echo "Uploading to server..."
rsync -avz --delete $BUILD_DIR/ $SERVER_USER@$SERVER_IP:$SERVER_PATH/

echo "Setting permissions..."
ssh $SERVER_USER@$SERVER_IP "chown -R www-data:www-data $SERVER_PATH && chmod -R 755 $SERVER_PATH"

echo "Deployment completed!"

Делаем скрипт исполняемым:


chmod +x deploy.sh

Настраиваем Nginx на сервере (/etc/nginx/sites-available/parcel-app):


server {
    listen 80;
    server_name your-domain.com;
    
    root /var/www/html;
    index index.html;
    
    # Кэширование статики
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # SPA routing
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # Gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}

Активируем конфигурацию:


sudo ln -s /etc/nginx/sites-available/parcel-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Автоматизация с GitHub Actions

Создадим CI/CD pipeline (.github/workflows/deploy.yml):


name: Deploy to Server

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build application
      run: npm run build
    
    - name: Deploy to server
      uses: appleboy/ssh-action@v0.1.5
      with:
        host: ${{ secrets.SERVER_HOST }}
        username: ${{ secrets.SERVER_USER }}
        key: ${{ secrets.SERVER_SSH_KEY }}
        script: |
          cd /var/www/html
          rm -rf *
          
    - name: Upload files
      uses: appleboy/scp-action@v0.1.4
      with:
        host: ${{ secrets.SERVER_HOST }}
        username: ${{ secrets.SERVER_USER }}
        key: ${{ secrets.SERVER_SSH_KEY }}
        source: "dist/*"
        target: "/var/www/html"
        strip_components: 1

Продвинутые возможности и трюки

Parcel поддерживает множество интересных фич из коробки:

  • Web Workers — импортируйте с суффиксом ?worker
  • Service Workers — регистрируйте через navigator.serviceWorker
  • Dynamic imports — code splitting работает автоматически
  • WebAssembly — импортируйте .wasm файлы напрямую

Пример использования Web Worker:


// worker.js
self.addEventListener('message', (e) => {
  const result = heavyComputation(e.data);
  self.postMessage(result);
});

// main.js
import Worker from './worker.js?worker';

const worker = new Worker();
worker.postMessage({data: 'process this'});
worker.addEventListener('message', (e) => {
  console.log('Result:', e.data);
});

Динамические импорты для code splitting:


// Lazy loading модулей
const loadChart = async () => {
  const { Chart } = await import('./chart-module.js');
  return new Chart();
};

// Условная загрузка
if (shouldLoadFeature) {
  import('./feature.js').then(module => {
    module.initFeature();
  });
}

Мониторинг и отладка

Для анализа bundle используем встроенный reporter:


npm install --save-dev @parcel/reporter-bundle-analyzer

Запускаем анализ:


npx parcel build src/index.html --reporter @parcel/reporter-bundle-analyzer

Для отладки сборки добавляем verbose режим:


npx parcel build src/index.html --log-level verbose

Распространенные проблемы и решения

Проблема: Parcel не может разрешить зависимость

Решение: Проверьте алиасы в package.json:


{
  "alias": {
    "@": "./src",
    "components": "./src/components"
  }
}

Проблема: Медленная сборка больших проектов

Решение: Настройте кэширование и исключения:


{
  "scripts": {
    "build": "parcel build src/index.html --cache-dir .cache"
  }
}

Проблема: Ошибки с CSS-in-JS библиотеками

Решение: Добавьте трансформер для styled-components:


npm install --save-dev @parcel/transformer-styled-components

Заключение и рекомендации

Parcel.js — отличный выбор для большинства проектов, особенно если вы цените простоту настройки и быструю разработку. Он идеально подходит для:

  • Прототипирования и MVP
  • Небольших и средних проектов
  • Команд, которые не хотят тратить время на настройку сборки
  • Миграции с устаревших сборщиков

Однако для энтерпрайз-проектов с сложными требованиями все еще может понадобиться Webpack с его гибкостью конфигурации.

Ключевые преимущества Parcel:

  • Практически нулевая конфигурация
  • Отличная производительность благодаря Rust
  • Современные возможности из коробки
  • Простой деплой и интеграция с CI/CD

Начните с простого проекта, изучите возможности, и вы быстро оцените, насколько Parcel упрощает жизнь разработчика. Официальная документация доступна на parceljs.org.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked