node.js - React Vite: Eksport fra lokale moduler ikke funnet (Migrering fra CRA)
Jeg prøver å importere eksporterte medlemmer fra lokale Node.js-pakker. Dette fungerte fint før jeg brukte Vite (standard CRA webpack-oppsett), men siden jeg byttet til Vite får jeg følgende feil:
Uncaught SyntaxError:
The requested module '/@fs/Users/...{long_path}.../lib/shared/countries/build/index.js'
does not provide an export named 'countryListAllIsoData'
Vite-prosjektet ble satt opp ved å bruke npm create vite@latest med typescript, react, swc-preset.
Disse mislykkede importene skjer bare på lokale pakker (ingen installert fra npm-registeret), så jeg er sikker på at problemet er på min side, men jeg har ikke vært i stand til å finne ut hva som forårsaker det.
Spørsmål 1: Hvordan kan jeg få disse importene til å fungere?
Siden de fungerte med Webpack, er jeg ikke helt sikker på hvorfor de ikke fungerer med Vite? Vite krevde at prosjektet mitt ble satt opp som en modul (i package.json - "type": "module"). Bryter måten importeringer fungerer i en modul med min nåværende kode?
Spørsmål 2: Hvordan kan jeg få linteren min til å vise disse feilene?
Jeg bruker VS Code som ser ut til å være helt fornøyd med måten modulen importeres på. Ingen feil vises, og jeg kan gå til definisjonen av importene uten problemer (noe som får meg til å tro at alt eksporteres korrekt).
Relevante kodeutdrag
Jeg importerer som følger:
import { countryListAllIsoData } from "countries";
tsconfig.json-filen er urørt (akkurat som npm create vite@latest laget den). Det samme gjelder for package.json-filen, bortsett fra at noen moduler ble installert (f.eks. den som forårsaker dette problemet).
Den lokale pakken som forårsaker dette problemet heter countries og er ganske liten og enkel. Den har følgende package.json-fil:
/// package.json
{
"name": "countries",
"version": "1.0.0",
"description": "",
"main": "./build/index.js",
"exports": {
".": "./build/index.js"
},
"scripts": {
"build": "tsc",
"prepare": "npm run build"
},
"keywords": [],
"author": "Bram Vanbilsen",
"license": "UNLICENSED",
"devDependencies": {
"typescript": "^4.8.4"
}
}
Filen tsconfig.json:
{
"compilerOptions": {
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"module": "commonjs", /* Specify what module code is generated. */
"moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declarationMap": true, /* Create sourcemaps for d.ts files. */
"outDir": "./build", /* Specify an output folder for all emitted files. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
Filen index.ts:
export const countryListAllIsoData = [...] as const;
Svar #1
Problemet
Jeg har møtt det samme problemet og klarte å løse det.
Problemet er at vite, i motsetning til for eksempel webpack, trenger ES-moduler for å fungere siden dette er hovedårsaken til at Vite er så rask sammenlignet med andre bundlere. Av denne - og noen andre - grunn(er) vil Vite forhåndspakke avhengigheter og utføre en konvertering fra UMD- eller CommonJS-moduler til ES-moduler.
Sitat fra Vite-dokumentene - Forhåndspakking av avhengigheter:
CommonJS- og UMD-kompatibilitet: Under utvikling leverer Vite all kode som native ESM. Derfor må Vite først konvertere avhengigheter som leveres som CommonJS eller UMD til ESM.
Men Vite utfører ikke denne konverteringen for lenkede (lokale) avhengigheter. Derfor må du sørge for at du kun bruker ESM-moduler.
Løsning #1
For å løse problemet må du endre tsconfig.json for biblioteket ditt til å bruke ES-moduler, så "module" MÅ IKKE være commonjs, men bør for eksempel være ES6 eller ESNext osv. Du må også justere "moduleResolution" til ES6, ESNext eller for TypeScript >= 5.x.x Bundler.
Så din tsconfig.json bør se slik ut:
{
"compilerOptions": {
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"module": "ESNext", /* Specify what module code is generated. */
"moduleResolution": "Bundler", /* Specify how TypeScript looks up a file from a given module specifier. */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declarationMap": true, /* Create sourcemaps for d.ts files. */
"outDir": "./build", /* Specify an output folder for all emitted files. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
Løsning #2:
Sitat fra Vite-dokumentasjonen - Monorepoer og lenkede avhengigheter:
Dette krever imidlertid at den tilknyttede avhengigheten eksporteres som ESM. Hvis ikke, kan du legge til avhengigheten i optimizeDeps.include og build.commonjsOptions.include i konfigurasjonen din.
export default defineConfig({
optimizeDeps: {
include: ['linked-dep'],
},
build: {
commonjsOptions: {
include: [/linked-dep/, /node_modules/],
},
},
})
Når du gjør endringer i den lenkede avhengigheten, start utviklingsserveren på nytt med --force kommandolinjealternativet for at endringene skal tre i kraft.
Svar #2
Jeg hadde dette problemet, og å bruke Vite-alias løste det.
I Vite-konfigurasjonen, legg til et alias for pakkenavnene med absolutte stier til den lokale mappen:
resolve: {
alias: {"countries":"/Users/...{long_path}.../lib/shared/countries"}
}
