Kliensoldali webprogramozás

Kitekintés

Horváth Győző
Egyetemi docens
1117 Budapest, Pázmány Péter sétány 1/c., 2.408-as szoba
Tel: (1) 372-2500/8469
horvath.gyozo@inf.elte.hu

Ismétlés

Webprogramozás

  • JavaScript alapok
  • DOM
  • Eseménykezelés
  • Függvénykönyvtárak nélkül
  • Imperatív/deklaratív

Progresszív fejlesztés

  • Függvénykönyvtárak, CDN
  • jQuery
  • Imperatív DOM kezelés
  • Progresszív fejlesztés
  • Funkciók hozzáadása
  • Funkciók egységbe zárása
  • Web komponensek

React + Redux

  • Keretrendszer használata
  • Parancssori eszközök használata
    • npm, babel, webpack
  • Deklaratív megközelítés
  • Funkcionális paradigma
  • Komponensek
  • Virtuális DOM

Tesztelés

  • Egységtesztek
  • Integrációs tesztek
  • Funkcionális tesztek
  • Hatékonysági tesztek
  • Eszközök
    • Jest, Testing Library, Cypress, Puppeteer

Stílus, animációk

Stílusok

  • inline style
  • className
  • CSS-in-JS
  • CSS modulok
  • Komponens függvénykönyvtárak

Külső stíluslap

/* Button.css */
.Button {
  padding: 20px;
}
import React, { Component } from 'react';
import './Button.css'; // Tell webpack that Button.js uses these styles
class Button extends Component {
  render() {
    // You can use them as regular CSS styles
    return <div className="Button" />;
  }
}

CSS modul

/* Button.module.css */
.error {
  background-color: red;
}
/* another-stylesheet.css */
.error {
  color: red;
}
import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet
class Button extends Component {
  render() {
    // reference as a js object
    return <button className={styles.error}>Error Button</button>;
  }
}

CRA-ban alapértelmezett

CSS-in-JS

CSS-t JS állítja elő (pl. styled-components)

// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;
// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;
// Use Title and Wrapper like any other React component – except they're styled!
render(
  <Wrapper>
    <Title>
      Hello World!
    </Title>
  </Wrapper>
);

CSS-in-JS

CSS-t JS állítja elő (pl. styled-components)

// This could be react-router-dom's Link for example
const Link = ({ className, children }) => (
  <a className={className}>
    {children}
  </a>
);
const StyledLink = styled(Link)`
  color: palevioletred;
  font-weight: bold;
`;
render(
  <div>
    <Link>Unstyled, boring Link</Link>
    <StyledLink>Styled, exciting Link</StyledLink>
  </div>
);

Animációk

React Transition Group

import { Transition } from 'react-transition-group';

const duration = 300;

const defaultStyle = {
  transition: `opacity ${duration}ms ease-in-out`,
  opacity: 0,
}

const transitionStyles = {
  entering: { opacity: 1 },
  entered:  { opacity: 1 },
  exiting:  { opacity: 0 },
  exited:  { opacity: 0 },
};

const Fade = ({ in: inProp }) => (
  <Transition in={inProp} timeout={duration}>
    {state => (
      <div style={{
        ...defaultStyle,
        ...transitionStyles[state]
      }}>
        I'm a fade Transition!
      </div>
    )}
  </Transition>
);

React Motion

import {Motion, spring} from 'react-motion';
// In your render...
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {value => <div>{value.x}</div>}
</Motion>
<Motion style={{x: spring(this.state.open ? 400 : 0)}}>
  {({x}) =>
    // children is a callback which should accept the current value of `style`
    <div className="demo0">
      <div className="demo0-block" style={{
        transform: `translate3d(${x}px, 0, 0)`,
      }} />
    </div>
  }
</Motion>

React Spring

import {useSpring, animated} from 'react-spring'

function App() {
  const props = useSpring({opacity: 1, from: {opacity: 0}})
  return <animated.div style={props}>I will fade in</animated.div>
}

React és web komponensek

React és web komponensek

  • React
    • deklaratív könyvtár
    • adat és DOM szinkronban tartására
  • Web komponensek
    • újrahasznosítható komponensek
    • erős egységbezárás

Web komponensek Reactben

class HelloMessage extends React.Component {
  render() {
    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
  }
}
function BrickFlipbox() {
  return (
    <brick-flipbox class="demo">
      <div>front</div>
      <div>back</div>
    </brick-flipbox>
  );
}

React web komponensekben

class XSearch extends HTMLElement {
  connectedCallback() {
    const mountPoint = document.createElement('span');
    this.attachShadow({ mode: 'open' }).appendChild(mountPoint);

    const name = this.getAttribute('name');
    const url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
    ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
  }
}
customElements.define('x-search', XSearch);

Statikus oldalgenerátorok

Kontextus

  • statikus → dinamikus (szerver/kliens) → statikus
  • CMS rendszerek
  • Blogmotorok
  • Bemutatkozó oldalak
  • Github pages

Statikus oldalgenerátorok

  • Website teljes legenerálása deploy előtt
    • HTML, CSS, JS
  • Sablonok + adatok + kód → website
  • Nincs szükség dinamikus szerverre
  • Gyorsabb, hatékonyabb, SEO-barát, biztonságosabb
  • Dinamikus? → cloud szolgáltatások
    • comments: pl. Disqus
    • eCommerce: pl. Snipcart
    • email: MailChimp
    • twitter, Google Analytics, Pinboard

