rollup.js

Predstavenie

Prehľad

Rollup je zväzovač modulov pre JavaScript, ktorý kompiluje malé časti kódu na niečo väčšie a komplexnejšie, ako je knižnica alebo aplikácia. Používa nový štandardizovaný formát pre moduly zahrnuté v revízii ECMAScript 6, namiesto idiosynkrétnych riešení ako je CommonJS a AMD. Moduly v ES6 vám umožňujú voľne a hladko kombinovať naužitočnejšie funkcie z vašich obľubených knižníc. V budúcnosti bude možné natívne využívať moduly, ale Rollup to dokáže už dnes.

Návod na rýchly štart

Inštalujte pomocou npm install --global rollup. Rollup sa dá používať pomocou rozhrania príkazového riadku s voliteľným súborom nastavení alebo pomocou JavaScript API. Spustite rollup --help pre zoznam možných nastavení. Šablóna na štartovací projekt ukazuje bežné nastavenia. Detailnejšie pokyny sú dostupné v príručke pre používateľa.

Príkazy

Tieto príkazy predpokladajú, že prístupový bod do aplikácie sa nazýva main.js a že chcete všetky tieto importované súbory kompilovať do súboru nazvaný bundle.js.

Pre prehliadače:

# kompilovať pre využitie v <script> ako samo-spúšťaciu funkciu
$ rollup main.js --file bundle.js --format iife

Pre Node.js:

# kompilovať ako CommonJS modul
$ rollup main.js --file bundle.js --format cjs

Pre prehliadače a Node.js:

# formát UMD vyžaduje názov balíčka
$ rollup main.js --file bundle.js --format umd --name "myBundle"

Prečo

Vývoj softvéru je v mnohých prípadoch jednoduchší, keď rozdelíte projekt na niekoľko malých častí, ktoré často odstraňujú neočakavané interakcie a dramaticky znižujú komplexitu problémov k vyriešeniu, a písanie malých projektov nie je riešením problému. Bohužiaľ, JavaScript neobsahuje túto vymoženosť v jadre jazyka.

Toto sa nakoniec zmenilo v revízii ECMAScript 6, ktorý obsahuje syntax pre importovanie a exportovanie funkcií a dát, takže môžu byť zdieľané medzi niekoľkými skriptami. Špecifikácia je teraz opravená, ale ešte nie je implementovaná v prehliadačoch a Node.js. Rollup umožňuje písanie kódu pomocou nového systému modulov a zkompiluje ich do existujúcich formátov ako sú moduly CommonJS, AMD, alebo skripty štýlu IIFE. To znamená, že môžete písať kód budúcnosti a využiť výhody princípu “trepania stromov”.

Princíp “trepania stromov”

Použitím ES6 modulov Rollup navyše staticky analyzuje kód, ktorý importujete a vylúči kód, ktorý sa vôbec nepoužíva. Vďaka tomu viete vytvárať súbory na základe existujúcich nástrojov a modulov bez pridávania ďalších závislostí alebo zvyšovania veľkosti projektu.

Napríklad, cez CommonJS sa musí importovať celá knižnica.

// importovať celý projekt utils cez CommonJS
var utils = require( 'utils' );
var query = 'Rollup';
// použiť metódu ajax z projektu utils
utils.ajax( 'https://api.example.com?search=' + query ).then( handleResponse );

Ale keď použijete ES6 moduly, tak namiesto importovania celého projektu utils môžete importovať iba jednu funkciu, ajax, ktorú potrebujete:

// importovať ajax funkciu cez ES6 príkaz import
import { ajax } from 'utils';
var query = 'Rollup';
// privolať funkciu ajax
ajax( 'https://api.example.com?search=' + query ).then( handleResponse );

Pretože Rollup obsahuje iba prosté minimum, výsledkom sú ľahšie, rýchlejšie a menej komplikované knižnice a aplikácie. Pretože tento prístup je založený na zreteľných príkazoch import a export, je efektívnejšie spustiť automatizovaný minifier k zisteniu nepoužitých premenných vo výslednom kóde.

Kompatibilita

Importovanie modulov CommonJS

Rollup vie importovať existujúce moduly CommonJS pomocou rozšírenia.

Zverejňovanie ES6 modulov

