Hvordan jeg endelig forstod forskellen på npm og npx

Hvordan jeg endelig forstod forskellen på npm og npx

Jeg sad en aften med en Vite-tutorial og tastede mekanisk npm create vite@latest ind. Terminalen svarede surt, tutorialen brugte pludselig npx i stedet, og jeg opdagede, at jeg egentlig ikke anede, hvad forskellen var. Jeg kopierede bare linjer og håbede det bedste.

Den her artikel er resultatet af de efterfølgende aftener, hvor jeg faktisk satte mig ned og undersøgte, hvad der sker, når man skriver npm vs npx. Ikke teoretisk, men sådan som det føles, når du bare prøver at få et projekt til at køre.

Hvad npm egentlig er

Hvis vi starter helt lavpraktisk, så er npm to ting på én gang:

  • En kommando i din terminal (npm)
  • Et online bibliotek (registry) med JavaScript/Node pakker

Når du skriver noget som:

npm install react

sker der groft sagt det her:

  • npm henter pakken react fra npm registry
  • den lægger koden i din node_modules mappe
  • den opdaterer din package.json og package-lock.json (hvis filerne findes)

Pointen: npm handler om at installere og styre afhængigheder i dit projekt.

npm som package manager

package.json er din “projekt-opsummering”. Her står blandt andet:

  • hvilke pakker du har installeret
  • hvilke versioner de bør have
  • hvilke scripts du kan køre med npm

Et meget simpelt eksempel:

{
  "name": "mit-projekt",
  "version": "1.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "dependencies": {
    "react": "^18.0.0"
  },
  "devDependencies": {
    "vite": "^5.0.0"
  }
}

Når du senere skriver:

npm install

kigger npm i din package.json og installerer det hele ned i node_modules. Det er derfor, man ikke bare kan slette mappen og håbe. Heldigvis kan du altid genskabe den ved at køre npm install igen.

Hvad npx er, og hvorfor det forvirrer

Så kommer npx. Første gang jeg så det, tænkte jeg bare: “fedt, endnu en forkortelse”.

npx er en måde at køre en pakke som et program uden at du nødvendigvis installerer den permanent først.

Eksempel:

npx create-vite@latest

Når du gør det, sker der typisk:

  • npx henter pakken create-vite (hvis du ikke har den i forvejen)
  • kører den som et kommando-værktøj (CLI)
  • smider den væk igen bagefter, eller bruger en cache

Du behøver altså ikke først:

npm install -g create-vite

for derefter at skrive:

create-vite

npx gør de to trin i én bevægelse.

npm vs npx i én sætning

  • npm: “jeg vil have denne pakke i mit projekt”
  • npx: “jeg vil køre denne pakke som et værktøj lige nu”

Det er også grunden til, at mange moderne tutorials bruger npx til “create” ting: du skal bare bruge værktøjet til at starte et projekt, ikke have det liggende fast.

6 kommandoer du sikkert har set i tutorials

Nu bliver det mere genkendeligt. Her er nogle linjer, jeg selv er stødt på i tutorials, og hvad de faktisk gør.

1. Vite projekt

Første version jeg så:

npm create vite@latest

På nyere npm versioner bliver det i praksis håndteret mere som npx, men det føles forvirrende, fordi det ser ud som en normal npm-kommando.

Mere gennemskuelig variant:

npx create-vite@latest

Her er det tydeligt: kør pakken create-vite som et værktøj én gang, lav et projekt, og videre.

2. ESLint

Installere ESLint i projektet:

npm install -D eslint

-D betyder --save-dev. Altså kun til udvikling, ikke produktion.

Starte konfiguration med npx:

npx eslint --init

Her bruger du npx til at køre ESLints “init”-kommando. Selve pakken ligger allerede i dine devDependencies, men npx sørger for at finde den lokale version og køre den.

3. Prettier

Installation:

npm install -D prettier

Køre Prettier direkte med npx:

npx prettier . --write

Det formaterer alle filer i projektet, alt efter hvordan du har sat din .prettierrc op.

Bedre i længden: læg det i et script:

{
  "scripts": {
    "format": "prettier . --write"
  }
}

og kør:

npm run format

Det gør dit projekt mindre afhængigt af, om du bruger npm, pnpm eller noget helt tredje.

4. TypeScript kompilering

Installation:

npm install -D typescript

Éngangskørsel med npx:

npx tsc --init

Det laver en tsconfig.json til dig.

Løbende brug som script:

{
  "scripts": {
    "build": "tsc"
  }
}

og så:

npm run build

5. Create React App (klassikeren)

Den gamle, men meget sete:

npx create-react-app my-app

Du beder npx om at hente create-react-app, køre den én gang, og så er det det.

Hvis du i stedet havde gjort:

npm install -g create-react-app
create-react-app my-app

så havde du en global installation, som hurtigt kan blive forældet i forhold til nye projekter.

6. Test-scripts

Mange testværktøjer installeres med npm, men køres via scripts:

npm install -D vitest
{
  "scripts": {
    "test": "vitest"
  }
}

og så:

npm test
# eller
npm run test

Her står du faktisk slet ikke og skriver npx, men under motorhjelmen bruger npm noget der minder om npx-logikken til at finde den lokale binær.

Lokalt vs globalt install – hvornår giver hvad mening?

Jeg har selv haft en periode, hvor alt blev installeret globalt, fordi det virkede “nemt”. Det var det ikke.

Lokale installationer

Standard-kommandoen:

npm install react

giver en lokal installation, der kun findes i det pågældende projekt. Fordele:

  • projektet kan genskabes på en anden maskine med npm install
  • forskellige projekter kan bruge forskellige versioner af samme pakke
  • nemt at se afhængighederne i package.json

Globale installationer

