Transpiler / compiler Babel
Najważniejszą ideą w technologii react jest możliwość tworzenia własnych znaczników (Tags) rozszerzających HTML. Osiągnięto to poprzez przetwarzanie takiego rozszerzonego kodu w JavaScript. Stosuje się w tym celu "transpiler" Babel, który został stworzony aby tłumaczyć standard JavaScript ES6 na wcześniejsze standardy (ES5), akceptowane przez przeglądarki. Ponieważ Babel obsługuje rozszerzenia (wtyczki) - nic prostszego, jak dodać wtyczki obsługujące rozszerzenia React.
Babel nie jest częścią projektu React, ale jest przez niego wykorzystywany.
Przykład:
Plik: helloworld.jsx
class HelloWorld extends React.Component {
render() {
return <h1>Hello World</h1>
}
}
ReactDOM.render(
<HelloWorld />
, document.getElementById('example00')
);
Definiuje on nowy znacznik HelloWorld. Każdy taki znacznik odpowiada obiektowi zbudowanemu na bazie klasy React.Component.
Funkcja render() zwraca (return) rozszerzony kod html (musi być zawarty w obrębie jednego znacznika - tu h1).
Oczywiście można wykorzystywać wcześniej zdefiniowane znaczniki.
Funkcja ReactDOM.render wstawia wygenerowany znacznik <HelloWorld />
do kodu na stronie html.
Wykorzystany w tym celu zostanjeie element example00.
Przykład strony z takim elementem (index.html):
<!DOCTYPE html>
<html>
<head>
<script src="node_modules/react/dist/react.js"></script>
<script src="node_modules/react-dom/dist/react-dom.js"></script>
</head>
<body>
<div id="example00"></div>
<script src="helloworld.js"></script>
</body>
</html>
Trzeba zwrócić uwagę, że do strony dołączono plik helloworld.js, a nie helloworld.jsx.
Czyli plik po przetworzeniu kompilatorem babel.
Jak to się robi?
1) Najpierw musimy zainstalować kompilator i odpowiednie biblioteki rReacta.
Działają one w środowisku NodeJs.
# pusty package.json:
npm init
# react:
npm install --save-dev react
npm install --save-dev react-dom
# kompilator babel:
npm install --save-dev babel-cli babel-preset-es2015
2) Teraz musimy zainstalować wtyczki do kompilatora [Uwaga! Można ten zapis skrócić do npm i ….]:
# + pluginy:
npm install babel-plugin-transform-react-jsx
3) Tworzymy plik .babelrc
Zawiera on informację co ma być tłumaczone:
{ "presets" : [["es2015", "react"]] }
4) Uruchamiamy kompilator:
# windows:
.\node_modules\.bin\babel --plugins transform-react-jsx index.jsx > helloworld.js
# linux:
./node_modules/.bin/babel --plugins transform-react-jsx helloworld.jsx > helloworld.js
5) Testujemy otwierając w przeglądarce plik index.html
Babel możemy dołączyć w postaci biblioteki do naszej strony – wtedy można na stronie używać JSX.
Bibliotekę możemy pobrać na przykład ze stron CDN.
https://cdnjs.com/libraries/babel-core
Przykład:
<!DOCTYPE html>
<html>
<head>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
Babel i Gulp
Gulp to popularny program do automatyzacji praz z projektami internetowymi. Wykorzystuje on ideę potoków (pipe). Kolejne etapy (elementy potoku) przetwarzają otrzymane dane i przekazuj ą dalej (tak jak w potokach systeów operacyjnych).
Z potoków implementuje się funkcję przetwarzania danych, używając języka JavaScript (działa to w środowisku NodeJS). Implementację tą zapisujemy w pliku gulpfile.js
.
Przykład:
const { src, dest, parallel } = require('gulp');
const babel = require('gulp-babel');
const browserify = require('gulp-browserify');
const babelOptions = {
presets: [
"@babel/preset-env",
"@babel/preset-react"
],
plugins: [
"@babel/plugin-transform-object-assign",
"@babel/plugin-transform-react-jsx"
]
}
function build() {
return src('./src/index.jsx')
.pipe(babel(babelOptions))
.pipe(browserify({
insertGlobals : true,
debug : true
}))
.pipe(dest('./public'));
}
exports.build=build;
W tym przykładzie mamy potok inicjowany przez odczyt pliku jsx (src). Następnie wywołujemy babel (tłumaczenie z JSX na JS) i browserify (ze środowiska NodeJS na środowisko przeglądarki). Na końcu dokonujemy zapisu do katalogu public (dest).
Aby to zadziałało, musimy zainstalować użyte paczki. Przykładowa konfiguracja aplikacji (fragment package.json):
"scripts": {
"build": "gulp build"
},
"dependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@babel/plugin-transform-object-assign": "^7.2.0",
"@babel/plugin-transform-react-jsx": "^7.3.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-browserify": "^0.5.1"
},
Poza zdefiniowanymi paczkami, mamy tu definicję skryptu build.
Aby zbudować aplikację wykonujemy:
yarn install
yarn build
webpack
Użyty w poprzednim przykładzie pakiet browserify umożliwia uruchamianie programów NodeJS w przeglądarce poprzez dodanie przeglądarkowych odpowiedników brakujących funkcji. Nieco inną filozofię zastosowano w pakiecie webpack [http://blog.namangoel.com/browserify-vs-webpack-js-drama\]. Te identyfikatory zastosowane w NodeJS mogą po przetworzeniu przez webpack mieć odmienne znaczenie. Dzięki temu aplikacje są zdecydowanie mniejsze. Dla prostego komponentu React przy użyciu webpack uzyskujemy nawet 4 razy mniejszy kod niż po zastosowaniu browserify i uglify (kompresja).
Powyższy przykłąd z wykorzystaniem webpack będzie wyglądał następująco:
const { src, dest, parallel } = require('gulp');
const babel = require('gulp-babel');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
// zakładamy pomocniczy katalog tmp na wynik tłumaczenia babel
const webpackConfig = { // minimalna konfiguracja
entry: './tmp/index.js',
output: {
filename: 'index.js'
},
mode: 'production' // lub: mode: 'development'
};
const babelOptions = {
presets: [
"@babel/preset-env",
"@babel/preset-react"
],
plugins: [
"@babel/plugin-transform-object-assign",
"@babel/plugin-transform-react-jsx"
]
}
function build() {
return src('./src/index.jsx')
.pipe(babel(babelOptions)).pipe(dest('./tmp'))
.pipe(webpackStream(webpackConfig), webpack)
.pipe(dest('./public'))
}
exports.build=build;
react-scripts
Skrypt react-scripts
jest częścią create-react-app
- choć można go instalować niezależnie.
Używając create-react-app
możesz zapomnieć o webpack, gulp etc.... ;).
Minimalna konfiguracja projektu ztym skryptem:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
},
"dependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0"
},
"devDependencies": {
"react-scripts": "^3.1.1",
"yarn": "^1.16.0"
}
Przy powyższej konfiguracji wystarczy wykonać:
yarn install
yarn build
Na podstawie dwóch plików: src/index.jsx
oraz public/index.html
, zostanie w katalogu build utworzona strona statyczna wykorzystjąca komponenty React. Najprostszy przykład:
src/index.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<div>Hello World</div>, document.getElementById('root'));
public/index.html
<html>
<body>
<div id="root"></div>
</body>
</html>