Parempi puiden ravistus syväanalyysin avulla

Tässä on projekti GSoC 2018: ssa: Paranna puiden ravistamista laajasti käytetyssä JS-koodipaketissa verkkopakkauksessa.

esittely

Puiden ravistaminen, DCE: n (kuolleen koodin eliminoinnin) tukitoiminto, joka auttaa DCE: tä moduulien välisessä käytössä, on kriittinen ominaisuus nipussaajalle. Se pätee erityisesti JS: lle. Nipun koon pienentäminen tarkoittaa verokustannusten pienentämistä joka kerta, kun paketti toimitetaan verkkosovellusta varten.

Github-projekti

中文 版

Ilman tätä laajennusta

Ennen tämän laajennuksen käyttöönottoa webpack käyttää erittäin yksinkertaista ratkaisua DCE: hen. Esimerkiksi:

Yllä olevassa esimerkissä webpack löytää viitteet tuotuihin muuttujiin. On selvää, että isNumberiin ei viitata moduulissa kokonaan. Tämän seurauksena se voidaan poistaa lopullisessa paketissa, jos sitä ei koskaan käytetä muissa moduuleissa.

Yllä oleva esimerkki on erittäin typerä, koska et tuo jotain mitä et tarvitse, ellet unohda poistaa niitä. Nykyaikaiset muokkaus- ja nukkaustyökalut muistuttavat sinua käyttämättömien tuontien poistamisesta. Tarvitsemme siis tehokkaamman ratkaisun.

Motivaatio

Yllä oleva numero havainnollistaa, että Webpack-puiden ravistamismekanismilla on vielä parantamisen varaa. Voimme selvittää vietyjen ja tuotujen muuttujien väliset suhteet moduulien välillä.

Jos jokin toinen moduuli ei tuota vietyä muuttujaa, se poistetaan yhdessä sen "lasten" kanssa (muut muuttujat, joihin vain se viittaa).

Kuva yllä olevasta numerosta

Merkintä ei tuota toimintoa2, toiminto2 ja koko ulkoinen2 voidaan poistaa. Valitettavasti Webpackin edellinen mekanismi ei pystynyt tarttumaan tällaiseen tapaukseen ennen tämän uuden laajennuksen käyttöönottoa.

toteutettavuus

Ajattele verkkopaketin roolia: se vie läpi kaikkien moduulien käyrän tulosta lähtien ja niputtaa ne yhteen. Samanaikaisesti verkkopakka tietää, mitä vientiä käytetään. Entä kaikkien laajuuksien läpikäyminen ja niputtaminen laajuudet yhteen? Tällä tavoin se voi poistaa käyttämättömät laajuudet ja moduulit. Itse asiassa voimme pitää laajuutta kuvaajana solmuna.

Yllä olevassa koodissa deepEqual liittyy fun5: een, sama on fun6: een. Jos jokin toinen moduuli ei tuota fun6: ta, tuotu funktio sama eliminoituu.

Mikä on soveltamisala?

Tietokoneohjelmoinnissa nimen sitomisen laajuus - nimen yhdistäminen kokonaisuuteen, kuten muuttujaan, on tietokoneohjelman alue, jolla sidonta on voimassa: jossa nimeä voidaan käyttää viitaten kokonaisuuteen. Tällaiseen alueeseen viitataan laajuuslohkona. Ohjelman muissa osissa nimi voi viitata toiseen kokonaisuuteen (sillä voi olla erilainen sidonta) tai ei mihinkään (se voi olla sitoutumaton). - Wikipedia

Missä tunnet laajuuden koodattaessa, se on jotain koodin lohkoa. Mutta se ei ole aivan vastaava. Tässä on tyyppejä ECMAScriptin laajuuksista:

ES6-moduulilla moduulin laajuutta pidetään juurilaajuisena. Moduulin sisällä vain luokan ja funktion laajuudet voidaan viedä, ne ovat moduulin laajuisia lapsia. Joten kaikkia laajuuksia ei pidetä kuvaajana solmuna.

Kuinka tämä laajennus toimii

Tämä laajennus sisältää laajuusanalysaattorin, joka voi poimia kaikki piirit moduuleista. Analysaattorin lähtöä käytetään sitten muuttujien referenssien selvittämiseen moduulissa.

Jotkut laajuuksista voidaan sitoa muuttujiin, kuten luokka ja funktio. Nämä viedyt laajuudet ovat atomi kuljettamista varten.

Tämä laajennus analysoi tuonnin ja viennin välisiä suhteita.

