Jak postupně přepnout na webpack

Toto je druhá část ze dvou částí o tom, proč a jak jsme přepnuli náš systém sdružování JavaScriptu z ad hoc systému Grunt úkolů a PHP na deklarativní konfiguraci webového balíčku. Klepnutím sem přejdete na stránku Proč jsme přešli na webpack a zjistili jste, proč jsme přešli na webpack.

Tento článek je pro vás, pokud má systém sestavování kódu JavaScript vaší kódové základny podobné problémům jako v našem Proč jsme přešli na webpack a chcete migrovat na webpack inkrementálním způsobem tak, že jej rozdělíte na menší kroky. Některé části tohoto článku jsou specifické pro AngularJS 1.x, ale zbytek lze použít na jakýkoli rámec.

Chcete-li migraci učinit co nejbolestivější, rozdělte ji na tyto kroky:

  1. Představte webpack vedle stávajícího systému sestavení beze změny kódu aplikace.
  2. Používejte webpack během vývoje na určitou dobu a vyřešte problémy hned, jak se objeví. Ukončete používání starého systému sestavení, ale nadále jej používejte ve výrobě.
  3. Odstraňte zastaralý systém sestavení a ponechte pouze webpack.
  4. Aktualizujte kódovou základnu vylepšeními, která jsou nyní možná s webpackem.

Rozdělením migrace na tyto kroky nemusíte trávit počáteční čas, který by byl stráven testováním všeho a pokrytím všech okrajových případů, abyste zajistili, že nový systém sestavení bude fungovat ve výrobě; jednoduše pokračujte v používání stávajícího systému sestavení pro výrobní nasazení.

Během vývoje okamžitě získáte výhody z určitých funkcí webového balíčku, jako jsou rychlé doby opětovného sestavení a ladění založené na sourcemapu, a pokud dojde k problému s novým krokem sestavení, můžete se vždy vrátit zpět ke svému starému.

1. Představte webpack vedle stávajícího systému sestavení

Začněte tím, že replikujete základní funkce vašeho starého systému sestavení potřebné pro sestavení aplikace:

  • Vytvoření balíčku JavaScriptu
  • Vytvoření balíčku CSS
  • Vykreslování cest JS / CSS do vaší šablony HTML

Upozorňujeme, že z tohoto seznamu můžete vyloučit pokročilejší požadavky, jako je minifikace, sdružování pro testy karmy nebo sdružování přeložených jazykových řetězců. To lze řešit během kroku # 2.

Vytvoření balíčku JavaScriptu

Váš stávající systém sestavení pravděpodobně zahrnuje krok zřetězení, který zkombinuje mnoho skriptů do jednoho, například s grunt-Contrib-concat:

grunt.initConfig ({
  concat: {
    js: {
      soubory: [{
        src: [
          'vendor / lodash.js',
          'vendor / jquery.js',
          'vendor / angular.js',
          'vendor / angular-cookies.js',
          'app / scripts / ** / *. js'
        ],
        dest: 'build / js /'
      }]
    }
  }
});

Naštěstí je webpack dostatečně flexibilní, aby toto chování replikoval pomocí importu-loaderu, exportu-loaderu a kontextu:

Chcete-li, aby se váš balíček JS webpacku choval stejně jako váš starý svazek zřetězení skriptů, vytvořte nový soubor .js, který bude sloužit jako váš vstupní bod pro webový balíček, a použijte import-loader a export-loader k importu závislostí a exportu hodnot pro skripty dodavatelů, např

// app / app.js
// Importujte staré skripty dodavatele ve správném pořadí
window._ = vyžadovat (
  '../vendor/lodash'
);
$. window.jQuery = vyžadovat (
  '../vendor/jquery'
);
window.angular = vyžadovat (
  "export? window.angular! ../ prodejce / úhlové"
);
vyžadovat(
  "import? angular => window.angular!" +
  '../vendor/angular-cookies'
);
// ... aplikační skripty

