Git Product home page Git Product logo

canariasjs-workshop-lerna's Introduction

canariasjs-lerna-workshop

Introducción

Texto de introducción

Proyecto que vamos a montar

En este proyecto vamos a montar un proyecto de tipo lerna. El cual nos permitirá tener una estructura de proyecto monorepo, donde podremos tener varios repositorios independientes, y de paso, una estructura de dependencias entre ellos, si llega a ser necesario.

Despues veremos como podemos interacturar con lerna mediante los distintos comandos que nos ofrece. Asi como interactur entre los distintos paquetes.

Tambien veremos que no sera necesario utilizar un unico bundler, ya que podremos utilizar uno por cada proyecto.

1 Init Repo!


Primero de todo lo instalaremos globalmente en nuestro npm (o yarn)

npm install --global lerna

Luego crearemos una carpeta donde vamos a montar nuestro proyecto.

mkdir lerna-workshop

Luego iniciaremos lerna con el siguiente commando:

lerna init

Por ultimo a;adiremos un gitignore bastante basico:

touch .gitignore

Y a;adiremos lo siguiente en dicho gitignore:

node_modules
dist

Esto nos deberia crear la sigueinte estructura:

lerna-repo/
  packages/
  package.json
  .gitignore
  lerna.json
  1. Entendiendo la configuracion de lerna

Si entramos a lerna.json veremos que nos ha creado un sencillo fichero de configuracion

{
  "packages": ["packages/*"],
  "version": "0.0.0"
}

Esta configuracion ha sido creada por defecto.

  • Packages: nos indica las carpetas que contienen los paquetes que vamos a montar.
  • Version: nos indica la version actual de lerna con la que va a comparar para realizar las actualizaciones.

Por otro lado, merece la pena indicar que podemos cambiar la forma de inicializar lerna, pero no lo haremos, de otra manera mediante: lerna init -i el cual nos permite inicializar la configuracion pero con el versionado independiente de cada paquete en vez de un verisonado "centralizado". Tambien vale la pena especificar que se puede cambiar esto a gusto (que ya veremos mas adelante en el curso).

Para los usuarios de yarn, podeis cambiar el cliente predeterminado con el cual correr los commandos de lerna especificando la siguiente configuracion:

{
  ...
  "npmClient": "yarn"
  ...
}
  1. Crear nuestro primer paquete

En lerna tenemos varias opciones de agregar paquetes a nuestro proyecto:

  • Crear un paquete nuevo "a mano".
  • Utilizar los comandos de lerna para agregar paquetes.

Primero de todo veremos un ejemplo "a mano":

cd packages
mkdir myFirstPackage
cd myFirstPackage
npm init -y

ahora si volvemos a la carpeta raiz y ejecutamos el siguiente comando:

lerna list

Esto nos deberia mostrar lo siguiente:

lerna notice cli v4.0.0
myfirstpackage
lerna success found 1 package

Y ahora vamos a mirar las opciones que nos permite el commando lerna create:

lerna create --help

Vemos que por ahora nos interesa lo siguiente de la opcion create:

  • name: nombre del paquete que vamos a crear.
  • --yes: nos permite omitir la pregunta de confirmacion.

Por ahora vamos a omitir la opcion de loc ya que utilizaremos la primera configuracion de paquetes en lerna.json.

lerna create mySecondPackage -y

Veremos que este comando nos crea scaffolding basicos para nuestro paquete con tests

ahora vamos a ver cuantos paquetes nos detecta lerna:

lerna list
lerna notice cli v4.0.0
myfirstpackage
mySecondPackage
lerna success found 2 packages
  1. Agregar bundlers

Para hacerlo mas real vamos agregar unos bundlers a nuestros paquetes.

En mi caso voy a utilizar rollup y vite. Pero sois libres de utilizar cualquier otro bundler que vosotros quieras.

Aprovecharemos y utilizaremos el siguiente comando para a;adir dependencias a varios paquetes a la vez:

lerna add typescript --dev

y veremos como lo ha a;adido a varios paquetes:

info cli using local version of lerna
lerna notice cli v4.0.0
lerna info Adding typescript in 1 package
lerna info Bootstrapping 2 packages
lerna info Installing external dependencies
lerna info Symlinking packages and binaries
lerna success Bootstrapped 2 packages

Por otro lado a;adiremos el rollap en myFirstPackage junto con algunos paquetes que necesitaremos:

cd packages/myFirstPackage
npm install --save-dev rollup @rollup/plugin-typescript @rollup/plugin-commonjs