Kun verkkopakkaus antaa tietoja siitä, mitä vientiä käytetään, tämä laajennus tuottaa tuonnin, joka voidaan poistaa.

Toteutuksen yksityiskohdat

Jos olen nähnyt kauemmas, se on vain seisomalla jättiläisten harteilla. - Isaac Newton

Tarvitsemme laajuusanalyysin löytääksemme referenssit muuttujien välillä. Olemassa oleva työkalu, kuten https://github.com/estools/escope, voisi auttaa.

Tämä laajuusanalyysi perustuu AST: iin. Laajennus kiinnittää verkkopaketin hankkimaan AST-moduuleja ja analysoimaan niitä.

Sitten analysaattori selvittää, että kaikki laajuudet kuuluvat moduulin laajuuteen (juurilaajuus) ja tuonnin viitetiedot. Jos tiedämme, mitä laajuuksia muut moduulit käyttävät, analysaattori voi kulkea kaikkien ala-alueiden läpi ja merkitä kaikki muuttujat muista moduuleista. Tuontia, jolla ei ole tunnistetta, voidaan pitää käyttämättömänä.

Reunalaukut

Parantaminen on muutosta; olla täydellinen on muuttaa usein. - Churchill

JavaScript-analyysiin liittyy monia reunatapauksia, joista jotkut on lueteltu alla:

Tässä on yksinkertainen kokeilu:

https://vincentdchan.github.io/webpack-deep-scope-demo/

Paikalliset referenssit moduulin laajuuden mukaan

Jos laajuuteen tai tuotuun muuttujaan viitataan moduulin laajuudessa, sitä ei poisteta.

Määritä toiminto muuttujalle

Tietovirta-analyysin puutteen vuoksi muuttujan kirjoittamiseen liittyvät toimenpiteet (kuten uudelleenmääritys) saisivat analyysin ohittamaan tämän muuttujan. Siksi isNullia ei poisteta yllä olevassa esimerkissä.

Jos funktiolauseke annetaan kerran muuttujan ilmoittamisen yhteydessä, funktiota pidetään itsenäisenä laajuutena, analyysi toimii.

Puhtaan funktion kutsu call

Jos nimettömä toiminto on kääritty funktiokutsuun, analysaattori ei pidä sitä itsenäisenä laajuutena, koska funktion kutsulla voi olla sivuvaikutuksia. Mutta jos funktion kutsu kutsutaan puhtaana, analysaattori voi pitää sitä laajuusrakenteen kaltaisena. Siksi, jos allPassia ei käytetä, kaikki muuttujat poistuvat.

Käytännön neuvoja

Tätä laajennusta varten on useita käytännön neuvoja:

ES6-moduuli vaaditaan

Itse asiassa analyysi perustuu ES6-moduuliin, jota kutsutaan tuonti / vienti-syntaksiksi. Se ei voi toimia muissa moduulijärjestelmissä, kuten CommonJS / AMD ... Siksi projektin on käytettävä ES6-moduulia. Käytä esimerkiksi lodash-es-koneita lodash-asemesta. Muutoin keskity muihin kuin babel-loader, TypeScript jne. Määrityksiin. Estä heitä siirtämästä koodiasi ES5-tyyliin, mikä voi johtaa analyysiin.

Käytä puhdasta funktiokutsua PURE-merkinnällä

Tämä laajennus ei voi päätellä, sisältääkö funktio sivuvaikutuksia. Joten / * @ __ PURE __ * / merkintä vaaditaan joihinkin vientitoimintopuheluihin, jotka Uglify ensin ottaa käyttöön. Voit käyttää joitain babel-laajennuksia lisätäksesi ne automaattisesti. Ja huomaa, että älä anna toisen kääntäjän, kuten babel tai ts-loader, poistaa kommentteja.

Yhteenveto

Tämän liitännäisen avulla verkkopakkaus parantaa puiden ravistamista. Se auttaa poistamaan kuolleen koodin ja pienentämään nipun kokoa. Toisaalta se vaatii ohjelmoijia kirjoittamaan puhtaan ja asianmukaisen koodin, koska edes paras kääntäjä ei voi optimoida pahinta koodia. Nyt meillä on parempi verkkopakkaus, onko sinulla jotain mahtavaa koodia käännettäväksi? Ole hyvä ja lähetä ennen ja jälkeen käyttökertomuksia, jotta ymmärrämme paremmin, kuinka tehokas tämä on projektiisi / kehykseen!