Aby sme si boli istí, že vaše ES6 moduly môžu byť použiteľné nástrojmi, ktoré pracujú spolu s CommonJS ako je Node.js alebo webpack, môžete použiť Rollup tak, aby ste kompilovali do formátu UMD alebo CommonJS, a poukázať na skompilovaný súbor pomocou atribútu main v súbore package.json. Ak váš súbor package.json obsahuje atribút module, tak nástroje, ktoré pracujú s ES6 modulmi ako je Rollup a webpack 2 budú napriamo používať verziu s podporou pre ES6 moduly.

Pozrite aj

Vytvárame prvý balíček

Predtým, než začneme sa uistite, že máte nainštalovaný Node.js, aby sme mohli používať npm. Taktiež by ste mali vedieť ako manipulovať s príkazovým riadkom vo vašom stroji.

Najjednoduchšia cesta k používaniu Rollup je použitím rozhrania príkazového riadku (CLI). Na teraz si Rollup nainštalujeme globálne (neskôr sa naučíme ako ho nainštalovať na jednotlivý projekt, aby sme sa uistili, že celý proces tvorby balíkov je prenosný). Do príkazového riadku napíšte:

npm install rollup --global # alebo skrátene: `npm i rollup -g`

Teraz môžete používať príkaz rollup. Skúste to!

rollup

Pretože s príkazom neboli pridané žiadne argumenty, Rollup vypíše inštrukcie použitia. Je to rovanké, ako keby sme spustili rollup --help alebo rollup -h.

Vytvorme jednoduchý projekt:

mkdir -p my-rollup-project/src
cd my-rollup-project

Najskôr vytvoríme prístupový bod. Vložme tento kód do súboru src/main.js:

// src/main.js
import foo from './foo.js';
export default function () {
  console.log(foo);
}

Potom vytvoríme modul foo.js, ktorý bude importovaný prístupovým bodom:

// src/foo.js
export default 'ahoj, svet!';

Teraz môžeme vytvoriť balíček:

rollup src/main.js --format cjs

Možnosť --format určuje, že aký typ balíčka chceme vytvoriť — v tomto prípade, CommonJS (ktorý sa spúšťa v Node.js). Pretože sme neurčili výstupný súbor, obsah sa vytlačí do stdout:

'use strict';

var foo = 'ahoj, svet!';

var main = function () {
  console.log(foo);
};

module.exports = main;

Takto môžete uložiť balíček ako súbor:

rollup src/main.js --format cjs --output bundle.js
# alebo `rollup main.js -f cjs -o bundle.js`

(Taktiež môžete použiť rollup src/main.js > bundle.js, ale toto je menej flexibílne, keď chceme používať zdrojové mapy.)

Teraz môžeme začať používať kód:

node
> var myBundle = require('./bundle.js');
> myBundle();
'ahoj, svet!'

Blahoželáme! Vytvorili ste svoj prvý balíček pomocou Rollup.

Používanie konfiguračných súborov

Zatiaľ je všetko v pohode, ale keď začneme používať viac možností, tak písanie rovnakého príkazu začne byť obťažujúce.

Aby sme sa neopakovali, môžeme vytvoriť konfiguračný súbor, ktorý obsahuje všetky možnosti, ktoré potrebujeme. Konfiguračný súbor je písaný v JavaScripte a je flexibilnejší ako nastavenia v príkazoch.

Vytvorte súbor v koreni projektu, ktorý sa bude volať rollup.config.js a do neho pridajte tento kód:

// rollup.config.js
export default {
  entry: 'src/main.js',
  format: 'cjs',
  dest: 'bundle.js' // ekvivalent možnosti --output
};

Keď chceme použiť konfiguračný súbor, musíme použiť atribút --config alebo -c:

rm bundle.js # aby sme sa uistili, či príkaz funguje
rollup -c

Niektoré nastavenia viete nahradiť nastaveniami v príkazovom riadku:

rollup -c -o bundle-2.js # --output je ekvivalentom atribútu dest

(Vedzte, že Rollup samo o sebe spracúva konfiguračný súbor, čo je dôvod, prečo môžeme používať syntax export default — kód nie je transpilovaný pomocou Babelu alebo niečím podobným, takže môžete používať iba funkcie, ktoré sú podporované vo verzii Node.js, ktorý beží vo vašom stroji.)

Keď chcete, tak môžete určiť iný konfiguračný súbor namiesto predvoleného rollup.config.js:

rollup --config rollup.config.dev.js
rollup --config rollup.config.prod.js

npm run build

