typescript - Hvordan deaktiverer jeg resolveJsonModule for en enkelt JSON-fil i en NextJs-applikasjon?
Jeg bygger en Next.js-applikasjon, og distribuerer med Vercel. Alt har fungert fint, helt til jeg nylig gjorde noen endringer i en stor JSON-fil som økte størrelsen med omtrent 20 %. Økningen i størrelse ser ut til å ha brutt en slags grense, og jeg får nå Webpack 5-feil, som ser ut til å skyldes TypeScript-typeoppløsning.
Jeg importerer JSON-filen direkte med en import. Fra det jeg har klart å samle inn, ser det ut til at resolveJsonModule compilerOption i tsconfig.json er ansvarlig for å fortelle webpack å forsøke å løse typene til JSON-filene på farten, slik at det antagelig kan sjekke at jeg gjør fornuftige ting med JSON-filen.
Det er faktisk en ganske enkel fil - det er bare et array av ganske enkle FoodItem-objekter som følger (illustrativt eksempel nedenfor):
import allFoodOriginal from '../data/all-food-data.json'
interface FoodData {
Calories: string,
Kilojoules: string
}
interface FoodItem {
id: number,
name: string,
folders: string[],
slug: string,
image?: string,
data?: FoodData
}
const allFood = allFoodOriginal as FoodItem[]
JSON-filen i seg selv er omtrent 1,4 millioner linjer lang, som er rundt 82021 elementer. Det ser ut til at dette rett og slett er for stort, da det kaster feilen i loggene nedenfor når den kompilere i Vercel-distribusjonen.
14:39:23.522 Installing dependencies...
14:39:28.885 npm WARN @babel/[email requires a peer of @babel/core@^7.0.0-0 but none is installed. You must install peer dependencies yourself.
14:39:28.896 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email (node_modules/@next/swc-darwin-arm64):
14:39:28.896 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email : wanted {"os":"darwin","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
14:39:28.907 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email (node_modules/@next/swc-win32-x64-msvc):
14:39:28.908 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email : wanted {"os":"win32","arch":"x64"} (current: {"os":"linux","arch":"x64"})
14:39:28.922 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email (node_modules/fsevents):
14:39:28.922 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email : wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
14:39:28.933 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email (node_modules/@next/swc-darwin-x64):
14:39:28.933 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email : wanted {"os":"darwin","arch":"x64"} (current: {"os":"linux","arch":"x64"})
14:39:28.934
14:39:28.935 updated 1 package in 4.846s
14:39:29.060
14:39:29.060 50 packages are looking for funding
14:39:29.060 run `npm fund` for details
14:39:29.061
14:39:29.847 Detected Next.js version: 11.1.2
14:39:29.850 Running "npm run build"
14:39:30.131
14:39:30.131 > [email build /vercel/path0
14:39:30.131 > next build
14:39:30.132
14:39:30.868 info - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
14:39:31.072 info - Checking validity of types...
14:45:11.987
14:45:11.989 > Build error occurred
14:45:12.003 RangeError: Value undefined out of range for undefined options property undefined
14:45:12.004 at Map.set (<anonymous>)
14:45:12.004 at recursiveTypeRelatedTo (/vercel/path0/node_modules/typescript/lib/typescript.js:62613:30)
14:45:12.004 at isRelatedTo (/vercel/path0/node_modules/typescript/lib/typescript.js:62112:34)
14:45:12.004 at checkTypeRelatedTo (/vercel/path0/node_modules/typescript/lib/typescript.js:61742:26)
14:45:12.004 at isTypeRelatedTo (/vercel/path0/node_modules/typescript/lib/typescript.js:61694:24)
14:45:12.005 at removeSubtypes (/vercel/path0/node_modules/typescript/lib/typescript.js:58445:33)
14:45:12.005 at getUnionType (/vercel/path0/node_modules/typescript/lib/typescript.js:58547:31)
14:45:12.005 at checkArrayLiteral (/vercel/path0/node_modules/typescript/lib/typescript.js:70038:17)
14:45:12.005 at checkExpressionWorker (/vercel/path0/node_modules/typescript/lib/typescript.js:76283:28)
14:45:12.005 at checkExpression (/vercel/path0/node_modules/typescript/lib/typescript.js:76204:38)
14:45:12.146 npm ERR! code ELIFECYCLE
14:45:12.146 npm ERR! errno 1
14:45:12.150 npm ERR! [email build: `next build`
14:45:12.150 npm ERR! Exit status 1
14:45:12.151 npm ERR!
14:45:12.151 npm ERR! Failed at the [email build script.
14:45:12.151 npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
14:45:12.157
14:45:12.157 npm ERR! A complete log of this run can be found in:
14:45:12.158 npm ERR! /vercel/.npm/_logs/2021-10-26T13_45_12_151Z-debug.log
14:45:12.174 Error: Command "npm run build" exited with 1
Når jeg kjører npm run build lokalt, får jeg rett og slett en Javascript heap out of memory-feil.
Jeg er glad for å ikke måtte bry meg om typetesting av JSON-filen, men jeg vet ikke hvordan jeg skal deaktivere typetesting fra innenfor min NextJs-applikasjon.
Hvis jeg setter resolveJsonModule til false, settes det automatisk tilbake til true av byggeprosessen som hevder å vite bedre.
Finnes det noen alternativer for å deaktivere typekontrollen for denne JSON-filen alene?
Oppdatering
Det ser ut til å være mulig å overvinne denne spesifikke typetjekkfeilen ved å laste JSON-filen med fs-modulen:
import fs from 'fs'
import path from 'path'
const allFood = JSON.parse(fs.readFileSync(path.join(process.cwd(), '/data/all-food-data.json'), 'utf-8')) as FoodItem[]
Dette introduserte imidlertid en annen feil, der sider ikke lenger ble generert dynamisk ved forespørsel, og i stedet fikk jeg en 404-feil. Hvis jeg satte fs.readFileSync()-kallet inne i getStaticProps-funksjonen, fikk jeg en 500-feil. Disse feilene oppsto kun på Vercel-distribusjonen, og den lokale versjonen fungerte fortsatt fint.
Det kan finnes en måte å løse disse problemene på, men jeg endte opp med en annen løsning:
Omvei
Å bare dele JSON-filen i to mindre filer og slå dem sammen under kjøring løste problemet.
import allFood1 from '../data/all-food-data.json'
import allFood2 from '../data/all-food-data-2.json'
const allFood = [...(allFood1 as FoodItem[]), ...(allFood2 as FoodItem[])] as FoodItem[]
Ikke egentlig et spesielt tilfredsstillende svar, så jeg lar spørsmålet stå ubesvart i håp om å finne en bedre måte å overvinne det på.