Lemoncode blog


Artículos, ideas, desarrollos, notas y mucho más

Configurando las pipelines de Bitbucket en tu proyecto front end

Las pipelines de Bitbucket permiten configurar fácilmente un entorno de integración continua en tu proyecto. Teóricamente, en teoría solo necesitas habilitarlas y configurar un fichero yml en tu raíz del proyecto.

Sin embargo …

  • Bitbucket factura por minutos de compilación, y por defecto tu integración se dispara en cada push, en cada rama. Debemos alcanzar un equilibrio de costes:

    • Lanzar la compilación en cada push hacia la rama master.

    • Lanzar la compilación en cada pull request.

  • Poner en marcha un fichero YAML de configuración es un proceso propenso a errores, especialmente si no tienes tiempo para leer detenidamente la documentación. Por tanto, necesitamos una manera fácil de comprobar que el YAML generado es válido.

Comment

Componentes de Clase en React: Inconvenientes

Introducción

Hasta hace unos meses, los componentes de clase de React (también llamados stateful components) estaban de moda. Pero eso se acabó con la llegada de los Hooks. ¿Por qué han dejado de ser una buena idea? En este post vamos a enumerar los principales inconvenientes a la hora de trabajar con componentes de clase en React.

La pesadilla del “this

En componentes de clase, el valor que adopta this dentro de una función dependerá de cómo sea invocada dicha función. Cuando nuestra función es utilizada como manejador de eventos (event handler), el valor al que apunta this será undefined. ¿Por qué? Las declaraciones y expresiones de clase (como por ejemplo nuestra función) se ejecutan en modo estricto, bajo el cual se aplica el binding por defecto a undefined y no a la instancia del componente como cabría esperar.

Más información al respecto aqui: https://medium.freecodecamp.org/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb

Por tanto, el this en un event handler disparado fuera de nuestro componente de clase, perderá la referencia a la instancia a la que pertenece.

Si ejecutamos el siguiente ejemplo y hacemos click en el botón Change Text, obtendremos el error:

Cannot read property ‘setState’ of undefined
export class MyHelloComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { myText: "hello" };
  }

  onChangeText() {        
    this.setState({ myText: "world" });
  }

  render() {
    return (
      <>
        <h3>{this.state.myText}</h3>
        <button onClick={this.onChangeText}>Change text</button>
      </>
    );
  }
}

La solución pasa por “atar” manualmente el this a la instancia de clase en cada una de las funciones declaradas como métodos de clase. Para ello contamos con dos mecanismos, o bien hacer un binding explícito en el constructor o bien utilizar funciones flecha experimentales (fat arrow) como método de clase (ver linea afectada marcada con el caracter “+”).

export class MyHelloComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { myText: "hello" };
+    this.onChangeText = this.onChangeText.bind(this);
  }

  onChangeText() {        
    this.setState({ myText: "world" });
  }

  render() {
    return (
      <>
        <h3>{this.state.myText}</h3>
        <button onClick={this.onChangeText}>Change text</button>
      </>
    );
  }
}

Demo: https://codesandbox.io/s/71opm61rzq

Esta característica de las clases puede llegar a convertirse en una fuente de problemas. ¿Cuántas veces has olvidado hacer adecuadamente el bind a tus event handlers, obteniendo finalmente un error en tiempo de ejecución?

Estado monolítico y funcionalidad difícilmente extraíble

En un componente de clase, tenemos un único lugar donde definir todo el estado al completo, y al mismo tiempo, una única forma de actualizarlo. ¿Inconveniente? Es complicado separar intereses y extraer la funcionalidad para su reuso. Recordemos que la separación de intereses (separation of concerns) y la reutilización de código (code reuse) son dos de los más importantes principios de programación que aparecerán en cualquier manual de buenas prácticas.

En el siguiente ejemplo, tenemos dos conceptos diferentes encapsulados en el mismo estado de clase:

export class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { color: "teal", name: "John", lastname: "Doe" };
  }

  getFullname() {
    return `${this.state.name} ${this.state.lastname}`;
  }

  render() {
      return (
          <div style={{ background: this.state.color }}>
              <h3>{this.getFullname()}</h3>
          </div>
      )
  }
}

