Aplicació Reactjs a través del servidor web Express

De wikijoan
Salta a la navegació Salta a la cerca

_

_

Tutorial[modifica]

Seguim

La idea és que quan desenvolupem una app amb React fem:

$ npm run start (o npm start)

i la visulitzem pel port 3000:

i el punt d'entrada d'aqueta app és el script src/App.js. Aquest seria el mode de desenvolupament.

Ara bé, en producció hem de servir l'app a través d'un servidor web (Express) per un altre port (per ex 8080), i el punt d'entrada ha de ser el script index.html (public/index.html i build/index.html).

Anem a veure com fer-ho.

Step 1: Install create-react-app[modifica]

$ create-react-app your-app-name
$ cd your-app-name

Step 2: Install packages for create react app[modifica]

$ npm install; 

Podem comprovar que funciona fent:

$ npm start
  • localhost:3000

El punt d'entrada és src/App.js.

Step 2b: npm run build[modifica]

Ara podem desplegar aquesta aplicació:

$ npm run build

> your-app-name@0.1.0 build /home/joan/M06_WEC_1920/UF2/your-app-name
> react-scripts build

Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  39.39 KB  build/static/js/2.ed50ce24.chunk.js
  777 B     build/static/js/runtime-main.7a59697d.js
  651 B     build/static/js/main.6d4ec6a5.chunk.js
  547 B     build/static/css/main.5f361e03.chunk.css

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

serve -s build
$ serve -s build

I funciona:

  • localhost:5000

El punt d'entrada és build/index.html

Si fem:

$ serve -s public

El punt d'entrada és public/index.html (editem aquest fitxer)

NOTA: el script build/index.html és el mateix que public/index.html. En el moment que fem el build es copia public/index.html a build/index.html.

Step 3: Install express[modifica]

$ npm install express --save

Step 4: Create a server.js file[modifica]

script server.js: (es crea a l'arrel del projecte, cd your-app-name)

const express = require('express');
const bodyParser = require('body-parser')
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));

app.get('/ping', function (req, res) {
 return res.send('pong');
});

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(process.env.PORT || 8080);

Step 5: Update your package.json[modifica]

Add the following to your package.json

"proxy": "http://localhost:8080"

Queda de la següent manera:

...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "proxy": "http://localhost:8080",
...

Step 6: Start the express server[modifica]

Arrenquem el servidor web:

$ node server.js

I l'aplicació la tenim disponible a:

  • localhost:8080

El punt d'entrada és el script build/index.html. Això ho podem comprovar si modifiquem aquest fitxer(posem alguna cosa després del body). Si volem que el punt d'entrada sigui public/index.html hem de modificar les línies app.use i res.sendFile del server.js.

NOTA. Això no cal fer-ho. public/index.html i build/index.html. El primer es copia en el segon quan fem el npm run build.

Step 7. Conclusions[modifica]

Ara tinc un entorn de producció a través del port 8080.

Puc continuar desenvolupant fent:

$ npm start

i puc modificar el script App.js i veure els canvis en calent pel port localhost:3000. Ara bé, no puc esperar veure aquests canvis pel port 8080. Per veure els canvis he de fer el npm run build.

Aplicació pràctica: Simple example of a ReactJS and OpenLayers map component[modifica]

Anem a posar-ho en pràctica i anem a fer el Hola món de Openlayers per visualitzar un mapa.

Installing OpenLayers for ReactJS:

$ npm install ol --save
$ npm install proj4 @material-ui/core --save

Si mirem package.json, veiem quines són les dependències, i crec que també és important fer:

$ npm install react --save
$ npm install react-dom --save
$ npm install react-scripts --save

Creem el script src/js/components/OLMapFragment.js: (aquest és el component principal de OpenLayers)

import React from 'react'
import Grid from '@material-ui/core/Grid'

// Start Openlayers imports
import { 
    Map,
    View
 } from 'ol'