Globalt er når du skriver:

npm install -g some-cli

Nu kan du køre some-cli alle steder i din terminal.

Det kan give mening til værktøjer, du bruger hele tiden, f.eks.:

  • npm selv (kommer med Node)
  • nodemon (nogle vælger det globalt)

Men til projekt-specifikke værktøjer som Vite, ESLint, Prettier osv. er det næsten altid bedre at holde dem lokale og så bruge npx eller npm run.

Hvis du vil læse mere om forskellen på lokale og globale pakker, kan du senere dykke ned i andre artikler om Node og npm på Coding Class.

Hvordan package.json scripts hænger sammen med npm og npx

Scripts i package.json er lidt undervurderede. De er din chance for at slippe for lange terminalkommandoer og gøre ting mere stabile på tværs af maskiner.

Et eksempel:

{
  "scripts": {
    "dev": "vite",
    "lint": "eslint src --ext .js,.jsx,.ts,.tsx",
    "format": "prettier . --write"
  }
}

Nu kan du køre:

npm run dev
npm run lint
npm run format

Her slipper du helt for at skrive npx. npm sørger for at finde den lokale vite, eslint og prettier for dig.

Hvis du en dag skifter til en anden package manager (pnpm, yarn), kan du stadig bruge de samme scripts. Det gør dine tutorials og dokumentation mindre skrøbelige.

Hvis du lige er i gang med at lære scripts, kan en intro til Node.js og npm være et fint sidestep.

Typiske fejl med npm og npx

Nu til den del, der som regel faktisk sender mig på Google: fejlbeskederne.

“command not found” eller “is not recognized”

Hvis du skriver:

npm

og får noget i stil med “command not found” eller “is not recognized as an internal or external command”, så er den typiske årsag:

  • Node (og dermed npm) er ikke installeret
  • eller din PATH ikke peger på Node installationen

Løsning: installer Node fra nodejs.org. På Windows kan det også hjælpe at genstarte terminalen eller logge ud/ind.

“npx: installed X in Y seconds” og så ingenting

Nogle gange skriver npx at den har installeret noget, men der sker ikke rigtigt mere. Typiske årsager:

  • du har stavet pakken forkert
  • pakken har ikke en CLI-entry, der matcher det du forventer

Her kigger jeg næsten altid på npm-siden for pakken og ser, hvordan de selv skriver, den skal køres.

Version-mismatch

Et andet klassisk problem: du følger en tutorial, der bruger en anden Node/npm-version end dig. Pludselig virker npm create <et-eller-andet> ikke som i videoen.

Mit mønster er:

  • tjek Node version med node -v
  • tjek npm version med npm -v
  • overvej at skifte til en LTS-version, hvis du er på noget meget gammelt eller meget nyt

Hvis du begynder at arbejde mere med flere projekter, er et værktøj som nvm (Node Version Manager) faktisk rart at lære.

“Permission denied” på Linux/macOS

Hvis du får rettighedsfejl ved globale installationer, når du skriver:

npm install -g noget

så er det fristende bare at smide sudo foran. Det har jeg selv gjort. Det gav så nye problemer senere.

En sundere løsning er tit at:

  • undgå globale installs, hvor du kan bruge npx
  • sørge for at din npm-global-mappe ligger et sted, hvor din bruger har rettigheder

Mini-tjekliste til et “tooling-sundt” projekt

Jeg er begyndt at have sådan en lille mental tjekliste, når jeg starter eller arver et projekt. Den kunne se sådan her ud:

  • Findes der en package.json? Hvis nej, start med npm init -y.
  • Installer værktøjer (Vite, ESLint, Prettier, TypeScript) lokalt med npm install -D ....
  • Brug npx til én-gangs-kommandoer som --init eller “create”-scripts.
  • Lav scripts i package.json til ting du kører ofte: dev, build, test, lint, format.
  • Lad være med at installere CLI’er globalt, medmindre du har en virkelig god grund.
  • Gem node_modules i .gitignore, og stol på npm install i stedet.

Hvis du vil bygge videre herfra, er næste naturlige skridt at kigge på, hvordan du strukturerer dine projekter med Git og versionsstyring. Der er flere intro-artikler om Git-workflows på Coding Class, som spiller ret godt sammen med det, du lige har læst om npm og npx.

Mikkel Schrøder er den dér stille type, der i årevis har siddet om aftenen med en kop kaffe og et åbent kodeprojekt, mens resten af huset er ved at falde til ro. Hans interesse for kodning startede, da han som teenager forsøgte at lave en simpel hjemmeside til sit favorit-fodboldhold og opdagede, at man kunne ændre alt ved at rode med HTML og CSS. Siden har han lært tingene ved at prøve sig frem, læse forumtråde og pille ved små projekter, indtil de gjorde det, han ville.

På Coding Class deler han ikke perfekte løsninger fra et glansbillede-univers, men de ting han faktisk selv har bokset med: mærkelige JavaScript-fejl, CSS der ikke opfører sig som forventet, og små Python-scripts, der starter i kaos og ender med at spare tid i hverdagen. Han kan godt lide at vise både den første, halvdårlige løsning og den forbedrede udgave, så du kan se forskellen og forstå tankegangen bag.

Mikkel brænder for at gøre programmering mindre skræmmende for dem, der ikke ser sig selv som "tech-typer". Derfor skriver han på helt almindeligt dansk, med små, konkrete kodeeksempler og fokus på, hvordan du selv kan komme fra teori til noget, der faktisk virker. På Coding Class forsøger han at bygge bro mellem manual-sproget og virkeligheden ved at vise, hvordan det føles at sidde med fejlen klokken 22.30 – og hvad der skulle til, før den forsvandt.

Send kommentar

You May Have Missed