Demo: https://codesandbox.io/s/yp9v4yyr8x

Veamos como podríamos implementar el mismo escenario usando hooks. En este caso podremos separar el estado para cada concepto:

import React from "react";

export const MyComponent = () => {
  const [color, setColor] = React.useState("teal");
  const [clientInfo, setClientInfo] = React.useState({name: 'John', lastname: 'Doe'});

  const getFullname = () => {
      return `${clientInfo.name} ${clientInfo.lastname}`;
  }

  return (
    <div style={{ background: color }}>
      <h3>{getFullname()}</h3>
    </div>
  );
};

Demo: https://codesandbox.io/s/ppom543mj7

Podemos dar un paso más y encapsular la funcionalidad relativa al usuario en un custom hook:

const useClientInfo = (name, lastname) =>  {
  const [clientInfo, setClientInfo] = React.useState({
    name,
    lastname,
  });

  const getFullname = () => {
    return `${clientInfo.name} ${clientInfo.lastname}`;
  };

  return {clientInfo, setClientInfo, getFullname}
}

export const MyComponent = () => {
  const [color, setColor] = React.useState("teal");
  const {getFullname} = useClientInfo('John', 'Doe');

  return (
    <div style={{ background: color }}>
      <h3>{getFullname()}</h3>
    </div>
  );
};

Demo: https://codesandbox.io/s/ly7wlq9mo9

Gestión de intereses relacionados en manejadores separados

Cuando usamos componentes de clase en React, disponemos de distintos eventos durante su ciclo de vida en los cuales ejecutar código: componentDidMount, componentDidUpdate, componentWillUnmount, etc. Podría darse el caso de que cierta funcionalidad relacionada tenga que ser dividida entre los distintos handlers del ciclo de vida del componente. Por ejemplo:

Definamos un componente padre:

export class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { visible: false };
  }

  render() {
    return (
      <>
        {this.state.visible && <MyChildComponent />}
        <button onClick={() => this.setState({ visible: !this.state.visible })}>
          Toggle Child component visibility
        </button>
      </>
    );
  }
}

Ahora, un componente hijo que simplemente mostrará la información de usuario:

export class MyChildComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: "John", lastname: "Doe" };
  }

  componentDidMount() {
    console.log("Hey Im mounting");
    console.log(`${this.state.name} ${this.state.lastname}`);
  }

  componentDidUpdate() {
    console.log("Just updating...");
    console.log(`${this.state.name} ${this.state.lastname}`);
  }

  componentWillUnmount() {
    console.log("bye bye, unmounting...");
  }

  render() {
    return (
      <div>
        <h3>
          {this.state.name} {this.state.lastname}
        </h3>
        <input
          value={this.state.name}
          onChange={e => this.setState({ name: e.target.value })}
        />
        <input
          value={this.state.lastname}
          onChange={e => this.setState({ lastname: e.target.value })}
        />
      </div>
    );
  }
}

Demo: https://codesandbox.io/s/oqyo3159jq

Mediante el empleo de hooks podemos agrupar toda esta funcionalidad en una única función:

const MyChildComponent = () => {
  const [userInfo, setUserInfo] = React.useState({name: 'John', lastname: 'Doe'})

  React.useEffect(() => {
    console.log('called when the component is mounted and right after it gets updated');

    return () => console.log('Clean up from the previous render before running effect next time ... ');
  })

  return (
    <div>
      <h3>
        {userInfo.name} {userInfo.lastname}
      </h3>
      <input
        value={userInfo.name}
        onChange={e => setUserInfo({ ...userInfo, name: e.target.value })}
      />
      <input
        value={userInfo.lastname}
        onChange={e => setUserInfo({ ...userInfo, lastname: e.target.value })}
      />
    </div>
  );
}

En este ejemplo, el código declarado dentro del useEffect es ejecutado una vez que el componente se ha montado pero también justo después de cada render. Por otro lado, la función de limpieza (devuelta en el useEffect) se ejecuta después de que el componente se haya montado y después de cada ejecución del efecto.

Demo: https://codesandbox.io/s/5zllr3k09p

