Problema monorepo cu vite si vanilla-extract

Incerc sa mut un proiect pe structura de monorepo dar intampin niste erori, am deschis un issue aici Unable to use vanilla-extract in a monorepo setup · Issue #1111 · vanilla-extract-css/vanilla-extract · GitHub
iar aici am minimal reproduction in caz ca vrea sa arunce cineva o privire GitHub - cojoclaudiu/vite-vanilla-extract-monorepo

Pentru monorepo foloseste Nx sau Turborepo.

Eu cred ca la plugins conteaza ordinea.

Fisierul de svg.d.ts parca intra la “files”: [] in tsconfig, nu in include.

1 Like

@isti37 mersi de raspun. am in plan sa folosesc lerna cu nx dar deocamdata vreau sa-l fac sa mearge cu workspaces (banuiesc ca daca nu o sa mearga cu workspaces nu o sa mearga nici cu nx sau turborepo).
am incercat sa schimb si ordinea la plugins si tot nu merge.

Una din cauze sau cel putin asa cred eu, apare atunci cand in packages/utils (@mono/utils) este importat .svg iar din @mono/utils importat in App.tsx

In legatura cu d.ts file era in folder-ul de icons dar am zis sa o mut global (am sa vad daca conteaza ca este in files sau in include) dar deocamdata cred ca e irelevanta deoarce eroarea nu porneste de acolo.

PS: tin sa precizez ca daca functia care o folosesc in acel demo nu este in packages/utils ci in src/utils atunci totul functioneaza cum trebuie

Cred ca am descoperit inca una din probleme, cred ca este din cauza acestui folder src

export * from "./src/getIcon";
export * from "./src/hexToRGBA";

Plugin-ul pt. vite de la vanilla-extract foloseste intern esbuild care nu are loader pt. .svg files.

Problema nu este de la plugin-ul de vanilla extract, este de la modul in care importi hexToRGBA in src/styles.css.ts.

  • import { hexToRGBA } from "@mono/utils" ← does not work
  • import { hexToRGBA } from "@mono/utils/src/hexToRGBA" ← it works

Prima versiune nu functioneaza pt. ca in @mono/utils/index.ts faci import la src/getIcon care importa ../../../src/icons/svg.

Intern vanilla extract transforma fisierele *.css.ts in CSS chunks, nu face tree-shake la imports, daca la asta te asteptai.

As recomanda sa folosesti pnpm in loc de yarn.

2 Likes

@navaru am sa iau in cosiderare pnpm dar vreau sa fac aceasta schimbare treptat si dupa posibil sa mut si pe pnpm si lerna cu ceva tool-uri de la nx.

problema la mine era cea a importului, pentru ca primeam acea eroare cu .svg
cred ca tu ai dreptate cu ce zici sa le import de aici import { hexToRGBA } from "@mono/utils/src/hexToRGBA" sincer nu am incercat, dar am sa verific in curand.

acum imi dau seama ca din cauza acelei functii din index.ts care are importat .svg se strica totul.

multumesc

1 Like

@navaru de ce pnpm si nu yarn? este asa mare diferenta? poti sa-mi spui care ar fi avantajele si dezavantajele?

Pnpm e foarte simplu, nu iti trebuie workspaces.
Cand rulezi pnpm install o sa se duca recursiv in fiecare folder si unde gaseste un package.json o sa descarce pe user (global) tot ce este necesar si face symlink la node_modules. (comenzile de pnpm run -r x si pnpm install sunt recursive)

E si foarte rapid.

Daca folosesti nx de exemplu nu mai ai nevoie de workspaces, se ocupa nx de build-uirea dependintelor intre librarii/aplicatii. Iar daca vrei neaparat workspaces in package.json (ceea ce poate conduce foarte usor la dependinte circulare, poti folosi foarte simplu workspace:*)

1 Like

Ideea e sa schimb oarecum spre workspaces dar nu vreau sa folosesc doar workspaces.

nx foloseste lerna pentru monorepo?

eu ma gandeam sa adaug doar lerna cu tool-ul pentru dependency tree (nu stiu exact cum se numeste) .

(cred ca incepusem un proiect cu nx si nu mi-a placut din cauza ca era prea mult boilerplate si cred ca erau destul de multe dependencies instalate by default)

am zis sa impart prima data aplciatia in packages fara external dependencies din cauza erorilor care pot aparea pe parcurs.

stiu ca si pnpm este oarecum pe hype si din ce in ce mai folosit, dar si acolo sunt poate alte setari care trebuie facute ca sa-l faci sa mearga si de aceea am ramas cu yarn.

ai facut tranzitie de la yarn la pnpm? cum a fost?

in principu vreau sa iau toate lucrurile pe rand ca sa nu ma impotmolesc in erori si circular dependencies. este prima data cand fac o tranzitie de genul si am momente cand ma simt overwhelmed. proiectul este deja in productie iar unele pachete logica si componente (cel mai probabil unstyled o sa fie refolosite).

m-am documentat cat de mult am putut pe partea de monorepo, dar este diferit in practica mai ales cand proiectul deja exista.

chiar astept sfaturi daca sunteti familiari, am sa tin cont de ele dar am sa incerc sa le implementez pe rand.

multumesc mult