Veľa JavaScriptových projektov nasleduje obyčajnú konvenciu: spustenie príkazu npm run build spustí systém tvorby balíčkov, ktorý sa líši medzi projektami. Tento príkaz je užitočný, pretože keď chce niekto prispievať do kódu, tak sa môže doňho ponoriť bez toho, aby vedel o tom, čo sa používa na vytváranie balíčkov (či je to Rollup, Webpack, Gulp alebo niečo viac esoterické). Rollup v tomto prípade nemusí byť inštalovaný globálne, ako sme to robili v prvej sekcii.

Nastavenie vlastného skriptu pre npm run build je príjemné a jednoduché.

Vytváranie súboru package.json

Súbor package.json obsahuje dôležité informácie o vašom projekte, vrátane názvu, verzie, licencie a závislostí. (V skutočnosti nemôžete zverejniť balíček do npm bez súboru package.json — ale stále by ste ho mali mať, keď vytvárate aplikáciu namiesto knižnice.)

Najľahšiou cestou k vytvoreniu súboru je spustením príkazu npm init vo vnútri priečinku projektu a nasledovaním výzviev.

Otvorte súbor package.json a nájdite (alebo vytvorte) sekciu scripts a pridajte príkaz build:

{
  ...,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "rollup -c"
  },
  ...
}

(Predpokladá sa, že v priečinku projektu sa nachádza súbor rollup.config.js.)

Lokálna inštalácia Rollupu

Doteraz sme používali globálnu inštaláciu Rollupu. Je lepšie, keď použijeme lokálnu inštaláciu, pretože každý, ktorý si naklonuje váš projekt a spustí npm install získa kompatibilnú verziu.

Spustite nasledovný príkaz...

npm install --save-dev rollup # alebo `npm i -D rollup`

...a všimnite si, že sekcia devDependencies v súbore package.json obsahuje:

{
  ...,
  "devDependencies": {
    "rollup": "^0.41.4"
  },
  ...
}

Všetky skripty, ktoré sa spustia cez npm run použijú lokálne inštalované verzie príkazov, ako je rollup.

Skúste spustiť príkaz:

npm run build

Znovu-tvorba balíčkov pri zmene súborov pomocou npm run dev

Inštaláciou rollup-watch si môžete vytvoriť skript, ktorý automaticky vytvorí nový balíček, keď sa zmenia zdrojové súbory:

npm install --save-dev rollup-watch
{
  ...,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "rollup -c",
    "dev": "rollup -c -w"
  },
  ...
}

Príkaz rollup -c -w (skratka pre rollup --config --watch) spustí Rollup v režime sledovania.

Začíname s rozšíreniami

Doposiaľ sme vytvárali iba jednoduché balíčky z prístupového bodu a modulu importovaného z relatívnej cesty. Keď začnete vytvárať komplexnejšie balíčky, často budete potrebovať väčšiu pružnosť — importovanie modulov inštalované cez npm, kompilácia kódu cez Babel, práca so súbormi vo formáte JSON a podobne.

Pre tieto účely používame rozšírenia, ktoré zmenia správanie systému v kľučových bodoch procesu tvorby. Zoznam dostupných rozšírení je udržiavaný vo wiki Rollup.

Používanie rozšírení

Pre tento návod použijeme rollup-plugin-json, čo je rozšírenie, ktoré povoľuje Rollupu importovať dáta zo súboru JSON.

Inštalujte rollup-plugin-json ako závislosť pre vývojové prostredie:

npm install --save-dev rollup-plugin-json

(Používame --save-dev namiesto --save, pretože náš spustiteľný kód nezávisí od rozšírenia – používa sa iba počas tvorby balíčka.)

Aktualizujte váš súbor src/main.js tak, aby importoval súbor package.json namiesto src/foo.js:

// src/main.js
import { version } from '../package.json';

export default function () {
  console.log('verzia ' + version);
}

Upravte súbor rollup.config.js tak, aby zahrnul rozšírenie pre spracovávanie súborov formátu JSON:

// rollup.config.js
import json from 'rollup-plugin-json';

export default {
  entry: 'src/main.js',
  format: 'cjs',
  plugins: [ json() ],
  dest: 'bundle.js'
};

Spustite Rollup cez príkaz npm run build. Výsledok by mal vyzerať takto:

'use strict';

var version = "1.0.0";

var main = function () {
  console.log('verzia ' + version);
};

module.exports = main;

(Všimnite si, že iba dáta, ktoré potrebujeme sú importované - name a devDependencies a iné časti súbora package.json sú ignorované. Presne takto funguje princíp “trasenia stromov“!)