Bien, pero … ¿y si quiero ejecutar un trozo de código solo cuando el componente se haya montado y hacer la limpieza cuando el componente vaya a desmontarse? Para ello, podemos jugar con el segundo parámetro del useEffect (en el ejemplo marcado con “-” las lineas que se eliminarían, con “+” las líneas que se añaden).

const MyChildComponent = () => {
  const [userInfo, setUserInfo] = React.useState({name: 'John', lastname: 'Doe'})

  React.useEffect(() => {
-    console.log('called just when the component is mounted and when after it gets updated');
+    console.log('called just when the component is mounted');

-    return () => console.log('Clean up from the previous render before running effect next time ... ');
+    return () => console.log('Clean up executed just when the component gets unmounted ... ');
-  })
+  }, [])

  return (
    <div>
      <h3>
        {userInfo.name} {userInfo.lastname}
      </h3>
      <input
        value={userInfo.name}
        onChange={e => setUserInfo({ ...userInfo, name: e.target.value })}
      />
      <input
        value={userInfo.lastname}
        onChange={e => setUserInfo({ ...userInfo, lastname: e.target.value })}
      />
    </div>
  );
}

Demo: https://codesandbox.io/s/q91qjql8r4

Ruido al utilizar High Order Components

Un HOC o High Order Component es una excelente forma de añadir nuevas capacidades a tu componente mediante composición, sin embargo:

  • Necesitas refactorizar su interfaz para poder aplicarlo.

  • Encadenar diversos HOC simultáneamente puede ser una pesadilla.

Veamos un ejemplo mínimo. El siguiente componente se emplea para saludar al usuario que está actualmente logado:

import React from "react";

export const MyComponent = (props) => {
  return (
    <>
      <h3>Hello: </h3>
    </>
  )
}

Para inyectar el usuario que está actualmente logado podemos crear un HOC:

const withUserInfo = (ComponentToWrap) => (props) =>
  <>
    <ComponentToWrap {...props} user="John" />
  </>
Let's make usage of this HoC in MyComponent

