VRath – z Reactem w parze cz. 1

Projekt rozkręca się dość powoli, ale małymi kroczkami i dojdę do mety. Dzisiaj zajmę się dalszą konfiguracją webpacka i spróbuję połączyć w parze Reacta i A-Frame’a. Do dzieła.

W ostatnim poście skończyłem na podłączaniu babel-loadera aby transformować kod napisany w standardzie ES6 do ES5. Nie określiłem jednak wspieranych przez projekt przeglądarek. Na początku przyszło mi na myśl aby wybrać jedynie te przeglądarki, które wspierają technologię WebVR, ale patrząc na wsparcie na caniuse.com (z chwilą pisania obsługę posiadał jedynie Edge, a Chrome i Firefox jedynie z pomocą odpowiednich flag) stwierdziłem, że to nie jest najlepszy pomysł. Na szczęście A-Frame wspiera wszystkie przeglądarki, które potrafią sobie poradzić z WebGL’em, a żeby uzyskać efekt VR wykorzystywany jest polyfill.



Wróćmy do mojej konfiguracji webpacka:

const path = require("path");

module.exports = {
	entry: "./src/assets/js/app.js",
	output: {
		filename: "bundle.js",
		path: path.resolve(__dirname, "build")
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: [/node_modules/],
				use: [{
					loader: "babel-loader",
					options: {
						presets: ["env"] 
					}
				}]
			}
		]
	}
};

Rozszerzę teraz pole presets o dodatkową logikę związaną z obsługą konkretnych przeglądarek. Skupię się na dwóch ostatnich wersjach, IE 11 i Androidzie powyżej 4.4, tak aby mieć jak największą ilość urządzeń ze wsparciem dla WebGL:

presets: [
	["env", {
		"targets": {
			"browsers": ["last 2 versions", "ie >= 11", "Android >= 5"]
		}
	}],
	["react"]
]

Przy okazji definiowania wspieranych przeglądarek dodałem także dodatkowy preset react, ponieważ i tak zamierzam go użyć. Oczywiście wcześniej należało go dodać do projektu:

yarn add babel-preset-react --dev

Webpack i pluginy

Ostatnim filarem i zarazem mocną stroną webpacka są pluginy. Pluginy rozszerzają możliwości webpacka i mogą wykonywać akcje nawet na poziomie „kompilacji” paczki. Cały ekosystem pluginów jest bardzo rozbudowany, a samo użycie jest niezwykle proste. Znaczna większość pluginów jest dostępnych do pobrania z repozytoriów NPM’a, ale część przychodzi razem z webpackiem i właśnie jednego z takich pluginów teraz użyję do „zaśmiecenia” wynikowego kodu w paczce:

const path = require("path");
const webpack = require("webpack");

module.exports = {
	entry: path.resolve(__dirname, "src/assets/js/app.js"),
	output: {
		filename: "bundle.js",
		path: path.resolve(__dirname, "build/js")
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: [/node_modules/],
				use: [{
					loader: "babel-loader",
					options: {
						presets: [
							["env", {
								"targets": {
									"browsers": ["last 2 versions", "ie >= 11", "Android >= 5"]
								}
							}],
							["react"]
						] 
					}
				}]
			}
		]
	},
    plugins: [
        new webpack.optimize.UglifyJsPlugin()
    ]
};

Do konfiguracji VRatha dodałem klucz plugins, któremu należy przekazać tablicę pluginów (przy okazji poprawiłem wyglądowo także punkt wejścia z użyciem modułu path). Do „zaśmiecenia” wynikowego kodu Webpack posiada wbudowany plugin UglifyJS i właśnie z niego skorzystałem. Wynikowa paczka bundle.js jest zminifikowana i tym samym waży dużo mniej. Pora przejść do innych zabawek.

Instalacja Reacta

O tym, że A-Frame jesteśmy w stanie połączyć z innymi bibliotekami operującymi na drzewie DOM już wspominałem, dlatego nie ma co czekać, trzeba to sprawdzić w praktyce. Mój projekt nie posiada jeszcze pliku index.html więc zacznę od niego:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="format-detection" content="telephone=no">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-title" content="VRath - VR shooting range">
        <meta name="apple-touch-fullscreen" content="yes">
        <meta name="keywords" content="vr, vrath, webvr, webgl, a-frame, react">
        <meta name="description" content="Simple VR shooting range">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        <title>VRath - VR shooting range</title>
    </head>
    <body>
        <div id="vrath-scene"></div>
        <script type="text/javascript" src="build/js/bundle.js"></script>
    </body>
</html>

Nie ma w tym przypadku żadnej czarnej magii, ot standardowy index.html z kilkoma znacznikami <meta> skierowanymi dla mobilek. Umieściłem go w głównym drzewie projektu, na poziomie pliku webpack.config.js. Punktem zaczepienia dla React będzie element o identyfikatorze vrath-scene, natomiast wynikowa paczka z webpacka zostanie przemieszczona do podkatalogu js. Czas na instalację React.js:

yarn add --dev react react-dom

Po instalacji chciałbym sprawdzić czy wszystko kompiluje się poprawnie. Stworzę więc banalny komponent z użyciem JSX aby przetestować konfigurację środowiska. Pliczek module.js, który wcześniej eksportował ciąg znaków, tym razem będzie eksportował tzw. stateless function, czyli bezstanowy, bardzo prosty komponent React:

import React from "react";

export default () => <p>Hello World!</p>;

Natomiast plik app.js zaimportuje powyższy komponent i zamontuje go w drzewie DOM, do elementu ze sceną:

import React from "react";
import ReactDOM from "react-dom";
import module from "./module.js";

ReactDOM.render(module(), document.getElementById("vrath-scene"));

Po wejściu w index.html w przeglądarce wyświetla się „Hello World!”, tak więc konfiguracja dla Reacta jest poprawna.

CDN…

VRath – z Reactem w parze cz. 2