de Jake Wiesler

Module ES6 care scutură arborele în webpack 2

Module ES6 care scutura arborele in webpack 2

Webpack 2 tocmai a fost lansat de beta săptămâna trecută. Acesta aduce cu sine o varietate de caracteristici anticipate, inclusiv suport nativ pentru module ES6.

În loc să utilizați var module = require('module') sintaxă, webpack 2 acceptă ES6 imports și exports. Acest lucru deschide ușa pentru optimizări de cod, cum ar fi scuturarea copacilor.

Ce este scuturarea copacilor?

Popularizat de Rich Harris Rollup.js pachet de module, scuturarea copacilor este abilitatea de a include numai cod în pachetul dvs. care este în curs folosit.

Când am jucat prima dată cu Rollup, am fost uimit de cât de bine a funcționat cu modulele ES6. Experiența de dezvoltare tocmai s-a simțit … corect. Aș putea crea module separate scrise în „JavaScript viitor”, apoi le pot include oriunde în codul meu. Orice cod care rămâne neutilizat nu face parte din pachetul meu. Geniu!

Ce problemă rezolvă?

Dacă scrieți JavaScript în 2017 și a intelege (vedea: Oboseala JavaScript) cu diferitele instrumente din jur, experiența ta de dezvoltare se simte probabil destul de fluidă. Acest lucru este important, dar și ceea ce este important este experiența utilizatorului. Multe dintre aceste instrumente moderne sfârșesc prin umflarea aplicațiilor web cu fișiere JavaScript masive, rezultând o performanță mai lentă.

Ceea ce îmi place la pachet este că necesită o lovitură la această problemă și aduce o soluție în prim-planul comunității JavaScript. Acum nume mari, cum ar fi webpack, încearcă să itereze pe el.

Scuturarea copacilor poate să nu fie „Soluția pentru a pune capăt tuturor soluțiilor” dar este o piesă importantă în plăcinta mai mare.

Un exemplu simplu

Înainte de a începe, vreau să vă ofer un exemplu banal de scuturare a copacilor. Aplicația dvs. este formată din 2 fișiere, index.js și module.js.

Interior de module.js exportați 2 funcții cu săgeată numite:

// module.js 

export const sayHello = name => `Hello ${name}!`; 

export const sayBye = name => `Bye ${name}!`

Numai sayHello este importat în index.js fişier:

// index.js 

import { sayHello } from './module'; 

sayHello('World');

sayBye este exportat dar nu importat. Oriunde. Prin urmare, din cauza agitării copacilor, acesta nu va fi inclus în pachet:

// bundle.js 

const sayHello = name => `Hello ${name}!`; 

sayHello('World');

În funcție de pachetul folosit, fișierul de ieșire de mai sus poate arăta diferit. Este doar o versiune simplificată, dar îți vine ideea.

Recent am citit un articol scris de Roman Liutikovși a făcut o mare analogie pentru a vizualiza conceptul de agitare a copacilor:

„Dacă vă întrebați de ce se numește shaking shaking: gândiți-vă la aplicația dvs. ca la un grafic de dependență, acesta este un copac, iar fiecare export este o ramură. Deci, dacă scuturați copacul, ramurile moarte vor cădea ”. – Roman Liutikov

Scuturarea copacilor în webpack 2

Din păcate, pentru cei dintre noi care folosesc webpack, scuturarea copacilor este „în spatele unui comutator”, dacă vreți. Spre deosebire de pachet, unele configurări trebuie făcute înainte de a putea obține funcționalitatea pe care o căutați. Partea „din spatele unui comutator” ar putea confunda unii oameni. Voi explica.

Pasul 1: Configurarea proiectului

Voi presupune că înțelegeți elementele de bază ale webpack-ului și vă puteți găsi drumul în jurul unui fișier de configurare webpack de bază.

Să începem prin a crea un nou director:

mkdir webpack-tree-shaking && cd webpack-tree-shaking

Odată ajuns în interior, să inițializăm un nou npm proiect:

npm init -y

-y opțiunea generează package.json rapid fără a fi nevoie să răspundeți la o grămadă de întrebări.

În continuare, să instalăm câteva dependențe de proiect:

npm i --save-dev webpack@beta html-webpack-plugin

Comanda de mai sus va instala cea mai recentă versiune beta a webpack 2 local în proiectul dvs., precum și un plugin util numit html-webpack-plugin. Acesta din urmă nu este necesar pentru obiectivul acestei soluții, dar va face lucrurile puțin mai rapide.

Notă: Comanda npm i --save-dev webpack@beta este încă recomandat de echipa webpack la momentul scrierii. webpack@beta va fi în cele din urmă eliminată treptat în favoarea webpack ultima comandă. Verificați Cum se descarcă? secțiunea din cea mai recentă postare a versiunii webpack pentru mai multe detalii.