Používanie Rollupu spolu s balíčkami z npm

V určitom okamihu je pravdepodobné, že váš projekt bude závislý na balíčkoch z repozitára npm vo vašom priečinku node_modules. Na rozdiel od iných zväzovačov ako sú Webpack alebo Browserify, Rollup nevie samo od seba pracovať so závislosťami — musíme to nastaviť.

Skúsme pridať jednoduchú závislosť nazvanú the-answer, ktorá exportuje odpoveď na otázku života, vesmíru a všetkého možného:

npm install --save the-answer # alebo `npm i -S the-answer`

Všimnite si, že teraz používame --save, takže balíček bude uložený v sekcii dependencies súbora package.json.

Keď upravíme súbor src/main.js...

// src/main.js
import answer from 'the-answer';

export default function () {
  console.log('odpoveďou je ' + answer);
}

...a spustíme Rollup...

npm run build

...uvidíme upozornenie podobné tomuto:

⚠️ 'the-answer' is imported by src/main.js, but could not be resolved – treating it as an external dependency

Výsledný bundle.js bude fungovať v Node.js, pretože príkaz import sa premení na príkaz v CommonJS require, ale balíček the-answer sa nezahrnie do balíčka. Na to potrebujeme rozšírenie.

rollup-plugin-node-resolve

Rozšírenie rollup-plugin-node-resolve naučí Rollup ako pracovať s externými modulmi. Nainštalujte ho...

npm install --save-dev rollup-plugin-node-resolve

...a pridajte ho do konfiguračného súboru:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';

export default {
  entry: 'src/main.js',
  format: 'cjs',
  plugins: [ resolve() ],
  dest: 'bundle.js'
};

Teraz, keď spustíte npm run build, nevypíše sa žiadne upozornenie — balíček bude obsahovať importovaný modul.

rollup-plugin-commonjs

Niektoré knižnice vystavujú ES6 moduly, ktoré môžete importovať tak, ako sú — the-answer je jedným z nich. V súčasnosti, väcšina balíčkov v npm sú namiesto toho vystavení modulom CommonJS. Pokiaľ sa to nezmení, musíme premeniť moduly z CommonJS na ES6, aby ich Rollup vedel spracovať.

Rozšírenie rollup-plugin-commonjs robí presne to isté.

Buďte si vedomí, že rollup-plugin-commonjs má byť pred ostatnými rozšíreniami, ktoré transformujú vaše moduly — to je preto, aby sa predišlo ostatným rozšíreniam, aby vykonávali zmeny, ktoré môžu prerušiť detekciu modulov CommonJS.

Zdieľané závislosti

Povedzme, že vytvárate knižnicu, ktorá ma zdieľanú závislosť ako je React alebo Lodash. Ak nastavíte všetky externé balíčky tak, ako je vysvetlené vyššie, Rollup zabalí do balíčka všetky importy:

import answer from 'the-answer';
import _ from 'lodash';

Taktiež môžete nastaviť, že ktoré importy budú zabalené a ktoré importy budete považovať ako externé. Na tomto príklade budeme považovať lodash ako externý, ale nie the-answer.

Tu je konfiguračný súbor:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';

export default {
  entry: 'src/main.js',
  format: 'cjs',
  plugins: [resolve({
    // nastavenia k rozšíreniu resolve
    customResolveOptions: {
      moduleDirectory: 'node_modules'
    }
  })],
  // toto indikuje, ktoré moduly budu považované za externé
  external: ['lodash'],
  dest: 'bundle.js'
};

A hotovo, lodash bude teraz považovaný za externý modul a nebudé zahrnutý vo vašej knižnici.

Atribút external akceptuje buď pole s názvami modulov alebo funkciu s názvom modulu, ktorý vráti pravdivú hodnotu, ak má byť modul považovaný za externý. Napríklad:

export default {
  // ...
  external: id => /lodash/.test(id)
}

Taktiež môžete použiť tento tvar importovania modulov, ak používate babel-plugin-lodash pre importovanie určitých modulov. V tomto prípade, Babel premení váš príkaz importovania na niečo podobné, ako je toto:

import _merge from 'lodash/merge';

Ak použivate pole pre atribút external, tak pole nevyužíva zástupné znaky, takže tento import bude považovaný za externý iba keď kondícia bude napísaná ako funkcia.

Použivanie Rollupu spolu s Babelom

Väčšina vývojárov používa Babel pre ich projekty, takže môžu využívať futuristické funckie, ktoré nie sú podporované ani prehliadačmi ani Node.js.

