javascript - Hur importerar man delad typescript-kod med create-react-app (utan att göra eject)?
Jag försöker uppnå delning av TypeScript-kod i en create-react-app i icke-eject-läge, men jag stöter på den ökända begränsningen att importer utanför src inte är tillåtna:
You attempted to import ../../common/src/lib.ts which falls outside of the project src/ directory. [...]
För fallet utan TypeScript har detta frågats och besvarats här, men jag kan inte få någon av lösningarna att fungera med TypeScript. Specifikt är problemen med de föreslagna lösningarna:
Att ställa in
baseDirits-config.json: Här klagar create-react-app på: Ditt projektsbaseUrlkan endast sättas tillsrcellernode_modules. Create React App stöder för närvarande inte andra värden.Metoder baserade på react-app-rewired: Mer lovande. Att inaktivera
ModuleScopePlugintar mig förbi felet "försökte importera utanför src", men problemet nu är att laddaren för TypeScript-filer inte samarbetar:Jag har verifierat att
.tssjälv är okej: Att kopiera till./srcoch importera det därifrån fungerar bra.Jag har också lagt till mappen
../../common/srciincludes-listan its-config.json.Min gissning är att webpack-loader-konfigurationen på något sätt har en regel som hindrar TypeScript-loaden från att transpilerar filer som inte matchar dess förväntade sökmönster. Hur kan detta åtgärdas med react-app-rewired?
Att skapa symboliska länkar till källorna fungerar inte heller - återigen med samma problem. Troligtvis eftersom webpack internt löser symboliska länkar och ser filen i en sökväg där de vanliga loader-reglerna inte gäller.
Eject-baserade lösningar: Jag skulle helst inte vilja ejecta för tillfället, men jag försökte och jag stöter i princip på samma problem igen.
Jag har också hittat andra frågor som verkade relaterade men inte svarade på problemet:
- Skapa React-app + Typescript i monorepo koddelning: Låter i princip som samma fråga, men det är det inte, eftersom det handlar om fallet med en ejected React-app.
- Dela kod mellan projekt som använder TypeScript och webpack: Tar också upp problemet med koddelning, men är inte specifikt för create-react-app, och jag vet inte om lösningen kan överföras till create-react-app, eftersom det kräver manuell kontroll av webpack-konfigurationen.
Att återanvända TypeScript-typningar i ett mono repo verkar vara ett ganska rimligt mönster. Missar jag något eller varför gör create-react-app detta så svårt?
För att reproducera: Min kod är i princip 100% vad du får från
npx create-react-app my-app --template typescript
med en import till extern tillagd.
Svar #1
Du kan använda craco (create-react-app config override) för att åsidosätta webpack-konfigurationen (abstraherad som en del av CRA) utan att ejecta.
Dessutom kan du använda ts-loader för att direkt referera icke-transpilerad ts-kod i externa projekt (t.ex. om du vill referera/använda delad kod/bibliotek som en del av ett mono-repo).
Om vi antar att din CRA-app finns i client-katalogen ser din projektstruktur ut som följer:
client/
|--src/
|--package.json
shared/
|--package.json
|--(ts files)
package.json
cd client
yarn add -D @craco/craco ts-loader
- skapa en
craco.config.js-fil iclient/(CRA)-katalogen - se till att
craco.config.jshar följande innehåll
const path = require("path");
module.exports = {
webpack: {
configure: webpackConfig => {
// ts-loader is required to reference external typescript projects/files (non-transpiled)
webpackConfig.module.rules.push({
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
transpileOnly: true,
configFile: 'tsconfig.json',
},
})
return webpackConfig;
}
}
};
- Ersätt
react-scripts-kommandon iclient/package.jsonmedcraco
/* client/package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "craco start",
- "build": "react-scripts build",
+ "build": "craco build"
- "test": "react-scripts test",
+ "test": "craco test"
}
Svar #2
UPPDATERING: Eftersom react-app-rewired endast underhålls passivt och inte stödjer CRA-versioner 2+ (vi är tre huvudversioner senare vid tidpunkten för skrivandet), skulle jag inte längre rekommendera detta tillvägagångssätt.
Efter flera timmar av experimenterande och att ha läst på GitHub-ärenden, har jag äntligen en fungerande lösning. Stort tack till BirukDmitry som gjorde detta mycket hjälpsamma inlägg på GitHub. Steg-för-steg-guide:
Installera react-app-rewired och customize-cra
npm i react-app-rewired customize-cra --save-devKonfigurera react-app-rewird med en minimal
config-overrides.jspå detta sätt:const { removeModuleScopePlugin, override, babelInclude } = require("customize-cra"); const path = require("path"); module.exports = override( removeModuleScopePlugin(), // (1) babelInclude([ path.resolve("src"), path.resolve("../common/src"), // (2) ]) );Inställning (1) är liknande det som behövs för att komma runt import-outside-src-begränsningen i allmänhet (se länkad fråga).
Inställning (2) är dock avgörande för att aktivera babel-transpilering (och därmed, inklusive TS-typeborttagning antar jag) för andra sökvägar också. Det är här du måste lägga till dina sökvägar från vilka du vill importera.
Inga anpassningar behövs för
tsconfig.json.Importera med relativa sökvägar, t.ex.
import * as mymodule from '../../common/src/mymodule'.
