Møt Grunt Byggverktøyet for JavaScript

Hvis du jobber med et stort prosjekt, vil du uten tvil ha et byggeskript eller en mengde oppgaveskript for å hjelpe deg med noen av de repeterende delene av prosessen. Du kan bruke Ant eller Rake, avhengig av hvilket språk prosjektet er skrevet inn i.

Men hva bruker du hvis prosjektet primært er JavaScript? Det er problemet Ben Alman satt opp for å løse da han opprettet Grunt.


Hva er Grunt, uansett?

Hva er Grunt? Vel, README på Github sier

Grunt er et oppgavebasert kommandolinjebyggingsverktøy for JavaScript-prosjekter.

Her er ideen: Når du jobber med et JavaScript-prosjekt, er det en rekke ting du vil gjøre regelmessig. Liker hva, spør du? Vel, som å sammenkalle gitt filer, kjører JSHint på koden din, kjører tester eller minifiserer skriptene dine. Hvis du limer JavaScript inn i JSHint online, forstår du sannsynligvis at det er en bedre måte å gjøre det på. selv om du bruker katt for å sammenkoble filer eller en kommandolinje minifier, ville det være fint å ha et enkelt, enhetlig sett med kommandoer for alle de ekstra oppgavene, som fungerte for hvert enkelt JavaScript-prosjekt, til høyre?

Det er det Grunt har som mål å være. Den har en rekke innebygde oppgaver som får deg ganske langt, med muligheten til å bygge dine egne plugins og skript som utvider grunnleggende funksjonalitet.

For mer Grunt intro godhet, se Bens innlegg på sin personlige blogg og Bocoup bloggen.


Hvordan installerer jeg Grunt?

Grunt er bygget på Node.js, og det er tilgjengelig som en pakke via Node pakkebehandling (npm). Du vil installere den globalt, så bruk denne kommandoen:

npm installere -g grunt

Du vil legge merke til at det installerer ganske mange avhengigheter; Det finnes andre npm-pakker som Grunt bruker. Når det er gjort, er du klar til å gå!


Hvordan bruker jeg Grunt?

Som du vet, er Grunt et kommandolinjeverktøy; derfor antar jeg at du har et terminalvindu åpent for resten av denne opplæringen.

La oss starte med å opprette en prøveprosjektkatalog; Vi skal faktisk ikke bygge et prosjekt her, men vi ser hvordan Grunt fungerer i denne katalogen. Når du er i den katalogen, kjør du grynte kommando (i henhold til dokumentasjonen, hvis du er på Windows, må du kanskje løpe grunt.cmd). Du ser sannsynligvis noe slikt ut:

 Kan ikke finne 'grunt.js' konfigurasjonsfil. Trenger du noe hjelp? 

Før du virkelig kan utnytte Grunt til sitt fulle potensial, trenger du en grunt.js fil i prosjektkatalogen. Heldigvis kan Grunt automatisk generere en grunt.js fil-og et annet prosjektskjelettmateriale - med i det oppgave, som kan kjøre uten en grunt.js filen på plass. Men grunt init Det er fortsatt ikke nok å få prosjektet ditt startet, som du vil se om du kjører det. Du må velge en type prosjekt for å generere. Løping grunt init vil gi deg en liste over prosjekttyper å velge mellom:

  • jquery: En jQuery-plugin
  • node: En nodemodul
  • commonjs: En CommonJS-modul
  • gruntplugin: En Grunt-plugin
  • gruntfile: En Gruntfile (grunt.js)

Hvis prosjektet ditt ikke stemmer overens med noen av de fire første prosjekttyper, kan du bruke den endelige: gruntfile: det skaper bare en grunnleggende grunt.js som du kan fylle inn. Så, la oss prøve dette, med jQuery-pluginmalen. Løpe Grunt init: jquery i terminalen din.

Du vil legge merke til mye innledende utgang. Hvis du tar deg tid til å lese malnotene, ser du at vi må fylle ut noen få verdier, som prosjektnavn og prosjekttittel. Faktisk, etter det notatet, ser du noe slikt:

Vennligst svar på følgende: [?] Prosjektnavn (jquery.demo)

Når du starter et prosjekt, vil Grunt spørre deg en rekke spørsmål, så det kan fylle ut noen alternativer. Den verdien i parentesene? Det er standardforslaget, basert på prosjekttype og navnet på prosjektkatalogen. Hvis du vil endre det, skriv ditt eget prosjektnavn på slutten av linjen og trykk 'enter'; ellers bare trykk 'enter' for å bruke standardnavnet.

Fortsett å gå og fyll inn resten av feltene. For et jQuery-pluginprosjekt, her er hva du trenger for å gi det:

  • Prosjekt tittel
  • Beskrivelse
  • Versjon
  • Project git repository
  • Prosjektets hjemmeside
  • Prosjektproblemer tracker
  • lisenser
  • Forfatternavn
  • Forfatter e-post
  • Forfatter url
  • Nødvendig jQuery-versjon