- export const MyComponent = (props) => {
+ const 

Podemos hacer uso de este HOC en MyComponent del siguiente modo:

const MyComponentInner = (props) => {  
  return (
    <>
      <h3>Hello: {props.user}</h3>
    </>
  )
}

export const MyComponent = withUserInfo()

Demo: https://codesandbox.io/s/l7qznjjyw9

Esta forma de añadir funcionalidad es bastante potente, pero, ¿no sería más sencillo y expresivo un mecanismo con el que podamos decir: “quiero usar esta funcionalidad”? Veamos como implementar este comportamiento utilizando hooks:

import React from "react";

const useUserInfo = () => {
  const [userInfo, setUserInfo] = React.useState('John');

  return {userInfo, setUserInfo}
}

export const MyComponent = (props) => {
  const {userInfo} = useUserInfo();

  return (
    <>
      <h3>Hello: {userInfo}</h3>
    </>
  )
}

Demo: https://codesandbox.io/s/pwj6z446xq

Ventajas:

  • No necesitamos reescribir el interfaz de nuestro componente: borrar el export, crear un componente para envolverlo, etc.

  • Sin complicaciones al tener anidando HOCs.

  • El contrato es claro, no tenemos que adivinar que propiedades está inyectando el HOC a nuestro componente.

Migrando componentes de su forma funcional a clase, y también en el sentido contrario

Cuando iniciamos la implementación de un componente tratamos de mantenerlo sencillo, por lo que es típico comenzar con un componente funcional. Un ejemplo simple podría ser el siguiente: mostrar un mensaje de bienvenida a un usuario (nos lo informa el padre a través de la propiedad userName).

import React from "react";

export const MyComponent = () => {
  return (
    <>
      <MyChildComponent userName="John"/>
    </>
  )
}

export const MyChildComponent = (props) => {
  return (
    <>
      <h3>Hello: {props.userName}</h3>      
    </>
  )
}

Demo: https://codesandbox.io/s/985wyr1olw

Supongamos que, en lugar de recibirlo desde el padre, queremos almacenarlo en el estado local de nuestro componente. Una aproximación clásica sería migrar nuestro componente a su forma stateful, es decir, refactorizarlo por completo, prestando atención de no equivocarnos con el this.state, añadiendo su constructor, implementando el método render, etc. Algo tal que así:

export const MyComponent = () => {
  return (
    <>
      <MyChildComponent/>
    </>
  )
}

export class MyChildComponent extends React.Component {  
  constructor(props) {
    super(props);
    this.state = {userName: 'John'}
  } 

  render() {
      return (
        <>  
         <h3>Hello: {this.state.userName}</h3>      
        </>
      )
  }
}

Demo: https://codesandbox.io/s/40l5k4q1o9

¿Cómo podría haber sido este refactor utilizando hooks? Tan sencillo como esto:

export const MyComponent = () => {
  return (
    <>
     <MyChildComponent/>
    </>
  )
}

export const MyChildComponent = (props) => {
  const [userName]  = React.useState('John');
  return (
    <> 
     <h3>Hello: {userName}</h3>      
    </>
  )
}

Demo: https://codesandbox.io/s/jlkoxm6plw

Combinando componentes funcionales y de clase

Por último, pero no menos importante, en un proyecto de dimensiones considerables, una aproximación mixta donde componentes funcionales y de clase tengan que convivir juntos podría traer diversos inconvenientes de mantenibilidad:

  • Inconsistencia en nuestra base de código.

  • Dificultad añadida para que nuevos desarrolladores se inicien en el proyecto, teniendo que aprender ambas formas y decidir cuando es más conveniente una u otra, o cuando deben refactorizar un componente existente en uno u otro sentido.

  • La refactorización de componentes, ya sea en un sentido u otro, es una tarea propensa a errores, por ejemplo: se nos olvida eliminar el this, nos equivocamos en la sintaxis de clase vs función, errores con la función de render, etc.

Resumiendo

Antes de tirarnos a la piscina con la nueva característica de moda, es importante aprender por qué la necesitamos y que problemas viene a resolver. Esperamos que este artículo pueda ayudaros a entender mejor por qué los hooks han generado tanta expectación en la comunidad y se han convertido en un estándar de facto. En los siguientes artículos de esta serie comenzaremos a indagar en los detalles que hacen a los hooks tan poderosos, mostrando su cara amable y también los casos frontera, basándonos en casos de uso en proyectos reales. ¡Estad atentos!

Esperamos que hayáis disfrutado el artículo. ¡Muchas gracias!

Comment

Beca Yes We Tech - Septima edición Máster Front End Lemoncode

En 2018 presentamos nuestra primera beca Yes We Tech, seleccionamos a dos candidatas para que cursaran el máster , ¿Cual fue el resultado? Tener a dos alumnas muy motivadas, con muchas ganas de trabajar y que como fruto del esfuerzo consiguieron un empleo al finalizar el máster, con estos resultados… ¿ Por qué no repetir? :)

En colaboración con YesWeTech ofrecemos nuestra segunda beca de estudios para aportar nuestro granito de arena a conseguir que haya más diversidad e igualdad de oportunidades en esta profesión. ¿En que consiste? En cubrir el 100% del coste del Máster Front End Online Lemoncode a una alumna que pertenezca a una minoría con baja representación en el sector profesional. Ofrecemos una plaza, y para ello hemos resuelto unas bases para poder inscribiros y seleccionar a la aspirante.

yeswetech.jpeg


La convocatoría se abre el 15 de Abril y se cierra el 15 de Mayo, el 1 de Junio anunciaremos la persona seleccionada. 

A continuación te detallamos las bases de la misma:

Requisitos

  • Pertenecer a minorías con baja representación en el sector profesional, es decir, mujeres y en especial quienes sean inmigrantes, pertenezcan al colectivo LGTBQIA+, estudiantes y mujeres con con diversidad funcional.

  • Ingresos inferiores a 27.000€ brutos año o contar con cargas familiaries.

  • Tener conocimientos previos de programación (sea experiencia laboral, como estudiante, o autodidacta demostrable).

Criterios de evaluación

  • Horas de estudio semana que la candidata pueda dedicar a la semana.

  • Curriculum Vitae.

  • Entrevista personal y opción de realizar prueba técnica a las finalistas.