Ahora vamos los ficheros de configuracion necesarios para que typescript y rollup funcionen:

  • Creamos tsconfig.json con lo siguiente:
{
  "compilerOptions": {
    "declaration": true,
    "module": "esnext",
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "sourceMap": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "outDir": "./dist"
  },
  "exclude": ["dist", "node_modules"],
  "include": ["src/**/*"]
}
  • Creamos rollup.config.js con lo siguiente:
import typescript from "@rollup/plugin-typescript";
import commonjs from "@rollup/plugin-commonjs";
 
export default {
  input: "src/index.ts",
  output: {
    sourcemap: true,
    dir: "dist",
    format: "cjs",
  },
  plugins: [commonjs(), typescript()],
};

Como vereis nos sigue faltando el propio codigo! sino no tenemos nada del que hacer el bundle!

Crearemos un fichero src/index.ts con lo siguiente:

export function Hello(name: string) {
  console.log(`Hello Mr: ${name}`);
}

No podemos olvidarnos de actualizar el package.json para que lanze el comando esperado!

 "scripts": {
   "build": "rollup -c"
 }

Y sinceramente, esto no esta mal (quien no se siente orgulloso de lo que hace) pero nosotros queremos que lerna nos facilite el trabajo. Os imaginais tirar este comando por cada uno de los paquetes? seria un infierno!

Para solucionar esto, lerna nos permite lanzar un commando especial que nos facilitara el trabajo. A;adiremos lo siguiente en los scripts de nuestro package.json principal:

"build": "lerna run build"

Esto nos permitira que lerna nos ayude a hacer el bundle de todos nuestros paquetes! Y con una facilidad, si el commando no existe en X paquete, no lo ejecuta tal como vemos en la ejecucion del comando.

lerna notice cli v4.0.0
lerna info Executing command in 1 package: "npm run build"
lerna info run Ran npm script 'build' in 'myfirstpackage' in 0.8s:
 
> [email protected] build
> rollup -c
 
lerna success run Ran npm script 'build' in 1 package in 0.8s:
lerna success - myfirstpackage

Ahora vamos a repetir el mismo proceso para nuestro segundo paquete, pero en este caso vamos a probar otro bundler, y por que no, otros commandos de lerna (para verlos):

lerna add vite --dev --scope=mySecondPackage
cd packages/mySecondPackage
npm i --save react react-dom
npm i --save-dev @types/node @types/react @types/react-dom @vitejs/plugin-react vite-plugin-dts

Ahora vamos los ficheros de configuracion necesarios para que typescript y rollup funcionen:

  • Creamos tsconfig.json con lo siguiente:
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"]
}
  • Creamos vite.config.ts con lo siguiente:
import react from "@vitejs/plugin-react";
import * as path from "node:path";
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";
 
export default defineConfig({
  plugins: [
    react(),
    dts({
      insertTypesEntry: true,
    }),
  ],
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.tsx"),
      name: "index",
      formats: ["umd"],
      fileName: () => `index.js`,
    },
    rollupOptions: {
      external: ["react", "react-dom"],
      output: {
        globals: {
          react: "React",
          "react-dom": "ReactDOM",
        },
      },
    },
  },
});

Como veis le hemos explicado a vite que nos ponga ciertas dependencias como externas, esto es xk queremos exprimir al maximo el peso de nuestros componentes (si, vite utiliza rollup por debajo, si no me equivoco y esbuild para trabajar, podriamos decir que coje lo mejor de cada casa!)

Eliminaremos la carpeta que nos creo lerna de lib y crearemos una carpeta src con el fichero index.tsx con un componente basico de react:

export function Counter() {
  return <div>hello world</div>
}

Y como siempre a;adimos el commando esperado en nuestro package.json:

"build": "tsc && vite build"

y con esto vemos como nos compila vite nuestro paquete!

vite v2.9.8 building for production...
✓ 9 modules transformed.
dist/my-lib.es.js   1.35 KiB / gzip: 0.69 KiB
dist/my-lib.umd.js   1.35 KiB / gzip: 0.78 KiB

Y por ultimo para terminar de pulir nuestros paques vamos a a;adir/cambiar estas definiciones del package.json

  "main": "dist/{nombreDelPaquete}.js",
  "types": "dist/{nombreDelPaquete}.d.ts",
  "files": [
    "dist",
    "src"
  ],
  1. Probando nuestros paquetes

Ahora que ya tenemos nuestros paquetes creados vamos a probarlos para ver que todo funciona como esperamos. Para ello vamos a crear con vite un proyecto llamado testsite donde vamos a probar nuestros paquetes.

npm create vite@latest testsite -- --template react-ts

Y ahora, mientras no tengamos los paquetes publicados vamos a a;adirlos de manera local, para ello ejecutaremos lo siguiente:

cd testsite
npm i
npm i --save ../packages/myFirstPackage ../packages/mySecondPackage

con esto deberiamos de ver nuestros paquetes a;adidos en las dependencias de nuestro proyecto:

"myfirstpackage": "file:../packages/myFirstPackage",
"mySecondPackage": "file:../packages/mySecondPackage",

Y por ultimo como hemos puestos nuestros paquetes como umd (a vite no le molan), los a;adiremos en la config de vite

...
optimizeDeps: {
  include: ["myfirstpackage", "mySecondPackage"],
},
...

y con esto podremos utilizarlos tranquilamente en nuestra App.tsx:

import { Counter } from "mySecondPackage";
import { Hello } from "myfirstpackage";
 
function App() {
  const [count, setCount] = useState(0);
 
  Hello(count.toString());
 
  return (
    <div className="App">
      <Counter />
      <header className="App-header">
  1. Bootstrap

Ahora empezaremos a liarnos con instalacion de paquetes y linkearlos entre ellos.

Para hacer un ejemplo rapido vamos a ejecutar el siguiente comando

lerna add myfirstpackage --scope=mySecondPackage

Aunque no sea el susodicho (bootstrap) podemos ver que se ejecuta automaticamente ya que lo reconoce como paquete ya que nos ha puesto la version actual en el package.json peeeeero, si no vamos a node_modules veremos que lerna lo a detectado como un paquete nuestro y por lo tanto es un symlink

  1. Hoist

Otra cosa buena con la que nos permite jugar lerna es con el tema del hoisting. Es una sencilla opcion (pero hay que tratarla con cuidado) que nos permite instalar las dependencias de una vez en vez de scoped por asi decirlo.

Para ello vamos a modificar el archivo lerna.json y vamos a;adir la siguiente opcion

"hoist": true,

Tambien vamos a borrar las carpetas node_modules y los ficheros -lock.json, a partir de ahora vamos a dejar a lerna ocuparse de las dependencias

y una vez modificado el fichero y borrada la carpeta de node_modules vamos a lanzar el comando en la carpeta raiz

lerna bootstrap

esta nos deberia resultar en lo siguiente:

info cli using local version of lerna
lerna notice cli v4.0.0
lerna info Bootstrapping 2 packages
lerna info Installing external dependencies
lerna info hoist Installing hoisted dependencies into root
lerna info hoist Pruning hoisted dependencies
lerna info hoist Finished pruning hoisted dependencies
lerna info hoist Finished bootstrapping root
lerna info Symlinking packages and binaries
lerna success Bootstrapped 2 packages

Si ejecutamos nuestro comando de build veremos que todo sigue funcionando correctamente:

npm run build

y para terminar de confirmar que funciona correctamente ejecutaremos nuestro test site:

cd testsite
npm run dev
  1. Testing

Ahora que ya tenemos nuestros componentes linkeados, vemos que todo funciona y encima no reinstalamos dependencias a lo loco. Todo va de lujooooo. Pero eh!? nos falta testear! para ello vamos a utilizar a nuestro amigo Jest para facilitarnos la tarea, para ello instalaremos lo siguiente en el root:

npm i --save-dev jest ts-jest jest-environment-jsdom @types/jest @testing-library/react @testing-library/jest-dom
npx ts-jest config:init

esta configuracion inicial no esta mal pero necesitaremos modificarla un poco:

/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  setupFilesAfterEnv: ["@testing-library/jest-dom/extend-expect"],
  globals: {
    "ts-jest": {
      tsconfig: "<rootDir>/packages/mySecondPackage/tsconfig.json",
    },
  },
};

POR FAVOR crear un tsconfig a nivel de solucion y extender los paquetes de ese para entornos reales!

Modificamos el fichero package.json para que ejecute los tests a;adiendo el siguiente commando:

"test": "jest",

Y con esto nos vamos a packages/mySecondPackage/__tests__, recordar que esto ya nos lo creo lerna y renombramos el fichero que tenemos por *.tsx

A;adimos lo siguiente:

import { render, screen } from "@testing-library/react";
 
import { Counter } from "../src/index";
 
describe("<Counter />", () => {
  test("should display a hello world", async () => {
    render(<Counter />);
 
    expect(screen.getByText(/hello world/i)).toBeInTheDocument();
  });
});

y ahora si que si tenemos los tests funcionando!

npm test
 
> test
> jest
 
 PASS  packages/mySecondPackage/__tests__/mySecondPackage.test.tsx
  <Counter />
    ✓ should display a hello world (13 ms)
 
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.425 s, estimated 2 s
Ran all test suites.
  1. Storybook

Vamos a a;adir la herramienta storybook que nos permitira mostrar lo chulo que son nuestros componentes, para ello vamos a ejecutar lo siguiente, dentro de una nueva carpeta llamada storybook, por que en otra y no en raiz? Pues porque al hacer hoist, nuestra dependencia de react-dom difiere de la necesaria por @storybook/react (https://github.com/storybookjs/storybook/blob/088ab2a96a799713098cee808e3c05a0d1484c49/app/react/package.json#L82) y esto nos puede causar problemas

npm i --save-dev vite
npx sb init --builder storybook-builder-vite
y
react

Nos creara una carpeta de stories, la borramos, y nos dirijimos a ./storybook/main.js y cambiamos donde busca las stories por lo siguiente:

"../../packages/**/*.stories.mdx",
"../../packages/**/*.stories.@(js|jsx|ts|tsx)"

Crear una story dentro de mySecondPackage/stories/mySecondPackage.story.tsx con

import { ComponentMeta, ComponentStoryObj } from "@storybook/react";
import { Counter } from "../src/index";
 
const meta: ComponentMeta<typeof Counter> = {
  title: "Design System/MyButton",
  component: Counter,
};
export default meta;
 
export const Primary: ComponentStoryObj<typeof Counter> = {};

El linter nos dira que no puede encontrar "@storybook/react" , podemos instalarlo en dev si asi lo queremos para que no nos escupa pero la ejecucion funcionara correctamente sin problemas.

para ello nos iremos a la carpeta de storybook y ejecutaremos

npm run storybook

y con esto ya tendremos nuestro div con hello world!

  1. Versionado de lerna

En lerna tenemos varios modos de versionar, o todos juntos de la mano (ej: proyecto de firebase) o cada paquete por separado.

Para probarlo vamos a lanzar el comando de lerna para versionar (tener en cuenta que si detecta cambios en ficheros no indicados a ignorar no nos dejara hacer commit):

lerna version

Este comando nos preguntara que version queremos poner (como en lerna.json tiene especificado el 0.0.0), patch, minor, major. en nuestro caso vamos a empezar con un patch.

Acto seguido nos ense;ara los paquetes que va a modificar y si queremos hacerlo, en nuestro caso decimos que si

Como vemos nos ha modificado los package.json con la version esperada, tanto los package.json como las dependencias.

En este caso estamos usando el versionado general, es decir da igual si modificamos 1 que mil, todos subiran de version. para verlo, vamos a cambiar algo de mySecondPackage, myFirstPackage no tiene dependencias por lo tanto no subira, pero al hacer un versionado general, cambiara.

Nos vamos a mySecondPackage y modificamos algo dentro del index.tsx, hacemos commit de los cambios y lanzamos lerna version:

info cli using local version of lerna
lerna notice cli v4.0.0
lerna info current version 0.0.1
lerna info Looking for changed packages since v0.0.1
? Select a new version (currently 0.0.1) Patch (0.0.2)
 
Changes:
 - myfirstpackage: 0.0.1 => 0.0.2
 - mySecondPackage: 0.0.1 => 0.0.2
 
? Are you sure you want to create these versions? (ynH)

como vemos nos ha modificados todos da igual que haya sido modificado o no

esto puede ser cambiado especificando el flag independent en lerna.json

para ello vamos a lerna.json y cambiamos el version de 0.0.2 a independent.

Y lo mismo, nos vamos a mySecondPackage, volvemos a cambiar algo, commit y lerna build

lerna notice cli v4.0.0
lerna info versioning independent
lerna info Looking for changed packages since v0.0.2
? Select a new version for mySecondPackage (currently 0.0.2) Patch (0.0.3)
 
Changes:
 - mySecondPackage: 0.0.2 => 0.0.3
 
? Are you sure you want to create these versions? (ynH) 

Como vemos solo hace cambios en el paquete "esperado", esto va a question de gustos, la que mas rabia os de!

Ahora vamos a por el siguiente y vamos a probar los conventional-commits!

(despues de la explicacion de ellos, ejecutaremos)

lerna version  --conventional-commits

RAW Paste Data

canariasjs-lerna-workshop

Introducción

Texto de introducción

Proyecto que vamos a montar

En este proyecto vamos a montar un proyecto de tipo lerna. El cual nos permitirá tener una estructura de proyecto monorepo, donde podremos tener varios repositorios independientes, y de paso, una estructura de dependencias entre ellos, si llega a ser necesario.

Despues veremos como podemos interacturar con lerna mediante los distintos comandos que nos ofrece. Asi como interactur entre los distintos paquetes.

Tambien veremos que no sera necesario utilizar un unico bundler, ya que podremos utilizar uno por cada proyecto.

1 Init Repo!


Primero de todo lo instalaremos globalmente en nuestro npm (o yarn)

npm install --global lerna

Luego crearemos una carpeta donde vamos a montar nuestro proyecto.

mkdir lerna-workshop

Luego iniciaremos lerna con el siguiente commando:

lerna init

Por ultimo a;adiremos un gitignore bastante basico:

touch .gitignore

Y a;adiremos lo siguiente en dicho gitignore:

node_modules
dist

Esto nos deberia crear la sigueinte estructura:

lerna-repo/
  packages/
  package.json
  .gitignore
  lerna.json
  1. Entendiendo la configuracion de lerna

Si entramos a lerna.json veremos que nos ha creado un sencillo fichero de configuracion

{
  "packages": ["packages/*"],
  "version": "0.0.0"
}

Esta configuracion ha sido creada por defecto.

  • Packages: nos indica las carpetas que contienen los paquetes que vamos a montar.
  • Version: nos indica la version actual de lerna con la que va a comparar para realizar las actualizaciones.

Por otro lado, merece la pena indicar que podemos cambiar la forma de inicializar lerna, pero no lo haremos, de otra manera mediante: lerna init -i el cual nos permite inicializar la configuracion pero con el versionado independiente de cada paquete en vez de un verisonado "centralizado". Tambien vale la pena especificar que se puede cambiar esto a gusto (que ya veremos mas adelante en el curso).

Para los usuarios de yarn, podeis cambiar el cliente predeterminado con el cual correr los commandos de lerna especificando la siguiente configuracion:

{
  ...
  "npmClient": "yarn"
  ...
}
  1. Crear nuestro primer paquete

En lerna tenemos varias opciones de agregar paquetes a nuestro proyecto:

  • Crear un paquete nuevo "a mano".
  • Utilizar los comandos de lerna para agregar paquetes.

Primero de todo veremos un ejemplo "a mano":

cd packages
mkdir myFirstPackage
cd myFirstPackage
npm init -y

ahora si volvemos a la carpeta raiz y ejecutamos el siguiente comando:

lerna list

Esto nos deberia mostrar lo siguiente:

lerna notice cli v4.0.0
myfirstpackage
lerna success found 1 package

Y ahora vamos a mirar las opciones que nos permite el commando lerna create:

lerna create --help

Vemos que por ahora nos interesa lo siguiente de la opcion create:

  • name: nombre del paquete que vamos a crear.
  • --yes: nos permite omitir la pregunta de confirmacion.

Por ahora vamos a omitir la opcion de loc ya que utilizaremos la primera configuracion de paquetes en lerna.json.

lerna create mySecondPackage -y

Veremos que este comando nos crea scaffolding basicos para nuestro paquete con tests

ahora vamos a ver cuantos paquetes nos detecta lerna:

lerna list
lerna notice cli v4.0.0
myfirstpackage
mySecondPackage
lerna success found 2 packages
  1. Agregar bundlers

Para hacerlo mas real vamos agregar unos bundlers a nuestros paquetes.

En mi caso voy a utilizar rollup y vite. Pero sois libres de utilizar cualquier otro bundler que vosotros quieras.

Aprovecharemos y utilizaremos el siguiente comando para a;adir dependencias a varios paquetes a la vez:

lerna add typescript --dev

y veremos como lo ha a;adido a varios paquetes:

info cli using local version of lerna
lerna notice cli v4.0.0
lerna info Adding typescript in 1 package
lerna info Bootstrapping 2 packages
lerna info Installing external dependencies
lerna info Symlinking packages and binaries
lerna success Bootstrapped 2 packages

Por otro lado a;adiremos el rollap en myFirstPackage junto con algunos paquetes que necesitaremos:

cd packages/myFirstPackage
npm install --save-dev rollup @rollup/plugin-typescript @rollup/plugin-commonjs

Ahora vamos los ficheros de configuracion necesarios para que typescript y rollup funcionen:

  • Creamos tsconfig.json con lo siguiente:
{
  "compilerOptions": {
    "declaration": true,
    "module": "esnext",
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "sourceMap": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "outDir": "./dist"
  },
  "exclude": ["dist", "node_modules"],
  "include": ["src/**/*"]
}
  • Creamos rollup.config.js con lo siguiente:
import typescript from "@rollup/plugin-typescript";
import commonjs from "@rollup/plugin-commonjs";

export default {
  input: "src/index.ts",
  output: {
    sourcemap: true,
    dir: "dist",
    format: "cjs",
  },
  plugins: [commonjs(), typescript()],
};

Como vereis nos sigue faltando el propio codigo! sino no tenemos nada del que hacer el bundle!

Crearemos un fichero src/index.ts con lo siguiente:

export function Hello(name: string) {
  console.log(`Hello Mr: ${name}`);
}

No podemos olvidarnos de actualizar el package.json para que lanze el comando esperado!

 "scripts": {
   "build": "rollup -c"
 }

Y sinceramente, esto no esta mal (quien no se siente orgulloso de lo que hace) pero nosotros queremos que lerna nos facilite el trabajo. Os imaginais tirar este comando por cada uno de los paquetes? seria un infierno!

Para solucionar esto, lerna nos permite lanzar un commando especial que nos facilitara el trabajo. A;adiremos lo siguiente en los scripts de nuestro package.json principal:

"build": "lerna run build"

Esto nos permitira que lerna nos ayude a hacer el bundle de todos nuestros paquetes! Y con una facilidad, si el commando no existe en X paquete, no lo ejecuta tal como vemos en la ejecucion del comando.

lerna notice cli v4.0.0
lerna info Executing command in 1 package: "npm run build"
lerna info run Ran npm script 'build' in 'myfirstpackage' in 0.8s:

> [email protected] build
> rollup -c

lerna success run Ran npm script 'build' in 1 package in 0.8s:
lerna success - myfirstpackage

Ahora vamos a repetir el mismo proceso para nuestro segundo paquete, pero en este caso vamos a probar otro bundler, y por que no, otros commandos de lerna (para verlos):

lerna add vite --dev --scope=mySecondPackage
cd packages/mySecondPackage
npm i --save react react-dom
npm i --save-dev @types/node @types/react @types/react-dom @vitejs/plugin-react vite-plugin-dts

Ahora vamos los ficheros de configuracion necesarios para que typescript y rollup funcionen:

  • Creamos tsconfig.json con lo siguiente:
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"]
}
  • Creamos vite.config.ts con lo siguiente:
import react from "@vitejs/plugin-react";
import * as path from "node:path";
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";

export default defineConfig({
  plugins: [
    react(),
    dts({
      insertTypesEntry: true,
    }),
  ],
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.tsx"),
      name: "index",
      formats: ["umd"],
      fileName: () => `index.js`,
    },
    rollupOptions: {
      external: ["react", "react-dom"],
      output: {
        globals: {
          react: "React",
          "react-dom": "ReactDOM",
        },
      },
    },
  },
});