Mange av disse har standardverdier; hvis du vil bruke standardverdien, bare trykk Enter for den linjen; For å forlate feltet tomt, kan du bare skrive "ingen". Når du har gått gjennom alle alternativene, ser du at Grunt lager noen grunnleggende prosjektfiler. Som hva? Som dette:

LISENS-GPL LICENSE-MIT README.md grunt.js libs | - jquery | | - jquery.js | - qunit | - qunit.css | - qunit.js package.json src | - jquery.demo.js test | - jquery.demo.html | - jquery.demo_test. js

Som du kan se, gir dette oss en god start: Ikke bare har vi vår pluginfil (src / jquery.demo.js), vi har også Qunit-tester (test / jquery.demo_test.js). Og det er heller ikke tomme filer. De har noen innledende innhold, med en så super-grunnleggende jQuery-plugin og enhetstester. Gå videre og sjekk ut innholdet i disse filene, du vil se hva jeg mener.

Grunt gjør mer enn å sette opp prosjektet for deg.

Selvfølgelig gjør Grunt mer enn å sette opp prosjektet for deg. Spesielt har prosjektet vårt nå grunt.js: en prosjektspesifikk konfigurasjonsfil; På grunn av alternativene det setter, kan vi nå bruke Grunts andre innebygde oppgaver. Snart vil vi spre det åpent og gjøre noen tilpasninger, men for nå la vi løse noen oppgaver.

Hvis du kjører grynte Med ingen alternativer nå, kjører vi standardoppgaven, hvis en er satt. I tilfelle av et jQuery-pluginprosjekt, svarer det til å kjøre disse fire kommandoene:

  • grunt lint: sjekker JavaScript mot JSHint
  • grunt qunit: Kjører Qunit-testene dine
  • grunt concat: sammenkobler prosjektfiler sammen og legger den nye filen i en dist mappe
  • grunt min: Minifiserer filen concat slukke.

Jeg bør merke noe om Qunit-testene her: Qunit-tester er ment å løpe i nettleseren som standard; bare åpen tester / jquery.demo.html (eller tilsvarende) i nettleseren. Imidlertid grunt qunit testen vil kjøre dem på terminalen, noe som betyr at du må ha PhantomJS installert. Det er ikke vanskelig: bare gå over til phantomjs.org og last ned og installer den nyeste versjonen. Hvis Grunt kan finne det i din bane, vil det være i stand til å kjøre Qunit-testene fra terminalen.

Så, kjører grynte bør gi deg utgang til lignende til dette:

Som du kan se, har hver av våre fire oppgaver kjørt. Hvis noen av dem skulle mislykkes, vil resten av oppgavene bli kansellert (med mindre du ringer Grunt med --makt flagg).


Hvordan tilpasser jeg mine oppgaver?

Allerede, vi har fått mye flott funksjonalitet ut av Grunt, bruker den akkurat som den kommer. Men la oss sprekke åpne det grunt.js fil og gjør noen konfigurasjon.

Innsiden grunt.js, Du vil se at all konfigurering er gjort ved å sende et objekt bokstavelig til grunt.initConfig (). La oss se på noen av egenskapene til konfigurasjonsobjektet.

pkg

Denne eiendommen peker til package.json fil som Grunt opprettet i vår prosjektkatalog. Har en package.json filen er en del av CommonJS Packages-spesifikasjonen; Det er et enkelt sted der de fleste metadataene om prosjektet (navn, versjon, hjemmeside, repository link ... mange av verdiene du angir når du initialiserer prosjektet) kan lagres. Men dette pkg Egenskapen gjør mer enn å peke på pakkefilen: Legg merke til syntaksen: ''. Det er en av Grunt's innebygde direktiver: det laster faktisk JSON-filen, så Grunt (eller du) kan få tilgang til alle egenskapene i package.json-filen fra pkg eiendom.

meta

De meta eiendom er et objekt med bare en eiendom: et banner. Dette banneret er kommentaren som går øverst på sammenkjøpte eller minifiserte prosjektfiler. Som du kan se, er det en streng med noen maletiketter (<%= %>); i de fleste tilfeller omgir kodene et anrop til en eiendom på pkg eiendom, for eksempel pkg.title. Du kan imidlertid også utføre funksjoner fra innsiden av disse kodene: bruken av grunt.template.today () og _.plukke() viser oss det.

concat / min / qunit / lo / se

Jeg har gruppert de neste fem egenskapene sammen fordi de er veldig like. De alle angir alternativer for bestemte oppgaver, oppgavene de er oppkalt etter. Når du konfigurerer disse oppgavene, er det viktig å merke seg at Grunt skiller mellom to typer oppgaver: vanlige oppgaver og multitasks. I utgangspunktet er forskjellen at vanlige oppgaver bare har et sett med konfigurasjonsalternativer, mens multitasks kan ha flere sett med instruksjoner (kalt mål). Av de fem oppgavene jeg oppførte i overskriften til denne delen, er den eneste som ikke er en multitask se.