Información mínima a enviar

  • Documento personal identificativo (DNI, NIE, Pasaporte)

  • Carta explicando los motivos por los que la alumna está interesada en realizar el máster.

  • Número de horas de estudio semanal que le puede dedicar al máster

  • Curriculum Vitae.

  • Información salarial (no es necesario el envío de documentación acreditativa, pero se podría requerir si la candidata llega a finalista).

Fechas

  • Aceptación candidatas del 15 de Abril al 15 de Mayo de 2019.

  • Fecha resolución beca (1 plaza) 1 de Junio de 2019.

  • Fecha arranque Máster 22 de Septiembre de 2019

Comite evaluador

  • Miembros de la comunidad YesWeTech.

  • Miembros de Lemoncode Formacion S.L.

Para aplicar envíanos un correo con la información que te pedimos a nuestra cuenta de EMail: formacion@lemoncode.net

Te estamos muy agradecidos si nos ayudas a difundir esta beca.

Comment

Preguntas frecuentes Máster Front End Online Lemoncode

A lo largo de las 5 ediciones de este Máster hemos tenido la suerte de contar con un buen número de estudiantes y nos han planteado cuestiones muy interesantes que nos gustaría compartir. En este post te resumimos las más comunes (si tienes alguna consulta que no este recogida en este artículo no dudes en contactar con nosotros). Espero que te sea de utilidad.

Comment

Configurando Alias en webpack + visual code + typescript + jest

Introducción

Este post está basado en este excelente Gist de Carlos Hidalgo

Cuando trabajamos con imports, una de las cosas que más duelen (y huelen) es trabajar con rutas relativas, es decir, si tenemos una estructura como esta:

Ejemplo de estructura de carpetas de proyecto

Ejemplo de estructura de carpetas de proyecto


Y por ejemplos estamos editando el fichero pods/movies/movies-grid.container.ts Y queremos desde nuestra página referenciar a un elemento de la carpeta api, tendríamos que hacer un import del tipo:

import {fetchMovies} from '../../api';

Con uno o dos niveles “../” igual esto no tiene mala pinta, pero a veces te puedes encontrar con cosas como:

import { TrainingSummary } from '../../../../model/trainingSummary';

Y lo que es peor, si refactorizamos y movemos de carpetas ficheros acabamos teniendo un lio de imports.

¿ Que solución podemos aplicar? crear unos alias a nivel de carpeta principal, que nos permitan minimizar el uso de carpetas relativas, es decir en este caso si hago un alias a la carpeta api, el import relativo que creamos anteriormente se quedaría de la siguiente manera:

import {fetchMovies} from '/api';

La idea aquí es crear unos alias en carpetas de primer nivel y evitar el infierno de rutas relativas.

Y..¿ Esto es fácil de configurar? Bueno más que fácil, tiene truco, tienes que saber bien donde tocar:

  • Hay que indicarle a webpack los mappings de esos alias (tocaremos el webpack.config.js).

  • Hay que ayudar a VSCode y Typescript a mapear esos alias (tocaremos el tsconfig.json).

  • Y si tenemos pruebas unitarias con JEST también debemos de indicarle los mapeos de carpeta a alias (aquí actualizaremos el fichero de configuración de jest, sea el jest.json o el propio package.json, depende de donde tengamos la configuración).

Con la hoja de ruta que os vamos a definir, a partir de ahora configurar un grupo de alias va a ser pan comido :).

Configurando webpack

Webpack necesita saber a paths físicos mapean los alias, abrimos el fichero webpack.config.js y añadimos a la sección resolve, una subsección que llamaremos alias y ahí listamos todos los mapeos de alias a ruta, quedaría tal que así:

webpack.config.json