Name Languages Frameworks Great for
Nuxt JavaScript Vue Isomorphic apps
Next JavaScript React Isomorphic apps
Gatsby JavaScript React Isomorphic apps
React Static JavaScript React Isomorphic apps
VuePress JavaScript Vue Documentation
Docusaurus JavaScript React Documentation
Jekyll Ruby - Blogging, Getting started
Hugo Go - Blogging
Eleventy JavaScript - Getting started
Jigsaw PHP - PHP and Laravel developers

JAM Stack

  • JavaScript + API + Markup
  • SSG-vel generált oldalak
  • Nem függnek szervertől
  • Előnyök
    • Jobb teljesítmény
    • Olcsóbb, jobban skálázható
    • Nagyobb biztonság
    • Jobb DX
    • SEO-barát

JAM Stack

  • Bevált gyakorlatok
    • CDN
    • Git
    • Modern eszközök
    • Automatizált generálás
    • Atomi deploy
    • Instant Cache invalidáció

React + JAM Stack

  • Gatsby.js – CMS
  • Next.js – SSR
  • React keretrendszerek szerveroldali kiegészítésekkel
  • Pre-rendering
    • Server-side rendering (SSR)
    • Static-site generator (SSG)
    • Hydration: meglévő DOM felokosítása
  • Statikus + dinamikus részek

SSR

  • ReactDOMServer: Component → HTML
    • ReactDOMServer.renderToString(element)
    • ReactDOM.hydrate()
    • ReactDOMServer.renderToStaticMarkup(element)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.hydrate(<App />, document.getElementById('root'));
import path from 'path';
import fs from 'fs';

import React from 'react';
import express from 'express';
import ReactDOMServer from 'react-dom/server';

import App from '../src/App';

const PORT = process.env.PORT || 3006;
const app = express();

app.use(express.static('./build'));

app.get('/*', (req, res) => {
  const app = ReactDOMServer.renderToString(<App />);

  const indexFile = path.resolve('./build/index.html');
  fs.readFile(indexFile, 'utf8', (err, data) => {
    if (err) {
      console.error('Something went wrong:', err);
      return res.status(500).send('Oops, better luck next time!');
    }

    return res.send(
      data.replace('<div id="root"></div>', `<div id="root">${app}</div>`)
    );
  });
});

app.listen(PORT, () => {
  console.log(`😎 Server is listening on port ${PORT}`);
});

Platformok

Platformok (+ React)

  • Web
    • Kliens
    • Szerver
  • Mobil
    • Web – Reszponzív design
    • Progressive Web Applications (PWA)
    • View wrapper
    • Natív – React Native
  • Desktop
    • Electron
    • Operációs rendszer

PWA

  • Progressive Web Applications
  • Számos technológia és tervezési minta együttese
  • Technikailag
    • HTTPS
    • Service workers (Offline)
    • Manifest fájl (JSON)
  • Alapelvek
    • Kereshetőség
    • Telepíthetőség
    • Megoszthatóság (link)
    • Hálózatfüggetlen (offline/online)
    • Progresszív (régi eszközök)
    • Kapcsolattartó (üzenetek)
    • Reszponzív, Biztonságos

PWA

PWA

serviceWorker.register();

React Native

  • Dokumentáció
  • React → Natív kód
    • Android
    • iOS
    • Windows
  • Közös és platformfüggő kódok
  • JS + Natív kód

React Native

import React from 'react';
import { View, Text, Image, ScrollView, TextInput } from 'react-native';

export default function App() {
  return (
    <ScrollView>
      <Text>Some text</Text>
      <View>
        <Text>Some more text</Text>
        <Image source={{uri: "https://reactnative.dev/docs/assets/p_cat2.png"}} style={{width: 200, height: 200}}/>
      </View>
      <TextInput
        style={{
          height: 40,
          borderColor: 'gray',
          borderWidth: 1
        }}
        defaultValue="You can type in me"
      />
    </ScrollView>
  );
}

React Native for Windows

Dokumentáció

Electron

  • Electron
  • Webes alkalmazások Desktopon
  • Node + headless Chrome
  • Cross-platform
  • Példák
    • VSCode
    • MS Teams
    • Facebook Messenger
    • Atom

Böngésző pluginok

TypeScript

TypeScript

  • A JavaScript típusos kiegészítése
  • Honlap
  • Fordítási fázis
  • Biztonság
  • Kódkiegészítés
const add = (x: number, y: number) => {
  return x + y;
};
add(16, 23);
add("Hello", 23); // error

TypeScript + React

Cheatsheet

export interface Props {
  name: string;
  priority?: boolean
}
const PrintName = (props: Props) => {
  return (
    <div>
      <p style={{ fontWeight: props.priority ? "bold" : "normal" }}>{props.name}</p>
    </div>
  )
}
const ShowUser = (props: Props) => {
  return <PrintName name="Ned" />
}

TypeScript + Redux

Dokumentáció

Keretrendszerek

Végszó

  • A web folyamatosan fejlődik
    • JavaScript
    • Böngésző
    • Keretrendszerek
    • Paradigmák
  • Rugalmasság
  • Önfejlesztés fontos!!!