Legg merke til at i vårt config-objekt, er qunit og lo Egenskaper er begge gjenstander med filer eiendom. filer er et enkelt mål for denne oppgaven. I begge tilfeller er de en rekke filer som skal brukes når du utfører denne oppgaven. La oss si at jeg vil kunne lune bare filene i src sub-katalogen. Jeg kunne legge til et annet mål slik at lo eiendom ville se slik ut:

lint: files: ['grunt.js', 'src / ** / *. js', 'test / ** / *. js'], src: ['src / ** / *. js'],

Nå, bare lint filene i src, jeg løper grunt lint: src: Jeg sender målnavnet etter et kolon. Hvis jeg bare kjører grunt lint, begge målene vil bli kjørt.

I tilfelle av concat og min Oppgaver, målene er mer kompliserte: de er objekter med kilde (src) og destinasjon (dest) eiendommer. Selvfølgelig forteller dette Grunt hvor å få filene og hvor de skal sette dem når det er ferdig med å behandle dem, henholdsvis. Hvis du legger til andre filer i prosjektet ditt, vil du legge til dem på riktig sted for å sikre at de blir sammenkalt og minifisert korrekt. Så, hvis jeg la til en src / utils.js fil som min jQuery-plugin var avhengig av, ville jeg endre concat.dist.src til dette:

src: ['',' src / utils.js ','.js> '],

Når du ser nærmere på noen av disse oppgavene, vil du legge merke til noen andre direktiver: det viktigste er sannsynligvis det direktiv. Dette gir deg tilgang til egenskapene til andre oppgaver for gjenbruk. Du vil legge merke til at konfigurasjonen for se oppgaven bruker , slik at den opererer på samme liste over filer som vi ga til lo oppgave. Du kan lære mer om de andre direktivene i Grunt-dokumentene.

Snakker om klokkeoppgaven, hva gjør det egentlig? Veldig enkelt: det løper oppgavene i oppgaver eiendom når en fil i den listen over filer er endret. Som standard er lo og qunit oppgavene kjøres.

jshint

Denne egenskapen konfigurerer bare hvilke "dårlige deler" JSHint ser etter i JavaScript. Den komplette listen over opsjoner finnes på JSHints nettstedssider.


Hele bunnen av vår grunt.js fil, vil du se denne linjen:

grunt.registerTask ('standard', 'lint qunit concat min');

Dette er hva som skaper standardoppgaven vår; du vet, den som kjører når vi kjører bare grynte. Det oppretter faktisk en aliasoppgave, og du kan opprette så mange aliasoppgaver som du vil:

grunt.registerTask ('src', 'lint: src qunit: src concat: src min: src');

Forutsatt at du opprettet src Mål for hver av oppgavene, kan du nå ringe grunt src og gjør akkurat det du vil ha.


Hvordan bruker jeg tredjepartsoppgaver?

Selv om oppgavene som følger med Grunt, blir ganske langt, kan du trolig tenke på andre ting du vil gjerne automatisere. Ikke bekymre deg: Grunt kommer med en API som lar alle å lage Grunt-oppgaver og plugins. Selv om vi ikke skal skape noen Grunt-oppgaver i denne opplæringen, hvis du er interessert i det, bør du begynne med Grunt-pluginmalen (løp Grunt init: Gruntplugin), og les deretter gjennom API-dokumentene. Når du har skrevet opp oppgaven din, kan du laste den inn i et prosjekt ved å legge til denne linjen inne i prosjektets grunt.js fil:

grunt.loadTasks (PATH_TO_TASKS_FOLDER);

Merk at parameteren ikke er banen til selve oppgavefilen, det er banen til mappen oppgavefilen er i.

Andre Grunt-plugins begynner imidlertid å vises, og noen er tilgjengelige på NPM. Etter at du har installert dem via npm installasjon, du laster dem inn i prosjektet ditt med denne linjen:

grunt.loadNpmTasks (PLUGIN_NAME);

Selvfølgelig vil du sjekke plugin dokumentasjonen for å se hva du bør legge til i konfigurasjonsobjektet.

Hvilke Grunt-plugins er tilgjengelige? Vel, siden Grunt er så nytt (mindre enn en måned gammel mens jeg skriver dette), er det ikke for mange ennå. Jeg har funnet to:

  • grynt-css: for linting og minifisering av CSS
  • grynt-jasmin-oppgave: for å kjøre Jasmine-spesifikasjoner

Hvis du har funnet andre, vil jeg gjerne høre om dem; post dem i kommentarene!


Konklusjon

Selv om Grunt er et helt nytt prosjekt, er det nesten ikke ufullstendig; som vi har sett, kommer det med stort sett alt du trenger for å bruke det på et stort prosjekt, og kan utvides så mye du vil.

Jeg håper Grunt blir en fellesskapsstandard, og at vi får se mange oppgaver, plugins og init-maler som dukker opp i nær fremtid. Hva føler du om det?