Protože každý skript dodavatele má různé závislosti a exportované hodnoty, musí být každý zkontrolován ručně, aby se určilo, zda a jak použít import-loader a export-loader. Nezapomeňte přiřadit globální proměnné `window`, abyste se ujistili, že jsou dostupné ve vašem kódu aplikace.

Pokud je třeba váš kód aplikace také spustit v určitém pořadí, můžete jednoduše „vyžadovat“ každý soubor postupně, např.

// app / app.js
// ... skripty dodavatele
vyžadují ('./ skripty / modulA');
vyžadují ('./ skripty / modulB');
vyžadují ('./ scripts / moduleC');
// ...
vyžadují ('./ skripty / hlavní');

Nebo, pokud váš kód aplikace může být spuštěn v jakémkoli pořadí (např. Pokud používáte moduly AngularJS), můžete využít kontextu webového balíčku k `vyžadovat 'všechny tyto soubory najednou:

// app / app.js
// ... skripty dodavatele
/ **
 * `vyžadují` všechny moduly v daném kontextu webpacku
 * /
funkce vyžadujíVšechny (kontext) {
  context.keys (). forEach (context);
}
// Shromažďujte všechny úhlové moduly
requAll (requ.context (
  './scripts',
  / * použijte podadresáře: * / true,
));

Pro práci se soubory JS je to všechno! Nebyly nutné provádět žádné změny skriptů dodavatele nebo kódu aplikace; stačí pouze upravit vstupní bod webového balíčku. Je důležité, abyste neupravovali samotný kód aplikace, abyste zajistili, že budete moci pokračovat ve vytváření pomocí předchozího systému sestavení.

Vytvoření balíčku CSS

Krok sestavení CSS pravděpodobně zahrnuje krok preprocesoru, jako například u Stylusu pomocí grunt-Contrib-stylus:

grunt.initConfig ({
  stylus: {
    kompilovat: {
      soubory: {
        src: 'app / css / main.styl',
        dest: 'build / css / main.css'
      }
    }
  }
});

webpack nabízí sadu nakladačů pro zpracování a výstup CSS:

  • stylus-loader / sass-loader / less-loader: spustí daný preprocesor v souborech CSS a vrací obyčejný CSS
  • css-loader: vyřeší `@ import` /` url (… )` a vrátí výsledný CSS
  • url-loader / file-loader: inline nebo emits content file in output webpack, jako font nebo image `url (...)` s v CSS
  • extract-text-webpack-plugin: přesune váš CSS do samostatného výstupního souboru, místo aby jej vložil do HTML

Konfigurace webpacku pomocí těchto zavaděčů je ponechána jako cvičení pro čtenáře, ale jakmile je nakonfigurováno, přidání šablony stylů do sestavení webpacku je stejně jednoduché jako přidání požadavku „(...)“ do vstupního bodu:

// app / app.js
vyžadují ('./css / main.styl');
// ... skripty dodavatele
// ... aplikační skripty

Poznámka: Krok sestavení CSS nemusí být nutně součástí sestavení webového balíčku; mohli jsme se například rozhodnout přepnout na jednoduchý npm skript, který vyvolá příkaz `stylus`. Používáním webpacku však získáme několik výhod:

  • K vytvoření JS i CSS je třeba spustit pouze webpack. není nutné spouštět samostatný příkaz k vytvoření CSS.
  • Do výstupu webpacku jsou automaticky zahrnuta aktiva obrazu / písma uvedená v CSS; není třeba je kopírovat do výstupní složky a spravovat cesty aktiv pomocí jiné metody.
  • file-loader automaticky vygeneruje hashované názvy souborů pro dlouhodobé ukládání souboru CSS do mezipaměti a zahrnutých písem / obrázků.

Vykreslování cest JS / CSS do vaší šablony HTML

Posledním krokem k tomu, aby bylo možné provozovat webpack i váš starý systém sestavení na stejné kódové základně, je vykreslení nového majetku webového balíčku JS / CSS do šablony HTML vašeho webu.

Cesty všech výstupních prostředků webového balíčku můžete zachytit pomocí objektu „Statistiky“, který se vrátí po dokončení sestavení. Jednoduchý způsob, jak předat tato data do vaší šablony HTML, je přes stats-webpack-plugin:

// webpack.config.js
const StatsPlugin = vyžadovat ('statistics-webpack-plugin');
module.exports = {
  // ...
  pluginy: [
    // ...
    new StatsPlugin ('webpack-statistics.json', {
      kusy: nepravdivé,
      moduly: false,
      děti: nepravdivé,
      cache: false,
      důvody: nepravdivé,
      zdroj: false,
      errorDetails: false,
      chunkOrigins: false,
    })
  ]
};

Chcete-li snadno přepínat mezi webpackem a starým systémem sestavení, můžete jednoduše vykreslit cesty aktiv webpacku, pokud ve vaší výstupní složce existuje webpack-statistics.json, jinak se vraťte zpět na cesty aktiv starého systému sestavení.

Například pomocí PHP:

To jsou všechny kusy potřebné k tomu, aby fungoval minimální webpack build! Nyní by měl být váš projekt v tomto stavu:

  • Spusťte svůj starý krok sestavení (např. „Grunt build“), který vytvoří složky JS / CSS ve složce sestavení, což způsobí, že šablona HTML vašeho webu bude starým způsobem vykreslovat cesty aktiv.
  • Spusťte `webpack`, který vytvoří složky JS / CSS a webpack-statistics.json ve složce buildu, což způsobí, že šablona HTML vašeho webu vykreslí cesty aktiv pomocí webpack-statistics.json.

2. Během vývoje používejte webpack a snižujte používání starého systému sestavení

Během této fáze řekněte ostatním vývojářům projektu, aby místo starého systému sestavení používali webpack. Pokud se vyskytnou nějaké problémy (například chybně nakonfigurovaný zavaděč), můžete je bezpečně vyřešit bez ovlivnění výroby, protože výroba dosud používá starý systém sestavení.

V této fázi byste také měli nakonfigurovat náhrady za jakékoli další úkoly, které starý systém sestavení provádí, jako je minifikace aktiv, provádění karmy nebo překlady jazyků.

Pokud používáte spouštěč úloh, jako je Grunt nebo Gulp, pak npm skripty jsou často jednodušší alternativou k úkolům Grunt / Gulp.

Zde uvádíme několik alternativ úkolů Grunt:

  • grunt-karma: rozhraní karmy z příkazového řádku (`karma start`)
  • grunt-angular-gettext: angular-gettext-cli + angular-gettext-loader
  • grunt-angular-templates: ngtemplate-l0ader

Na konci této fáze byste měli mít:

  • Npm skript, který nahradí každou úlohu sestavení, např. `npm run bundle: watch` to bundle & watch během vývoje,` npm run bundle: production` pro bundling & minify s jazykovými překlady, `npm run karma` pro spuštění testů Karma
  • Důkladně otestujte celou svou aplikaci, abyste se ujistili, že funguje správně: dejte si pozor na chybějící skripty nebo šablony stylů, protože tyto mohou způsobit poškození aplikace.

3. Odstraňte zastaralý systém sestavení a ponechte pouze webpack

Tato část je jednoduchá: jednoduše nakonfigurujte skript vytváření sestav CI tak, aby spouštěl nové skripty vytváření sestav npm (jako `npm test && npm run bundle: production`), odstraňte starou konfiguraci spouštěče úloh (Gruntfile.js / gulpfile.js / atd.) a odeberte nyní nepoužité závislosti z balíčku.json.

Pokud také webpack-statistics.json neexistuje, budete chtít smazat kód z vaší šablony HTML, který spadá zpět do vašeho starého systému sestavení.

Pokud jste svou aplikaci důkladně otestovali v předchozí fázi, měla by tato fáze proběhnout bez problémů. Samozřejmě byste měli nejprve nasadit do testovacího prostředí podobného produkci, abyste byli v bezpečí.

4. Aktualizujte kódovou základnu pomocí vylepšení povolených webpackem

Nyní, když je webpack jediným systémem sestaveným na místě, můžeme vyřešit problémy původně popsané v Proč jsme přešli na webpack:

Řešení závislostí

Pamatujete si, jak nastavíte vstupní bod webového balíčku pro import skriptů globálně, v závislosti na prvním pořadí?

// app / app.js
vyžadují ('./css / main.styl');
// Importujte staré skripty dodavatele ve správném pořadí
window._ = vyžadovat (
  '../vendor/lodash'
);
// ...
vyžadují ('./ skripty / modulA');
vyžadují ('./ skripty / modulB');
vyžadují ('./ scripts / moduleC');
// ...
vyžadují ('./ skripty / hlavní');

Není ideální pokračovat v importu tímto způsobem: zajištění správného pořadí může být náchylné k chybám a znečištění globálního jmenného prostoru může být problematické.

Místo toho můžete nyní importovat závislosti do modulu, kde se používají, např. pokud main.js závisí na lodash.js, moduleA.js a moduleC.js:

// app / scripts / main.js
var _ = vyžadovat ('../../ prodejce / lodash');
var A = požadavek ('./ moduleA');
var C = požadavek ('./ moduleC');
// ...

A pokud moduleB.js závisí pouze na moduA.js:

// app / scripts / moduleB.js
var A = požadavek ('./ moduleA');
// ...

Jakmile je modul explicitně importován všemi jeho závislými, může být odebrán ze vstupního bodu webového balíčku: přechod jednoho modulu najednou, a váš vstupní bod webového balíčku bude nakonec ponechán pouze s:

// app / app.js
vyžadují ('./css / main.styl');
vyžadují ('./ skripty / hlavní');

Používání npm balíčků

Nyní můžete začít používat npm balíčky namísto kopírování modulů třetích stran do úložiště: inovace balíčků se stává snadnější, sdílené přechodné závislosti snižují duplicitu kódu a již nemusíte vytvářet vlastní balíčky UMD.

Mělo by to být tak jednoduché, jako když provedete `npm install `, pak aktualizujete odkazy na modul, změnit toto:

var _ = vyžadovat ('../../ prodejce / lodash');

K tomuto:

var _ = vyžadovat ('lodash');

Nyní, když jsou závislosti explicitní a používáme npm balíčky, dosáhli jsme (alespoň poněkud) cíle, kterým je snazší pochopení kódové základny. A také jsme vylepšili paritu dev-prod, protože webpack nyní s našimi závislostmi na modulech pracuje stejným způsobem jak ve vývoji, tak ve výrobě: jediným rozdílem je to, že výrobní sestavení je minimalizováno.

Samozřejmě jsme také připravili kódovou základnu pro budoucnost, kde je jednodušší začít používat ES2015 + zapnutím babel-loaderu, a použití React a Redux se stává snadnější díky možnosti používat balíčky JSX a npm.

Toto byl přechod, který v poslední době úspěšně proběhla kódová základna aplikace EventMobi. Pokud je váš projekt v podobné podobě, doufám, že to poskytlo určitý náhled, jak jej vylepšit!

[Pokud se vám tento článek líbil, klikněte na malou nalevo, aby to ostatní věděli. Pokud chcete více podobných příspěvků, sledujte publikaci EventMobi s tlačítkem (Sledovat) na pravé straně!

Nakonec, pokud se vaše řešení objeví ve vaší uličce, najmeme! Podívejte se na naše současné otevřené pozice na adrese http://www.eventmobi.com/careers/]