Como veis le hemos explicado a vite que nos ponga ciertas dependencias como externas, esto es xk queremos exprimir al maximo el peso de nuestros componentes (si, vite utiliza rollup por debajo, si no me equivoco y esbuild para trabajar, podriamos decir que coje lo mejor de cada casa!)

Eliminaremos la carpeta que nos creo lerna de lib y crearemos una carpeta src con el fichero index.tsx con un componente basico de react:

export function Counter() {
  return <div>hello world</div>
}

Y como siempre a;adimos el commando esperado en nuestro package.json:

"build": "tsc && vite build"

y con esto vemos como nos compila vite nuestro paquete!

vite v2.9.8 building for production...
✓ 9 modules transformed.
dist/my-lib.es.js   1.35 KiB / gzip: 0.69 KiB
dist/my-lib.umd.js   1.35 KiB / gzip: 0.78 KiB

Y por ultimo para terminar de pulir nuestros paques vamos a a;adir/cambiar estas definiciones del package.json

  "main": "dist/{nombreDelPaquete}.js",
  "types": "dist/{nombreDelPaquete}.d.ts",
  "files": [
    "dist",
    "src"
  ],
  1. Probando nuestros paquetes

Ahora que ya tenemos nuestros paquetes creados vamos a probarlos para ver que todo funciona como esperamos. Para ello vamos a crear con vite un proyecto llamado testsite donde vamos a probar nuestros paquetes.