import {
    GeoJSON,
    XYZ
} from 'ol/format'
import {
    Tile as TileLayer,
    Vector as VectorLayer
} from 'ol/layer'
import {
    Vector as VectorSource,
    OSM as OSMSource,
    XYZ as XYZSource,
    TileWMS as TileWMSSource
} from 'ol/source'
import {
    Select as SelectInteraction,
    defaults as DefaultInteractions
} from 'ol/interaction'
import { 
    Attribution,
    ScaleLine,
    ZoomSlider,
    Zoom,
    Rotate,
    MousePosition,
    OverviewMap,
    defaults as DefaultControls
} from 'ol/control'
import {
    Style,
    Fill as FillStyle,
    RegularShape as RegularShapeStyle,
    Stroke as StrokeStyle
} from 'ol/style'

import { 
    Projection,
    get as getProjection
 } from 'ol/proj'

// End Openlayers imports

class OLMapFragment extends React.Component {
    constructor(props) {
        super(props)
        this.updateDimensions = this.updateDimensions.bind(this)
    }
    updateDimensions(){
        const h = window.innerWidth >= 992 ? window.innerHeight : 400
        this.setState({height: h})
    }
    componentWillMount(){
        window.addEventListener('resize', this.updateDimensions)
        this.updateDimensions()
    }
    componentDidMount(){

        // Create an Openlayer Map instance with two tile layers
        const map = new Map({
            //  Display the map in the div with the id of map
            target: 'map',
            layers: [
                new TileLayer({
                    source: new XYZSource({
                        url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                        projection: 'EPSG:3857'
                    })
                }),
                new TileLayer({
                    source: new TileWMSSource({
                        url: 'https://ahocevar.com/geoserver/wms',
                        params: {
                            layers: 'topp:states',
                            'TILED': true,
                        },
                        projection: 'EPSG:4326'
                    }),
                    name: 'USA'
                }),
            ],
            // Add in the following map controls
            controls: DefaultControls().extend([
                new ZoomSlider(),
                new MousePosition(),
                new ScaleLine(),
                new OverviewMap()
            ]),
            // Render the tile layers in a map view with a Mercator projection
            view: new View({
                projection: 'EPSG:3857',
                center: [0, 0],
                zoom: 2
            })
        })
    }
    componentWillUnmount(){
        window.removeEventListener('resize', this.updateDimensions)
    }
    render(){
        const style = {
            width: '100%',
            height:this.state.height,
            backgroundColor: '#cccccc',
        }
        return (
            <Grid container>
                <Grid item xs={12}>
                    <div id='map' style={style} >
                    </div>
                </Grid>
            </Grid>
        )
    }
}
export default OLMapFragment

El script principal de React no és App.js, sinó index.js (que normalment crida a App.js). Per tant, anem a modifificar-lo:

script src/index.js:

import React from 'react'
import { render} from 'react-dom'
import OLMapFragment from './js/components/OLMapFragment'

render(
    <OLMapFragment />
    ,
    document.getElementById('react-container')
)

veiem com s'importa el component OLMapFragment, i queda clar la ruta que ha de tenir OLMapFragment.js.

I finalment falta index.html, que per tot el que hem dit ha d'estar a public/index.html.

script public/index.html:

<!DOCTYPE html>
<html class="no-js" lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content='ie=edge'>
    <title>Openlayers React</title>
    <meta name="description" content="Explore planet Mars">
    <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
    <!-- material-ui prerequisites -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
    <!-- end material-ui prerequisites -->

    <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css"
        type="text/css" />

</head>

<body>
    <!--[if lte IE 8]
        <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com">upgrade your browser</a></p>
        <![endif]-->
    <div id='react-container'></div>

</body>

</html>

Aquí és on tenim el contenidor principal del mapa, i on tenim els links dels estils i fonts.

Now, run the ReactJS project with a web server and open the web page with an Internet browser.

Per tant, amb tot el que hem dit:

$ npm start
$ npm run build
$ serve -s build

i a través del Express:

$ node server.js
  • localhost:8080

creat per Joan Quintana Compte, abril 2020