node.js - React Vite: Exporter från lokala moduler hittades inte (Migrering från CRA)
Jag försöker importera exporterade medlemmar från lokala Node.js-paket. Dessa fungerade bra tidigare med Vite (standard CRA webpack-inställning), men sedan jag bytte till Vite får jag följande fel:
Uncaught SyntaxError:
The requested module '/@fs/Users/...{long_path}.../lib/shared/countries/build/index.js'
does not provide an export named 'countryListAllIsoData'
Vite-projektet skapades med npm create vite@latest med typescript, react, swc-preset.
Dessa misslyckade importer sker endast på lokala paket (inga installerade från npm-registret) så jag är säker på att problemet ligger hos mig, men jag har inte kunnat spåra vad som orsakar det.
Fråga 1: Hur kan jag få dessa importeringar att fungera?
Eftersom de fungerade med Webpack, är jag inte riktigt säker på varför de inte fungerar med Vite? Vite krävde att mitt projekt skulle sättas upp som en modul (i package.json - "type": "module"). Bryter sättet importeringar fungerar i en modul min nuvarande kod?
Fråga 2: Hur kan jag få min linter att visa dessa fel?
Jag använder VS Code som verkar vara helt nöjd med sättet modulen importeras på. Inga fel visas och jag kan gå till definitionen av importerna utan några problem (vilket får mig att tro att allt exporteras korrekt).
Relevanta kodsnuttar
Jag importerar på följande sätt:
import { countryListAllIsoData } from "countries";
Filen tsconfig.json är orörd (exakt som npm create vite@latest skapade den). Detsamma gäller för filen package.json, förutom att några moduler installerades (t.ex. den som orsakar detta problem).
Det lokala paketet som orsakar detta problem heter countries och är ganska litet och enkelt. Det har följande 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
Jag har stött på samma problem och kunde lösa det.
Problemet är att vite, till skillnad från t.ex. webpack, behöver ES-moduler för att fungera eftersom detta är den primära anledningen till att Vite är så snabbt jämfört med andra bundlers. Av denna - och några andra - anledning(ar) kommer Vite att förförpacka beroenden och utföra en konvertering från UMD- eller CommonJS-moduler till ES-moduler.
Citerat från Vite-dokumentationen - Förhandsbundling av beroenden:
CommonJS- och UMD-kompatibilitet: Under utveckling levererar Vite all kod som native ESM. Därför måste Vite först konvertera beroenden som levereras som CommonJS eller UMD till ESM.
Men Vite utför inte denna konvertering för länkade (lokala) beroenden. Därför måste du se till att du endast använder ESM-moduler.
Lösning #1
För att lösa problemet behöver du ändra tsconfig.json för ditt bibliotekssyntax till att använda ES-moduler, så "module" FÅR INTE vara commonjs, utan bör till exempel vara ES6 eller ESNext osv. Du behöver också justera "moduleResolution" till ES6, ESNext eller för TypeScript >= 5.x.x Bundler.
Så din tsconfig.json bör se ut så här:
{
"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:
Citat från Vite-dokumentationen - Monorepos och länkade beroenden:
Men detta kräver att den länkade beroendet exporteras som ESM. Om inte, kan du lägga till beroendet i optimizeDeps.include och build.commonjsOptions.include i din konfiguration.
export default defineConfig({
optimizeDeps: {
include: ['linked-dep'],
},
build: {
commonjsOptions: {
include: [/linked-dep/, /node_modules/],
},
},
})
När du gör ändringar i den länkade depen, starta om utvecklingsservern med kommandoradsalternativet --force för att ändringarna ska träda i kraft.
Svar #2
Jag hade detta problem och att använda Vite-alias löste det.
I Vite-konfigurationen, lägg till ett alias för paketnamnen med absoluta sökvägar till den lokala mappen:
resolve: {
alias: {"countries":"/Users/...{long_path}.../lib/shared/countries"}
}