Najľahšiou cestou k používaniu Babelu spolu s Rollup je použitím rozšírenia rollup-plugin-babel. Nainštalujte ho pomocou:

npm i -D rollup-plugin-babel

Do rollup.config.js napíšte:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';

export default {
  entry: 'src/main.js',
  format: 'cjs',
  plugins: [
    resolve(),
    babel({
      exclude: 'node_modules/**' // only transpile our source code
    })
  ],
  dest: 'bundle.js'
};

Predtým, než Babel začne kompilovať váš kód, Babel musí byť správne nastavený. Vytvorte nový súbor src/.babelrc:

{
  "presets": [
    ["latest", {
      "es2015": {
        "modules": false
      }
    }]
  ],
  "plugins": ["external-helpers"]
}

Je tam pár neobvyklých vecí v tomto nastavení. Po prvé, musíme nastaviť možnosť "modules": false, pretože inak by Babel premenil naše moduly na moduly CommonJS, než sa Rollup dostane k tvorbe a výsledkom bude chyba.

Po druhé, používame rozšírenie external-helpers, ktorý povoľuje Rollupu zahŕňať akékoľvek pomocné funkcie iba na vrchu balíčka, namiesto toho, aby sme zahŕňali v každom moduli, ktorý ich bude využívať (čo je predvolené správanie).

Po tretie, súbor .babelrc umiestňujeme do priečinka src, namiesto toho, aby sme ho umiestnili do koreňa projektu. Vďaka tomu môžeme mať rôzne konfiguračné súbory s názvom .babelrc pre iné veci, ako sú testy — dobrým nápadom je, aby sme mali rôzne konfigurácie pre rôzne úlohy.

Predtým, než spustíme Rollup, musíme nainštalovať prednastavený balíček latest a rozšírenie external-helpers:

npm i -D babel-preset-latest babel-plugin-external-helpers

Spustením Rollup sa vytvorí balíček... aj keď nevyužívame žiadne ES6 funkcie. Upravte súbor src/main.js:

// src/main.js
import answer from 'the-answer';

export default () => {
  console.log(`odpoveďou je ${answer}`);
}

Spustite Rollup pomocou npm run build a pozrite sa na balíček:

'use strict';

var index = 42;

var main = (function () {
  console.log('odpoveďou je ' + index);
});

module.exports = main;

Zdrojové mapy

Tvorba zdrojových máp môže byť povolená pridaním možnosti --sourcemap počas používania príkazového riadku, alebo pridaním sourceMap: true do konfiguračného súboru.

export default {
  entry: 'src/main.js',
  format: 'umd',
  dest: 'bundle.js',
  sourceMap: true
};

Často kladené otázky

Čo je princíp “trasenia stromov”?

Princíp “trasenia stromov”, alebo princíp “začlenenia živého kódu”, je proces začlenenia iba kódu, ktorý sa využíva. Je podobný princípu “eliminácii mŕtveho kódu”, ale je viac efektívny. Prečítajte si viac o pôvode názvu: Tree-shaking vs Dead-Code Elimination

Prečo sú ES6 moduly lepšie ako AMD alebo CommonJS?

ES6 moduly sú oficiálnym štandardom, ktorý bude čoskoro v prehliadačoch a Node.js. Povoľujú statickú analýzu, ktorá povoľuje optimizácie a obsahuje pokročilé vlastnosti, ako sú okružné referencie alebo živé väzby.

Kto vytvoril logo pre Rollup? Vyzerá krásne.

Ja viem! Vytvoril ho Julian Lloyd.

Porovnanie s ostatnými nástrojmi

táto sekcia bude vyplnená čoskoro...

Používanie Rollupu spolu s Gulp

Rollup vracia funkcie Promise, s ktorými je Gulp oboznámený, takže integrácia je jednoduchá.

Syntax je podobný konfiguračným súborom, ale vlastnosti sú rozdelené spomedzi dvoch rôznych operácií: tvorba balíčka a transpilácia do konečného výstupu.

var gulp = require('gulp'),
  rollup = require('rollup'),
  rollupTypescript = require('rollup-plugin-typescript')
;

gulp.task('build', function () {
  return rollup.rollup({
    entry: "./src/main.ts",
    plugins: [
      rollupTypescript()
    ],
  })
    .then(function (bundle) {
      bundle.write({
        file: "./dist/library.js",
        format: "umd",
        name: "library",
        sourcemap: true
      });
    })
});