module.exports = {
  resolve: {
    alias: {
      api: path.resolve(__dirname, './src/api/'),
      commonApp: path.resolve(__dirname, './src/common-app/'),
      core: path.resolve(__dirname, './src/core/'),
      layout: path.resolve(__dirname, './src/layout/'),
      pods: path.resolve(__dirname, './src/pods/'),      
      scenes: path.resolve(__dirname, './src/scenes/'),
    },
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
  },
La lista de alias es la que usamos en nuestra aplicación, en tu aplicación tendrás otras carpetas y otros alias que podrás configurar según tus necesidades.

Configurando Typescript + Visual Studio code

Ahora nos toca que Typescript y Visual Studio Code se lleven bien con estos alias, para ellos en el tsconfig, tenemos que decirle cual es nuestra carpeta de partida (en este caso la src) y crear una sección de paths en la que añadimos nuestra lista de alias (muy importante: esta lista de paths tiene que ir debajo de la sección de compilerOptions).

tsconfig.json

{
  "compilerOptions": { 
    "moduleResolution": "node",
    "baseUrl": "./src/",
    "paths": {
      "api": ["./api/*"],
      "common-app": ["./common-app/*"],
      "core": ["./core/*"],
      "layout": ["./layout/*"],
      "pods": ["./pods/*"],
      "scenes": ["./scenes/*"]
    }
  }
}

Configurando Jest


Cómo último paso, si estamos usando Jest, tenemos que añadir la lista de paths al fichero de configuración, dependiendo del proyecto la configuracíon de jest te la puedes encontrar en el mismo package.json o en un fichero específico (jest.json o similar), en el ejemplo que cubrimos se encuentra en el jest.json.

/config/jest.json

{
  "moduleNameMapper": {
    "^api/(.*)$": "/src/api/$1",
    "^common-app/(.*)$": "/src/common-app/$1",
    "^core/(.*)$": "/src/core/$1",
    "^layout/(.*)$": "/src/layout/$1",
    "^pods/(.*)$": "/src/pods/$1",
    "^scenes/(.*)$": "/src/scenes/$1"
  }
}

Ejemplo real

Si quieres ver esto aplicado en un proyecto real, aquí tienes:

Agradecimientos

Este post está basado en este excelente Gist de Carlos Hidalgo, que se pego unas horas de investigación y cabezazos hasta que dio con los pasos exactos :).

¿Con ganas de aprender desarrollo Front End?

Si tienes ganas de ponerte al día en el mundo del Front End, impartimos un máster online con clases en vivo. Para más información: http://lemoncode.net/master-frontend

Comment

Entrevista a Juan José Montiel

En el Máster Front End Online Lemoncode, participamos un equipo de 12 de profesores, y también una serie de empresas que están adheridas a nuestra bolsa de trabajo. ¿Alguna vez te ha picado la curiosidad de saber de donde venimos o qué hacemos? Continuamos esta de serie de posts entrevistando a Juan José Montiel, profesor del máster Front End Online Lemoncode, experto en accesibilidad y Microsoft MVP.

Comment

Entrevista a Erik Rasmussen

En el Máster Front End Online Lemoncode, participamos un equipo de 12 de profesores, y tambíen una serie de empresas que están adheridas a nuestra bolsa de trabajo. ¿Alguna vez te ha picado la curiosidad de saber de donde venimos o qué hacemos? Abrimos sería de posts con entrevistas al equipo y empresas que colaboradon en este máster.

Empezamos entrevistando a Erik Rasmussen, el desarrollador de proyectos tales como Redux-Forms, o guías como Redux Ducks

Comment

React y D3.js, trabajando juntos I - Introducción

Esta serie de dos posts viene inspirada por la charla que impartimos en el Open South Code 2018 sobre la integración entre React y D3.js, cuyo material puedes encontrar aqui: fjcalzado.surge.sh. En esta primera parte haremos un breve repaso de ambas librerías, centrándonos principalmente en la gestión del DOM. Veremos conceptos interesantes y concluiremos con la problemática a la hora de trabajar con ambos frameworks. En la segunda parte, explicaremos las distintas soluciones disponibles y las ilustraremos con código y ejemplos. ¡Vamos allá!

2 Comments

Server Side Rendering I - Conceptos

El otro día en el Máster Front End Lemoncoders, Eirik Rasmussen nos dió una sesión muy interesante sobre server side rendering y como implementarlo usando React y Next. Eso nos ha animado a escribir una serie de posts en la que explicamos como funciona esto de manera detallada.

En este primer artículo de la serie vamos a centrarnos en  es explicar bien el problema que viene a resolver "Server side rendering" así como conceptos de base, en siguientes entrega nos meteremos de lleno en una implementación utilizando Next y React.

7 Comments

Webpack: poniendo a dieta tus bundles (II)