npm create vite@latest testsite -- --template react-ts

Y ahora, mientras no tengamos los paquetes publicados vamos a a;adirlos de manera local, para ello ejecutaremos lo siguiente:

cd testsite
npm i
npm i --save ../packages/myFirstPackage ../packages/mySecondPackage

con esto deberiamos de ver nuestros paquetes a;adidos en las dependencias de nuestro proyecto:

"myfirstpackage": "file:../packages/myFirstPackage",
"mySecondPackage": "file:../packages/mySecondPackage",

Y por ultimo como hemos puestos nuestros paquetes como umd (a vite no le molan), los a;adiremos en la config de vite

...
optimizeDeps: {
  include: ["myfirstpackage", "mySecondPackage"],
},
...

y con esto podremos utilizarlos tranquilamente en nuestra App.tsx:

import { Counter } from "mySecondPackage";
import { Hello } from "myfirstpackage";

function App() {
  const [count, setCount] = useState(0);

  Hello(count.toString());

  return (
    <div className="App">
      <Counter />
      <header className="App-header">
  1. Bootstrap

Ahora empezaremos a liarnos con instalacion de paquetes y linkearlos entre ellos.

Para hacer un ejemplo rapido vamos a ejecutar el siguiente comando

lerna add myfirstpackage --scope=mySecondPackage

Aunque no sea el susodicho (bootstrap) podemos ver que se ejecuta automaticamente ya que lo reconoce como paquete ya que nos ha puesto la version actual en el package.json peeeeero, si no vamos a node_modules veremos que lerna lo a detectado como un paquete nuestro y por lo tanto es un symlink

  1. Hoist

Otra cosa buena con la que nos permite jugar lerna es con el tema del hoisting. Es una sencilla opcion (pero hay que tratarla con cuidado) que nos permite instalar las dependencias de una vez en vez de scoped por asi decirlo.

Para ello vamos a modificar el archivo lerna.json y vamos a;adir la siguiente opcion

"hoist": true,

Tambien vamos a borrar las carpetas node_modules y los ficheros -lock.json, a partir de ahora vamos a dejar a lerna ocuparse de las dependencias

y una vez modificado el fichero y borrada la carpeta de node_modules vamos a lanzar el comando en la carpeta raiz

lerna bootstrap

esta nos deberia resultar en lo siguiente:

info cli using local version of lerna
lerna notice cli v4.0.0
lerna info Bootstrapping 2 packages
lerna info Installing external dependencies
lerna info hoist Installing hoisted dependencies into root
lerna info hoist Pruning hoisted dependencies
lerna info hoist Finished pruning hoisted dependencies
lerna info hoist Finished bootstrapping root
lerna info Symlinking packages and binaries
lerna success Bootstrapped 2 packages

Si ejecutamos nuestro comando de build veremos que todo sigue funcionando correctamente:

npm run build

y para terminar de confirmar que funciona correctamente ejecutaremos nuestro test site:

cd testsite
npm run dev
  1. Testing

Ahora que ya tenemos nuestros componentes linkeados, vemos que todo funciona y encima no reinstalamos dependencias a lo loco. Todo va de lujooooo. Pero eh!? nos falta testear! para ello vamos a utilizar a nuestro amigo Jest para facilitarnos la tarea, para ello instalaremos lo siguiente en el root:

npm i --save-dev jest ts-jest jest-environment-jsdom @types/jest @testing-library/react @testing-library/jest-dom
npx ts-jest config:init

esta configuracion inicial no esta mal pero necesitaremos modificarla un poco:

/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  setupFilesAfterEnv: ["@testing-library/jest-dom/extend-expect"],
  globals: {
    "ts-jest": {
      tsconfig: "<rootDir>/packages/mySecondPackage/tsconfig.json",
    },
  },
};

POR FAVOR crear un tsconfig a nivel de solucion y extender los paquetes de ese para entornos reales!

Modificamos el fichero package.json para que ejecute los tests a;adiendo el siguiente commando:

"test": "jest",

Y con esto nos vamos a packages/mySecondPackage/__tests__, recordar que esto ya nos lo creo lerna y renombramos el fichero que tenemos por *.tsx

A;adimos lo siguiente:

import { render, screen } from "@testing-library/react";

import { Counter } from "../src/index";

describe("<Counter />", () => {
  test("should display a hello world", async () => {
    render(<Counter />);

    expect(screen.getByText(/hello world/i)).toBeInTheDocument();
  });
});

y ahora si que si tenemos los tests funcionando!

npm test

> test
> jest

 PASS  packages/mySecondPackage/__tests__/mySecondPackage.test.tsx
  <Counter />
    ✓ should display a hello world (13 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.425 s, estimated 2 s
Ran all test suites.
  1. Storybook

Vamos a a;adir la herramienta storybook que nos permitira mostrar lo chulo que son nuestros componentes, para ello vamos a ejecutar lo siguiente, dentro de una nueva carpeta llamada storybook, por que en otra y no en raiz? Pues porque al hacer hoist, nuestra dependencia de react-dom difiere de la necesaria por @storybook/react (https://github.com/storybookjs/storybook/blob/088ab2a96a799713098cee808e3c05a0d1484c49/app/react/package.json#L82) y esto nos puede causar problemas

npm i --save-dev vite
npx sb init --builder storybook-builder-vite
y
react

Nos creara una carpeta de stories, la borramos, y nos dirijimos a ./storybook/main.js y cambiamos donde busca las stories por lo siguiente:

"../../packages/**/*.stories.mdx",
"../../packages/**/*.stories.@(js|jsx|ts|tsx)"

Crear una story dentro de mySecondPackage/stories/mySecondPackage.story.tsx con

import { ComponentMeta, ComponentStoryObj } from "@storybook/react";
import { Counter } from "../src/index";

const meta: ComponentMeta<typeof Counter> = {
  title: "Design System/MyButton",
  component: Counter,
};
export default meta;

export const Primary: ComponentStoryObj<typeof Counter> = {};

El linter nos dira que no puede encontrar "@storybook/react" , podemos instalarlo en dev si asi lo queremos para que no nos escupa pero la ejecucion funcionara correctamente sin problemas.

para ello nos iremos a la carpeta de storybook y ejecutaremos

npm run storybook

y con esto ya tendremos nuestro div con hello world!

  1. Versionado de lerna

En lerna tenemos varios modos de versionar, o todos juntos de la mano (ej: proyecto de firebase) o cada paquete por separado.

Para probarlo vamos a lanzar el comando de lerna para versionar (tener en cuenta que si detecta cambios en ficheros no indicados a ignorar no nos dejara hacer commit):

lerna version

Este comando nos preguntara que version queremos poner (como en lerna.json tiene especificado el 0.0.0), patch, minor, major. en nuestro caso vamos a empezar con un patch.

Acto seguido nos ense;ara los paquetes que va a modificar y si queremos hacerlo, en nuestro caso decimos que si

Como vemos nos ha modificado los package.json con la version esperada, tanto los package.json como las dependencias.

En este caso estamos usando el versionado general, es decir da igual si modificamos 1 que mil, todos subiran de version. para verlo, vamos a cambiar algo de mySecondPackage, myFirstPackage no tiene dependencias por lo tanto no subira, pero al hacer un versionado general, cambiara.

Nos vamos a mySecondPackage y modificamos algo dentro del index.tsx, hacemos commit de los cambios y lanzamos lerna version:

info cli using local version of lerna
lerna notice cli v4.0.0
lerna info current version 0.0.1
lerna info Looking for changed packages since v0.0.1
? Select a new version (currently 0.0.1) Patch (0.0.2)

Changes:
 - myfirstpackage: 0.0.1 => 0.0.2
 - mySecondPackage: 0.0.1 => 0.0.2

? Are you sure you want to create these versions? (ynH)

como vemos nos ha modificados todos da igual que haya sido modificado o no

esto puede ser cambiado especificando el flag independent en lerna.json

para ello vamos a lerna.json y cambiamos el version de 0.0.2 a independent.

Y lo mismo, nos vamos a mySecondPackage, volvemos a cambiar algo, commit y lerna build

lerna notice cli v4.0.0
lerna info versioning independent
lerna info Looking for changed packages since v0.0.2
? Select a new version for mySecondPackage (currently 0.0.2) Patch (0.0.3)

Changes:
 - mySecondPackage: 0.0.2 => 0.0.3

? Are you sure you want to create these versions? (ynH) 

Como vemos solo hace cambios en el paquete "esperado", esto va a question de gustos, la que mas rabia os de!

Ahora vamos a por el siguiente y vamos a probar los conventional-commits!

(despues de la explicacion de ellos, ejecutaremos)

lerna version  --conventional-commits

Public Pastes Paste Ping C | 22 min ago | 0.02 KB Babeeva Julia-06.05.22-Найбільше число(Цикл) JavaScript | 42 min ago | 0.46 KB Nigerian scammers 6-5-1/2022 HTML | 1 hour ago | 59.78 KB Emoji game with renew list Python | 1 hour ago | 2.51 KB LearnDash Nested Lesson URLs #2 PHP | 1 hour ago | 4.48 KB MaterialScript C++ | 1 hour ago | 5.79 KB plane Python | 1 hour ago | 7.83 KB Untitled Bash | 1 hour ago | 10.25 KB create new paste / syntax languages / archive / faq / tools / night mode / api / scraping api / news / pro privacy statement / cookies policy / terms of serviceupdated / security disclosure / dmca / report abuse / contact

By using Pastebin.com you agree to our cookies policy to enhance your experience. Site design & logo © 2022 Pastebin We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand Not a member of Pastebin yet? Sign Up, it unlocks many cool features!

canariasjs-workshop-lerna's People

Contributors

ayozedkt avatar

Watchers

Ayoze Martín Hdernández avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.