Lerna === nx, doar ca Lerna era la baza un tool ca sa combini mai multe repo-uri intr-un singur repo.

Intr-adevar nx e complex, dar un monorepo de obicei nu e un one man job, e foarte complex.

Cand proiectul exista deja strategia e sa iei totul pe bucati si sa muti unul cate unul ori ca librarie ori ca aplicatie totul intr-un proiect nou. Dupa cum ai spus are mult boilerplate, dar are si comenzi (wizards) pentru a le genera automat. VSCode are o extensie cu formulare pentru Nx.

Ai mare grija la local development si la final build. Poti alege sa faci un shell in care importi direct pachetul build-uit din fiecare aplicatie (1 shell + 1 aplicatie sau mai multe) sau poti alege sa folosesti pur si simplu o aplicatie in care importi tot. (eu am facut greseala asta) Shell-ul de obicei este mai ok fiindca pentru local development sau in CI/CD vrei sa faci mai multe aplicatii ca sa nu ruleze build/tsc/lint/format/prettier pe tot proiectul deodata ca sa nu creasca timpul si resursele necesare exponential cu numarul de linii de cod…

Iar pentru CI/CD si build-ul complet poti folosi nx affected care va face build/test doar la ce s-a schimbat din monorepo, restul le ia din cache.

1 Like

Stiti cumva o rezolvare la problema cu ordinea importurilor?
Eu folosesc un plugin pentru eslint pentru import orders si am doua importuri care daca nu respecta o ordine aplicatia nu se mai incarca si primesc mesajul asta:
Uncaught ReferenceError: can't access lexical declaration ... before initialization

Pot sa ignor acele file sa nu se faca sort automat dar as vrea sa stiu daca exista si alte solutii in afara de asta

de exemplu

import App from ‘./App’;
import { persistor, store } from ‘@think/store’;

import { persistor, store } from '@think/store'; linia asta trebuie sa fie sub ./App

Ordinea importurilor nu conteaza daca nu folosesti require. Daca folosesti require importi direct codul, daca folosesti import * from x sau import {function} from ‘./x’ se importa doar ce iti trebuie.

La mine conteaza, nu stiu daca am circular dependency, eu la asta ma gandeam

Nu ar trebui sa conteze, conteaza unde il folosesti daca e ceva array/obiect/hook/functie care trebuie sa fie intr-o anumita ordine. E posibil sa ai ceva optiune in tsconfig sau vite care converteste modulele.

Conteaza si ordinea cand sunt exportate asa din index.ts

export * from './src/api';
export * from './src/features';
export * from './src/selectors';
export * from './src/slices';
export * from './src/store';

Asta era inca o curiozitate de a mea, este ok sa le export asa in index.ts?

Depinde unde folosesti export *, nu folosi export * direct pe fisiere, foloseste export * from ‘./director’ in care ai un index.ts in care faci export {x } from ‘./x’

Dar daca conteaza ordinea ai ceva setare la TS/Vite care nu e ok, nu ar trebui sa conteze.

In cazul in care folosesti import default from ‘./x’ poti avea probleme fiindca nu il mai importi ca si modul.

cam asta am in tsconfig

{
	"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"
	},

	"paths": {
		"@think/*": ["packages/*/index.ts"]
	},

	"include": ["src", "globals.d.ts", "packages/**/*"],

	"references": [{ "path": "./tsconfig.node.json" }]
}

si asta in vite.config.ts

import { resolve } from 'path';
import { PluginOption, defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
import svgr from '@svgr/rollup';
import { injectScriptConfigPlugin } from './packages/utils/src/injectScriptConfigPlugin';
import { visualizer } from 'rollup-plugin-visualizer';

// https://vitejs.dev/config/
export default defineConfig({
	build: {
		rollupOptions: {
			input: {
				main: resolve(__dirname, 'index.html'),
				preview: resolve(__dirname, 'index.html'),
			},
		},
	},

	plugins: [
		react({
			jsxImportSource: '@welldone-software/why-did-you-render',
		}),
		vanillaExtractPlugin(),
		svgr(),

		visualizer({
			template: 'treemap', // or sunburst
			open: true,
			gzipSize: true,
			brotliSize: true,
			filename: 'analice.html',
		}) as PluginOption,

		injectScriptConfigPlugin(),
	],

	resolve: {
		alias: {
			// Needed for `useSelector` tracking in wdyr.tsx: https://github.com/welldone-software/why-did-you-render/issues/85
			'react-redux': 'react-redux/dist/react-redux.js',
		},
	},
});

TypeScript: TSConfig Reference - Docs on every TSConfig option (typescriptlang.org)

Dar in afara de esModuleInterop, cred ca ai un modul care are o dependinta care trebuie importata in modul. Doar ca iti merge fiindca in mod aleator import-ul care e necesar e importat mai inainte. Totusi nu inteleg de ce nu se plange IDE-ul sau tsc de asta.

Stiu ca am problema asta de ceva timp, dar nu am primit nici o eroare din IDE sau tsc.

@isti37 daca am
packages

  • components
    • package.json
{
	"name": "@mono/components",
	"version": "1.0.0",
	"main": "index.ts"
}

trebuie sa adaug si `“type”: “module”?
si trebuie sa ii adaug si dependintele?
eu as vreau sa am dependintele in root package.json si sa fie luat de acolo