En la entrega anterior vimos como podíamos usar webpack-bundle-analyzer para ver que librerías de terceros hacían que nuestro "bundle" estuviera gordo.

En esta entrega vamos a ver como habilitar treeshaking en esas librerías y reducir su tamaño de forma considerable. Como ejemplo trabajaremos con una librería de componentes popular: material_ui, crearemos un aplicacíon simple y veremos como reducimos el espacio que ocupa esta librería en nuestra aplicación, pasaremos de un peso de 960 Kb a 56 Kb.

Comment

Webpack: poniendo a dieta tus bundles

Abrimos una serie de posts en lo que nos centramos en aligerar el peso de nuestros bundles, en este primer post os presentamos una herramienta que os ayudará a identificar que paquetes son culpables del "sobrepeso" de tu aplicación.

1 Comment

Curso NodeJS por Jaime Salas - 70% Descuento

Hace unos meses ofrecimos un descuentazo para el curso de .net core, ahora le toca al de nodejs, es hora de ponerte al día con la grabación del curso “Creación de API’s REST con nodejs, express, mongoose, mongo” de 21 horas de duración.

El temario del curso:

  1. Comenzar con node
  2. Modulos
  3. Modelo asíncrono
  4. Eventos.
  5. Streams.
  6. Sistema local.
  7. Aproximacion Web.
  8. Mongo.
  9. Mongoose.
  10. Rest Api con Express.

¿Qué tal está este curso?

Te pasamos la opinión de un alumno (Jorge Carballo):

"Esta formación me encanto. Había estado tocando algo de nodejs y con el curso he aprendido mucho y he descubierto que es una tecnología muy interesante. Me ha dado pie a investigar y practicar más sobre nodejs."

Hemos publicado una oferta especial limitada a los primeros 50 primeros que adquiráis este curso. El precio normal es de 150 €, presentando el cupón que te adjuntamos, esté te saldría por 45 €.

Instrucciones para canjear este cupón:

Pincha en comprar el curso de nodejs.

  • Regístrate como usuario (te puedes registrar también con linkedin).

  • En el proceso de compra antes de meter tu tarjeta de crédito, mira en la parte superior izquierda encontrarás un enlace para introducir un cupón de descuento.

cupon_nodejs.png
  • Mete este cupón:   
    nodejsnewsletter34hnc3
  • Con eso ya te sale el curso por sólo 45 € y ya puedes introducir tu tarjeta de crédito para realizar el pago.

Comment

Curso .net core por Eduard Tomás 70% de descuento

Hace unos días que publicamos una oferta para los subscriptores de nuestra newsletter, la grabación de un curso bien completo de .net core (21 horas de duración), impartido por nada más y nada menos que Eduard Tomás (MVP ASP .net), con un 70% de descuento (el curso tiene un coste de 150 €, con el cupón se te quedaría en 45 €).

Está oferta ha tenido una muy buena acogida, hemos decidido abrirla a la comunidad a los 50 primeros que adquieran el curso.

¿ Qué tal está el curso? Te pasamos la opinión de un alumno que lo cursó

"En este curso de .NET Core 2.0 de los chicos de Lemoncode, el maestro en la materia Eduard Tomás da un repaso magnifico de la tecnología y no contento con ello, nos aporta como añadido conocimientos de C#, inyección de dependencias, entity framework core, métodos de extensión, etc.

Sin conocer .NET Core me ha aportado muchísimo y he salido con ganas de más.

Eduard es un gran conocedor de la materia, muy didáctico y comunicador lo que hace una combinación perfecta para sumergirte en la materia.

Recomendado 100%."

Antonio Tobajas (Alumno curso .net core)

¿ Qué temario tiene? Lo puedes consultar en este enlace: https://lemoncode.net/creacion-de-rest-apis-con-net-core

¿ Tienes fecha límite para verlo? No, lo puedes ver cuando y cuantas veces quieras, es más te puedes bajar el contenido a tu disco duro.

Instrucciones para obtener el descuento:

cupon.png

 

  • Mete este cupón:

netcorenewsletter89hp765

  • Con este cupón te sale el curso por sólo 45 € y ya puedes introducir tu tarjeta de crédito para realizar el pago.

 

 

3 Comments