Atskleiskite JavaScript kodo transformavimo galią su šiuo detaliu Babel papildinių kūrimo vadovu. Išmokite pritaikyti JavaScript sintaksę, optimizuoti kodą ir kurti galingus įrankius programuotojams visame pasaulyje.
JavaScript kodo transformavimas: išsamus Babel papildinių kūrimo vadovas
JavaScript yra neįtikėtinai universali kalba, kuria paremta didelė dalis interneto. Tačiau nuolatinė JavaScript evoliucija, dažnai pasipildanti naujomis funkcijomis ir sintakse, kelia iššūkių programuotojams. Būtent čia į pagalbą ateina kodo transformavimo įrankiai, ypač „Babel“. „Babel“ leidžia programuotojams naudoti naujausias JavaScript funkcijas net ir tose aplinkose, kurios jų dar nepalaiko. Iš esmės, „Babel“ konvertuoja modernų JavaScript kodą į versiją, kurią gali suprasti naršyklės ir kitos vykdymo aplinkos. Supratimas, kaip kurti pasirinktinius „Babel“ papildinius, suteikia programuotojams galią išplėsti šį funkcionalumą, optimizuoti kodą, užtikrinti kodavimo standartų laikymąsi ir netgi kurti visiškai naujus JavaScript dialektus. Šis vadovas pateikia išsamią „Babel“ papildinių kūrimo apžvalgą, tinkančią visų lygių programuotojams.
Kodėl „Babel“? Kodėl papildiniai?
„Babel“ yra JavaScript kompiliatorius, kuris transformuoja modernų JavaScript kodą (ESNext) į atgal suderinamą JavaScript versiją (ES5), kuri gali veikti visose naršyklėse. Tai yra esminis įrankis, užtikrinantis kodo suderinamumą įvairiose naršyklėse ir aplinkose. Tačiau „Babel“ galia neapsiriboja paprasta transpiliacija; jo papildinių sistema yra pagrindinė funkcija.
- Suderinamumas: Naudokite pažangiausias JavaScript funkcijas jau šiandien.
- Kodo optimizavimas: Pagerinkite kodo našumą ir dydį.
- Kodo stiliaus užtikrinimas: Užtikrinkite nuoseklias kodavimo praktikas komandose.
- Individuali sintaksė: Eksperimentuokite ir įgyvendinkite savo JavaScript sintaksę.
„Babel“ papildiniai leidžia programuotojams pritaikyti kodo transformavimo procesą. Jie veikia su abstrakčiu sintaksės medžiu (AST), struktūrizuotu JavaScript kodo vaizdavimu. Šis požiūris leidžia smulkmeniškai kontroliuoti, kaip kodas yra transformuojamas.
Abstraktus sintaksės medis (AST) – kas tai?
AST yra į medį panašus jūsų JavaScript kodo vaizdavimas. Jis suskaido jūsų kodą į mažesnes, lengviau valdomas dalis, leidžiančias „Babel“ (ir jūsų papildiniams) analizuoti ir manipuliuoti kodo struktūra. AST leidžia „Babel“ identifikuoti ir transformuoti įvairias kalbos konstrukcijas, tokias kaip kintamieji, funkcijos, ciklai ir kt.
Įrankiai, tokie kaip AST Explorer, yra neįkainojami norint suprasti, kaip kodas yra pavaizduotas AST. Galite įklijuoti JavaScript kodą į įrankį ir pamatyti atitinkamą AST struktūrą. Tai yra kritiškai svarbu kuriant papildinius, nes jums reikės naršyti ir modifikuoti šią struktūrą.
Pavyzdžiui, apsvarstykite šį JavaScript kodą:
const message = 'Hello, World!';
console.log(message);
Jo AST vaizdavimas galėtų atrodyti maždaug taip (supaprastintai):
Program {
body: [
VariableDeclaration {
kind: 'const',
declarations: [
VariableDeclarator {
id: Identifier { name: 'message' },
init: Literal { value: 'Hello, World!' }
}
]
},
ExpressionStatement {
expression: CallExpression {
callee: MemberExpression {
object: Identifier { name: 'console' },
property: Identifier { name: 'log' }
},
arguments: [
Identifier { name: 'message' }
]
}
}
]
}
Kiekvienas mazgas AST vaizduoja konkretų kodo elementą (pvz., `VariableDeclaration`, `Identifier`, `Literal`). Jūsų papildinys naudos šią informaciją kodo naršymui ir modifikavimui.
„Babel“ papildinių kūrimo aplinkos paruošimas
Norėdami pradėti, turėsite paruošti savo kūrimo aplinką. Tai apima Node.js ir npm (arba yarn) įdiegimą. Tada galite sukurti naują projektą ir įdiegti reikiamas priklausomybes.
- Sukurkite projekto aplanką:
mkdir babel-plugin-example
cd babel-plugin-example
- Inicijuokite projektą:
npm init -y
- Įdiekite „Babel“ branduolį ir priklausomybes:
npm install --save-dev @babel/core @babel/types
@babel/core: Pagrindinė „Babel“ biblioteka.@babel/types: Įrankis AST mazgams kurti.
Taip pat galite įdiegti papildinius, tokius kaip `@babel/preset-env`, testavimui. Šis rinkinys padeda transformuoti ESNext kodą į ES5, bet nėra privalomas pagrindiniam papildinių kūrimui.
npm install --save-dev @babel/preset-env
Pirmojo „Babel“ papildinio kūrimas: paprastas pavyzdys
Sukurkime pagrindinį papildinį, kuris prideda komentarą kiekvieno failo viršuje. Šis pavyzdys parodo esminę „Babel“ papildinio struktūrą.
- Sukurkite papildinio failą (pvz.,
my-babel-plugin.js):
// my-babel-plugin.js
module.exports = function(babel) {
const { types: t } = babel;
return {
name: 'add-comment',
visitor: {
Program(path) {
path.unshiftContainer('body', t.addComment('leading', path.node, 'This code was transformed by my Babel plugin'));
}
}
};
};
module.exports: Ši funkcija gauna „Babel“ egzempliorių kaip argumentą.t(@babel/types): Suteikia metodus AST mazgams kurti.name: Papildinio pavadinimas (derinimui ir identifikavimui).visitor: Objektas, turintis lankytojo funkcijas. Kiekvienas raktas atitinka AST mazgo tipą (pvz., `Program`).Program(path): Ši lankytojo funkcija paleidžiama, kai „Babel“ aptinka `Program` mazgą (AST šaknį).path.unshiftContainer: Įterpia AST mazgą į konteinerio pradžią (šiuo atveju – į `Program` `body`).t.addComment: Sukuria pradinį komentaro mazgą.
- Išbandykite papildinį: Sukurkite bandomąjį failą (pvz.,
index.js):
// index.js
const greeting = 'Hello, Babel!';
console.log(greeting);
- Konfigūruokite „Babel“ (pvz., naudojant
.babelrc.jsfailą):
// .babelrc.js
module.exports = {
plugins: ['./my-babel-plugin.js']
};
- Paleiskite „Babel“, kad transformuotumėte kodą:
npx babel index.js -o output.js
Ši komanda apdoros `index.js` su jūsų papildiniu ir išves transformuotą kodą į `output.js`.
- Peržiūrėkite išvestį (
output.js):
// This code was transformed by my Babel plugin
const greeting = 'Hello, Babel!';
console.log(greeting);
Turėtumėte pamatyti komentarą, pridėtą transformuoto kodo pradžioje.
Giliau į papildinio struktūrą
„Babel“ papildiniai naudoja lankytojo šabloną (visitor pattern) AST naršymui ir kodo transformavimui. Panagrinėkime pagrindinius papildinio komponentus detaliau.
module.exports(babel): Pagrindinė funkcija, eksportuojanti papildinį. Ji gauna „Babel“ egzempliorių, suteikiantį prieigą prie `types` (t) įrankio ir kitų „Babel“ funkcijų.name: Aprašomasis jūsų papildinio pavadinimas. Tai padeda derinti ir identifikuoti papildinį „Babel“ konfigūracijoje.visitor: Jūsų papildinio šerdis. Tai objektas, kuriame yra lankytojo metodai skirtingiems AST mazgų tipams.- Lankytojo metodai: Kiekvienas metodas `visitor` objekte atitinka AST mazgo tipą (pvz., `Program`, `Identifier`, `CallExpression`). Kai „Babel“ aptinka tokio tipo mazgą, jis iškviečia atitinkamą lankytojo metodą. Lankytojo metodas gauna `path` objektą, kuris atspindi dabartinį mazgą ir suteikia metodus AST naršymui bei manipuliavimui.
pathobjektas: `path` objektas yra esminis kuriant papildinius. Jis suteikia daugybę metodų AST naršymui ir transformavimui:
path.node: Dabartinis AST mazgas.path.parent: Dabartinio mazgo pirminis mazgas.path.traverse(visitor): Rekursyviai naršyti dabartinio mazgo antrinius mazgus.path.replaceWith(newNode): Pakeisti dabartinį mazgą nauju mazgu.path.remove(): Pašalinti dabartinį mazgą.path.insertBefore(newNode): Įterpti naują mazgą prieš dabartinį mazgą.path.insertAfter(newNode): Įterpti naują mazgą po dabartinio mazgo.path.findParent(callback): Randa artimiausią pirminį mazgą, atitinkantį sąlygą.path.getSibling(key): Gauna gretutinį mazgą.
Darbas su @babel/types
@babel/types modulis suteikia įrankius AST mazgams kurti ir manipuliuoti. Tai yra labai svarbu kuriant naują kodą ir modifikuojant esamas kodo struktūras jūsų papildinyje. Šio modulio funkcijos atitinka skirtingus AST mazgų tipus.
Štai keli pavyzdžiai:
t.identifier(name): Sukuria identifikatoriaus (Identifier) mazgą (pvz., kintamojo pavadinimą).t.stringLiteral(value): Sukuria eilutės literalo (StringLiteral) mazgą.t.numericLiteral(value): Sukuria skaitinio literalo (NumericLiteral) mazgą.t.callExpression(callee, arguments): Sukuria iškvietimo išraiškos (CallExpression) mazgą (pvz., funkcijos iškvietimą).t.memberExpression(object, property): Sukuria nario išraiškos (MemberExpression) mazgą (pvz., `object.property`).t.arrowFunctionExpression(params, body): Sukuria rodyklinės funkcijos išraiškos (ArrowFunctionExpression) mazgą.
Pavyzdys: naujos kintamojo deklaracijos sukūrimas:
const newDeclaration = t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('myNewVariable'),
t.stringLiteral('Hello, world!')
)
]);
Praktiniai papildinių pavyzdžiai
Panagrinėkime keletą praktinių „Babel“ papildinių pavyzdžių, kad pademonstruotume jų universalumą. Šie pavyzdžiai parodo dažniausiai pasitaikančius naudojimo atvejus ir suteikia atspirties taškus jūsų pačių papildinių kūrimui.
1. „Console.log“ pašalinimas
Šis papildinys pašalina visus `console.log` pareiškimus iš jūsų kodo. Tai gali būti itin naudinga kuriant produkcinę versiją, kad netyčia nebūtų atskleista derinimo informacija.
// remove-console-logs.js
module.exports = function(babel) {
const { types: t } = babel;
return {
name: 'remove-console-logs',
visitor: {
CallExpression(path) {
if (path.node.callee.type === 'MemberExpression' &&
path.node.callee.object.name === 'console' &&
path.node.callee.property.name === 'log') {
path.remove();
}
}
}
};
};
Šiame papildinyje `CallExpression` lankytojas patikrina, ar funkcijos iškvietimas yra `console.log` pareiškimas. Jei taip, `path.remove()` metodas pašalina visą mazgą.
2. Šablono literalų transformavimas į sujungimą
Šis papildinys konvertuoja šablono literalus (``) į eilučių sujungimą naudojant `+` operatorių. Tai naudinga senesnėms JavaScript aplinkoms, kurios natūraliai nepalaiko šablono literalų (nors „Babel“ paprastai tai sutvarko automatiškai).
// template-literal-to-concat.js
module.exports = function(babel) {
const { types: t } = babel;
return {
name: 'template-literal-to-concat',
visitor: {
TemplateLiteral(path) {
const expressions = path.node.expressions;
const quasis = path.node.quasis;
let result = t.stringLiteral(quasis[0].value.raw);
for (let i = 0; i < expressions.length; i++) {
result = t.binaryExpression(
'+',
result,
expressions[i]
);
result = t.binaryExpression(
'+',
result,
t.stringLiteral(quasis[i + 1].value.raw)
);
}
path.replaceWith(result);
}
}
};
};
Šis papildinys apdoroja `TemplateLiteral` mazgus. Jis iteruoja per išraiškas ir kvazius (eilučių dalis) ir sukonstruoja lygiavertį sujungimą naudojant `t.binaryExpression`.
3. Autorių teisių pranešimų pridėjimas
Šis papildinys prideda autorių teisių pranešimą kiekvieno failo pradžioje, demonstruodamas, kaip įterpti kodą konkrečiose vietose.
// add-copyright-notice.js
module.exports = function(babel) {
const { types: t } = babel;
return {
name: 'add-copyright-notice',
visitor: {
Program(path) {
path.unshiftContainer('body', t.commentBlock(' Copyright (c) 2024 Your Company '));
}
}
};
};
Šis pavyzdys naudoja `Program` lankytoją, kad pridėtų kelių eilučių komentaro bloką failo pradžioje.
Pažangios papildinių kūrimo technikos
Be pagrindų, yra ir pažangesnių technikų, kurios gali pagerinti jūsų „Babel“ papildinių kūrimą.
- Papildinio parinktys: Leiskite vartotojams konfigūruoti jūsų papildinį naudojant parinktis.
- Kontekstas: Pasiekite „Babel“ kontekstą, kad valdytumėte būseną ar atliktumėte asinchronines operacijas.
- Šaltinio žemėlapiai (Source Maps): Generuokite šaltinio žemėlapius, kad susietumėte transformuotą kodą su originaliu šaltiniu.
- Klaidų apdorojimas: Apdorokite klaidas sklandžiai, kad pateiktumėte naudingą grįžtamąjį ryšį vartotojams.
1. Papildinio parinktys
Papildinio parinktys leidžia vartotojams pritaikyti jūsų papildinio elgseną. Jas apibrėžiate pagrindinėje papildinio funkcijoje.
// plugin-with-options.js
module.exports = function(babel, options) {
const { types: t } = babel;
const { authorName = 'Unknown Author' } = options;
return {
name: 'plugin-with-options',
visitor: {
Program(path) {
path.unshiftContainer('body', t.commentBlock(` Copyright (c) 2024 ${authorName} `));
}
}
};
};
Šiame pavyzdyje papildinys priima `authorName` parinktį su numatytąja reikšme „Unknown Author“. Vartotojai konfigūruoja papildinį per „Babel“ konfigūracijos failą (.babelrc.js arba babel.config.js).
// .babelrc.js
module.exports = {
plugins: [[
'./plugin-with-options.js',
{ authorName: 'John Doe' }
]]
};
2. Kontekstas
„Babel“ suteikia konteksto objektą, kuris leidžia valdyti būseną ir atlikti operacijas, kurios išlieka per kelias failų transformacijas. Tai naudinga užduotims, tokioms kaip kaupimas talpykloje (caching) ar statistikos rinkimas.
Prieiga prie konteksto gaunama per „Babel“ egzempliorių, paprastai perduodant parinktis į papildinio funkciją. `file` objektas turi kontekstą, būdingą šiuo metu transformuojamam failui.
// plugin-with-context.js
module.exports = function(babel, options, dirname) {
const { types: t } = babel;
let fileCount = 0;
return {
name: 'plugin-with-context',
pre(file) {
// Runs once per file
fileCount++;
console.log(`Transforming file: ${file.opts.filename}`);
},
visitor: {
Program(path) {
path.unshiftContainer('body', t.commentBlock(` Transformed by plugin (File Count: ${fileCount})`));
}
},
post(file) {
// Runs after each file
console.log(`Finished transforming: ${file.opts.filename}`);
}
};
};
Aukščiau pateiktas pavyzdys demonstruoja `pre` ir `post` kablius (hooks). Šie kabliai leidžia atlikti paruošimo ir valymo užduotis prieš ir po failo apdorojimo. Failų skaičius didinamas `pre`. Pastaba: trečiasis argumentas, `dirname`, nurodo aplanką, kuriame yra konfigūracijos failas, o tai naudinga atliekant operacijas su failais.
3. Šaltinio žemėlapiai (Source Maps)
Šaltinio žemėlapiai yra būtini derinant transformuotą kodą. Jie leidžia susieti transformuotą kodą su originaliu šaltinio kodu, todėl derinimas tampa daug lengvesnis. „Babel“ automatiškai tvarko šaltinio žemėlapius, tačiau gali tekti juos konfigūruoti priklausomai nuo jūsų kūrimo proceso.
Įsitikinkite, kad šaltinio žemėlapiai yra įjungti jūsų „Babel“ konfigūracijoje (dažniausiai jie būna įjungti pagal nutylėjimą). Naudojant paketuotojus, tokius kaip Webpack ar Parcel, jie paprastai pasirūpins šaltinio žemėlapių generavimu ir integravimu.
4. Klaidų apdorojimas
Patikimas klaidų apdorojimas yra labai svarbus. Pateikite prasmingus klaidų pranešimus, kad padėtumėte vartotojams suprasti ir ištaisyti problemas. „Babel“ suteikia metodus klaidoms pranešti.
// plugin-with-error-handling.js
module.exports = function(babel) {
const { types: t } = babel;
return {
name: 'plugin-with-error-handling',
visitor: {
Identifier(path) {
if (path.node.name === 'invalidVariable') {
path.traverse({})
path.buildCodeFrameError('Invalid variable name: invalidVariable').loc.column;
//throw path.buildCodeFrameError('Invalid variable name: invalidVariable');
}
}
}
};
};
Naudokite `path.buildCodeFrameError()`, kad sukurtumėte klaidų pranešimus, kuriuose būtų nurodyta klaidos vieta šaltinio kode, todėl vartotojui bus lengviau ją rasti ir ištaisyti. Išmetus klaidą, sustabdomas transformavimo procesas ir klaida parodoma konsolėje.
„Babel“ papildinių testavimas
Kruopštus testavimas yra būtinas norint užtikrinti, kad jūsų papildiniai veiktų teisingai ir neįvestų netikėtos elgsenos. Galite naudoti vienetų testus (unit tests), kad patikrintumėte, ar jūsų papildinys transformuoja kodą taip, kaip tikėtasi. Apsvarstykite galimybę testuoti įvairius scenarijus, įskaitant tinkamus ir netinkamus įvesties duomenis, kad užtikrintumėte visapusišką aprėptį.
Yra keletas testavimo karkasų. Jest ir Mocha yra populiarūs pasirinkimai. „Babel“ suteikia pagalbines funkcijas papildinių testavimui. Jos dažnai apima įvesties kodo palyginimą su laukiamu išvesties kodu po transformacijos.
Pavyzdys naudojant Jest ir @babel/core:
// plugin-with-jest.test.js
const { transformSync } = require('@babel/core');
const plugin = require('./remove-console-logs');
const code = `
console.log('Hello');
const message = 'World';
console.log(message);
`;
const expected = `
const message = 'World';
`;
test('remove console.log statements', () => {
const { code: transformedCode } = transformSync(code, {
plugins: [plugin]
});
expect(transformedCode.trim()).toBe(expected.trim());
});
Šis testas naudoja `transformSync` iš `@babel/core`, kad pritaikytų papildinį bandomajai įvesties eilutei, o tada palygina transformuotą rezultatą su laukiamu išvesties rezultatu.
„Babel“ papildinių publikavimas
Sukūrę naudingą „Babel“ papildinį, galite jį publikuoti npm, kad pasidalintumėte juo su pasauliu. Publikavimas leidžia kitiems programuotojams lengvai įdiegti ir naudoti jūsų papildinį. Įsitikinkite, kad papildinys yra gerai dokumentuotas ir atitinka geriausias pakavimo bei platinimo praktikas.
- Sukurkite
package.jsonfailą: Jame pateikiama informacija apie jūsų papildinį (pavadinimas, aprašymas, versija ir kt.). Būtinai įtraukite raktinius žodžius, tokius kaip „babel-plugin“, „javascript“ ir kitus, kad pagerintumėte aptinkamumą. - Sukurkite GitHub repozitoriją: Laikykite savo papildinio kodą viešoje ar privačioje repozitorijoje. Tai yra labai svarbu versijų kontrolei, bendradarbiavimui ir būsimiems atnaujinimams.
- Prisijunkite prie npm: Naudokite `npm login` komandą.
- Publikuokite papildinį: Naudokite `npm publish` komandą iš savo projekto aplanko.
Geroji praktika ir svarstymai
- Skaitomumas ir prižiūrimumas: Rašykite švarų, gerai dokumentuotą kodą. Naudokite nuoseklų kodo stilių.
- Našumas: Atsižvelkite į savo papildinio poveikį našumui, ypač dirbant su didelėmis kodo bazėmis. Venkite nereikalingų operacijų.
- Suderinamumas: Užtikrinkite, kad jūsų papildinys būtų suderinamas su skirtingomis „Babel“ versijomis ir JavaScript aplinkomis.
- Dokumentacija: Pateikite aiškią ir išsamią dokumentaciją, įskaitant pavyzdžius ir konfigūracijos parinktis. Geras README failas yra būtinas.
- Testavimas: Rašykite išsamius testus, kad apimtumėte visas savo papildinio funkcijas ir išvengtumėte regresijų.
- Versijavimas: Laikykitės semantinio versijavimo (SemVer), kad valdytumėte savo papildinio leidimus.
- Bendruomenės indėlis: Būkite atviri bendruomenės indėliui, kuris padės pagerinti jūsų papildinį.
- Saugumas: Išvalykite ir patikrinkite bet kokius vartotojo pateiktus duomenis, kad išvengtumėte galimų saugumo pažeidžiamumų.
- Licencija: Įtraukite licenciją (pvz., MIT, Apache 2.0), kad kiti galėtų naudoti jūsų papildinį ir prisidėti prie jo kūrimo.
Išvada
„Babel“ papildinių kūrimas atveria platų pritaikymo pasaulį JavaScript programuotojams visame pasaulyje. Suprasdami AST ir turimus įrankius, galite kurti galingus įrankius, skirtus pagerinti darbo eigas, užtikrinti kodavimo standartus, optimizuoti kodą ir tyrinėti naujas JavaScript sintakses. Šiame vadove pateikti pavyzdžiai suteikia tvirtą pagrindą. Kuriant savo papildinius, nepamirškite testavimo, dokumentacijos ir gerosios praktikos. Ši kelionė nuo pradedančiojo iki eksperto yra nuolatinis procesas. Nuolatinis mokymasis ir eksperimentavimas yra raktas į „Babel“ papildinių kūrimo įgūdžių įvaldymą ir indėlį į nuolat besikeičiančią JavaScript ekosistemą. Pradėkite eksperimentuoti, tyrinėti ir kurti – jūsų indėlis neabejotinai bus naudingas programuotojams visame pasaulyje.