Comenzaremos sobre una carpeta vacia e inicializaremos el package.json
npm init -y
Luego de eso instalaremos las dependencias que necesitaremos
npm i react react-dom --save;
npm i webpack webpack-cli webpack-dev-server --save-dev;
npm i "babel-loader@^8.0.0-beta" @babel/core --save-dev;
npm i @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties --save-dev;
npm i html-webpack-plugin html-loader --save-dev;
npm i style-loader css-loader --save-dev;
Nota:
- Los
*-loader
son los paquetes que ayudarán en la comunicación con webpack - @babel/preset-env @babel/preset-react ayudarán a la transpilación de ES6 y JSX
- @babel/plugin-proposal-class-properties este plugin ayudará a usar un nuevo feature de ES, class instance/static fields
Editamos el archivo package.json
con las siguientes líneas
"scripts": {
"start": "webpack-dev-server --open --mode development",
"build": "webpack --mode production"
},
Creamos el archivo .babelrc
e incluimos nuestros presets
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}
Tambien creamos el archivo webpack.config.js
y le damos la siguiente configuración
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /\.css$/,
use:[
{ loader: "style-loader" },
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[local]--[hash:base64:5]'
}
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
Nota: Que quede claro que estamos activando CSS Modules para observar el resultado y analizarlo
Agregamos la carpeta src
y dentro de esta los archivos: index.html
, index.js
, App.js
y App.css
index.html será nuestro template para el html-webpack-plugin
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My Awesome App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js será el lugar en donde rederizaremos nuestra App
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const root = document.getElementById('root');
root ? ReactDOM.render(<App />, root) : false;
App.js será nuestro componente principal
import React, { Component } from 'react'
import styles from './App.css'
export default class App extends Component {
state = {
message: 'Message'
}
handleToggleMessage = (message) => {
this.setState({ message })
}
render() {
return (
<div className={styles.app}>
<div className={styles.container}>
<h1>{this.state.message}</h1>
<button
className={styles.buttonSuccess}
onClick={() => this.handleToggleMessage('Hello World!!! :D')}>Hello</button>
<button
className={styles.buttonPrimary}
onClick={() => this.handleToggleMessage('Bye World!!! :(')}>Bye</button>
</div>
</div>
)
}
}
App.css
* {
margin: 0;
padding: 0;
}
h1 {
margin-bottom: 10px;
}
.app {
background-color: #f3f3f3;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.container {
background-color: #fff;
border-radius: 5px;
padding: 30px;
text-align: center;
}
.button {
border: 0;
border-radius: 5px;
color: #fff;
outline: 0;
margin: 0 5px;
padding: 5px 10px;
}
.buttonSuccess {
composes: button;
background-color: #27ae60;
}
.buttonPrimary {
composes: button;
background-color: #2980b9;
}