Deschide package.json și asigurați-vă că au fost instalate ca devDependencies.

Pasul 2: Creați fișiere JS

Pentru a vedea cum se clatină copacii în acțiune, trebuie să aveți un JavaScript pentru a vă juca. În rădăcina proiectului dvs., creați un fișier src dosar cu 2 fișiere în interior:

mkdir src && cd src 

touch index.js 

touch module.js

Notă: touch comanda creează un fișier nou prin terminal.

Copiați codul de mai jos în fișierele corecte:

// module.js 

export const sayHello = name => `Hello ${name}!`; 

export const sayBye = name => `Bye ${name}!`;
// index.js 

import { sayHello } from './module'; 

const element = document.createElement('h1'); 

element.innerHTML = sayHello('World'); 

document.body.appendChild(element);

Dacă ați ajuns până aici, structura folderelor ar trebui să arate astfel:

/ 
| - node_modules/ 
| - src/ 
|    | - index.js 
|    | - module.js 
| - package.json

Pasul 3: Webpack din CLI

Deoarece nu aveți fișier de configurare creat pentru proiectul dvs., singura modalitate de a face webpack să facă orice lucru în acest moment este prin CLI-ul webpack. Să efectuăm un test rapid.

În terminalul dvs., rulați următoarea comandă în rădăcina proiectului:

node_modules/.bin/webpack

După ce executați această comandă, ar trebui să vedeți ieșirea astfel:

No configuration file found and no output filename configured via CLI option. A configuration file could be named 'webpack.config.js' in the current directory. Use --help to display the CLI options.

Comanda nu face nimic, iar CLI-ul webpack confirmă acest lucru. Nu ați oferit pachetului web nicio informație despre fișierele pe care doriți să le grupați. Puteți furniza aceste informații prin intermediul liniei de comandă sau un fișier de configurare. Să alegem prima doar pentru a testa că totul funcționează:

node_modules/.bin/webpack src/index.js dist/bundle.js

Ceea ce ați făcut acum este să treceți webpack an entry fișier și un output fișier prin CLI. Aceste informații spun webpack, „du-te la src/index.js și grupați tot codul necesar în dist/bundle.jsȘi face exact asta. Veți observa că acum aveți un dist director care conține bundle.js.

Deschideți-l și verificați-l. Există câteva javascripturi suplimentare în pachet, necesare pentru ca webpack să-și facă treaba, dar în partea de jos a fișierului ar trebui să vedeți și propriul cod.

Pasul 4: Creați un fișier de configurare webpack

Webpack poate gestiona o mulțime de lucruri. Mi-am petrecut o parte din timpul liber scufundându-mă în acest pachet și încă abia am zgâriat suprafața. Odată ce ați trecut exemplele banale, este bine să lăsați CLI în urmă și să creați un fișier de configurare pentru a face față greutății grele.

În rădăcina proiectului dvs., creați un fișier webpack.config.js fişier:

touch webpack.config.js

Acest fișier poate fi la fel de complicat pe măsură ce îl faceți. O vom menține ușoară de dragul acestei postări:

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: 'dist'
  },
  plugins: [
    new HtmlWebpackPlugin({ title: 'Tree-shaking' })
  ]
}

Acest fișier oferă webpack cu aceleași informații pe care le-ați dat CLI-ului mai devreme. Ați definit index.js ca al tau entry fișier și bundle.js ca al tau output fişier. Ați adăugat de asemenea html-webpack-plugin care va genera un fișier html în dist director. Convenabil.

Continuați și testați acest lucru pentru a vă asigura că funcționează în continuare. Eliminați-vă dist director și în linia de comandă tip:

webpack

Dacă totul a decurs fără probleme, vă puteți deschide dist/index.html și vezi „Hello World!”.

Notă: Utilizarea unui fișier de configurare ne oferă comoditatea tastării webpack in loc de node_modules/.bin/webpack. Micile victorii.

Pasul 5: Babel

Am menționat mai devreme că webpack 2 aduce suport nativ pentru modulele ES6. Acest lucru este adevărat, dar nu schimbă faptul că ES6 nu este pe deplin acceptat în toate browserele. Din această cauză, ți se cere transforma codul dvs. ES6 într-un JavaScript ușor acceptabil folosind un instrument ca Babel. Împreună cu webpack, Babel ne oferă posibilitatea de a scrie „viitorul dvs. JavaScript” fără să vă faceți griji cu privire la implicațiile browserelor neacceptate.

Să mergem mai departe și să instalăm Babel în proiectul dvs.:

npm i --save-dev babel-core babel-loader babel-preset-es2015

Ia act de babel-preset-es2015 pachet. Tipul ăsta mic este motivul pentru care m-am așezat să scriu toate acestea.

Pasul 6: babel-loader

Webpack poate fi configurat pentru a transforma fișiere specifice în module prin încărcătoare. Odată transformate, acestea sunt adăugate la un grafic de dependență. Webpack folosește graficul pentru a rezolva dependențele și include doar ceea ce este necesar în pachetul final. Aceasta este baza pentru modul în care funcționează webpack.

Acum puteți configura webpack pentru utilizare babel-loader pentru a vă transforma toate .js fișiere:

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: { filename: 'bundle.js', path: 'dist' },
  module: {
    rules: [
      {
        test: /.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: { 
          presets: [ 
            'es2015' 
          ] 
        }
      }
    ]
  },
  plugins: [ 
    new HtmlWebpackPlugin({ title: 'Tree-shaking' }) 
  ]
};

module proprietatea oferă un set de instrucțiuni pentru webpack. Se spune „luați toate fișierele care se termină cu .js și transformați-le folosind babel-loader, dar nu transformați niciun fișier în interiorul node_modules! “

Trecem și de babel-preset-es2015 pachet ca opțiune pentru babel-loader. Acest lucru spune doar babel-loader Cum pentru a transforma JavaScript.

Alerga webpack din nou pentru a vă asigura că totul este bun. Da? Grozav! Ceea ce am făcut este să împachetăm fișierele dvs. JavaScript în timp ce le compilăm în JavaScript care sunt ușor acceptate în toate browserele.

Problema de bază

Pachetul babel-preset-es2015 conține un alt pachet numit babel-plugin-transform-es2015-modules-commonjs care transformă toate modulele dvs. ES6 în CommonJS module. Acest lucru nu este ideal și iată de ce.

Pachetele Javascript, cum ar fi webpack și Rollup, pot efectua agitarea copacilor numai pe module care au o structură statică. Dacă un modul este static, atunci grupul poate determina structura sa la momentul construirii, eliminând în siguranță codul care nu este importat nicăieri.

CommonJS modulele nu au o structură statică. Din acest motiv, webpack nu va putea scutura codul neutilizat din pachetul final. Din fericire, Babel a atenuat această problemă oferind dezvoltatorilor o opțiune pe care o puteți transmite către dvs. presets matrice împreună cu babel-preset-es2015:

options: { presets: [ [ 'es2015', { modules: false } ] ] }

Potrivit lui Babel documentație:

“modules – Activați transformarea sintaxei modulului ES6 la un alt tip de modul (Activat în mod implicit la „commonjs”). Poate fi false să nu transforme module sau unul dintre ["amd", "umd", "systemjs", "commonjs"].

Glisați acest bit suplimentar de cod în configurația dvs. și veți găti cu ulei de arahide.

Starea finală a webpack.config.js arata asa:

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: { filename: 'bundle.js', path: 'dist' },
  module: {
    rules: [
      {
        test: /.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: { 
          presets: [ 
            [ 'es2015', { modules: false } ] 
          ] 
        }
      }
    ]
  },
  plugins: [ new HtmlWebpackPlugin({ title: 'Tree-shaking' }) ]
};

Marea finală

Alerga webpack din nou și deschideți-vă bundle.js fişier. Nu veți observa nicio diferență. Înainte de a înnebuni, știi asta! E bine. Am rulat webpack în modul de dezvoltare tot acest timp. Webpack știe că aveți exporturi neutilizate în cod. Chiar dacă este inclus în pachetul final, sayBye nu va ajunge niciodată la producție.

Dacă tot nu mă crezi, fugi webpack -p în terminalul tău. -p opțiunea înseamnă producție. Webpack va efectua câteva optimizări suplimentare de performanță, inclusiv reducere, eliminând orice cod neutilizat pe parcurs.

Deschide bundle.js. Deoarece este minimizat, continuați și căutați Hello. Aceasta ar trebui să sa fii acolo. Caută Bye. Aceasta nu ar trebui.

Voila! Acum aveți o implementare funcțională a agitării copacilor în webpack 2!

Pentru curioși, am fost încet iterați asupra propriei mele configurații ușoare de webpack într-un GitHub Repo:

jake-wies / webpack-hotplate
webpack-hotplate – Un webpack boilerplate pentru proiecte personale
github.com

Nu este menit să fie prea exagerat și umflat. Se concentrează pe a fi o placă de cazan accesibilă, cu pasaje la fiecare pas. Dacă sunteți interesat, verificați-l!

Dacă aveți întrebări, nu ezitați să contactați Stare de nervozitate!