When I run ‘npm run build’ I get the following error:
> [email protected] build
> react-scripts build
Creating an optimized production build...
Failed to compile.
Unexpected end of JSON input
However, ‘npm start’ works and the website works locally. This issue only arises when I run ‘npm run build’
I’ve tried a variety of things to fix this issue, rebuilding after each (and trying all of them and then rebuilding):
- cleared build cache
- cleared npm cache
- deleted and reinstalled node modules, package-lock.json and package.json
- Created a new react app and copied the files over
My package.json passes jsonlint, and I cannot figure out the issue
But nothing is working. Here are my files:
package.json
:
{
"homepage": "http://[redacted].github.io/",
"name": "my-website",
"version": "0.1.0",
"private": true,
"dependencies": {
"framer-motion": "^10.16.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.11.0",
"react-scripts": "5.0.1"
},
"scripts": {
"start": "react-scripts start",
"predeploy": "npm run build",
"deploy": "gh-pages -d build",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^10.4.14",
"gh-pages": "^6.1.1",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.5"
}
}
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
};
tailwind.config.js
:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [],
}
App.js
:
import React from 'react';
import HomePage from './components/Homepage';
function App() {
return (
<div className="App">
<HomePage />
</div>
);
}
export default App;
Homepage.js
:
import React, { useEffect, useRef, useState } from 'react';
import { motion, useScroll, useSpring } from 'framer-motion';
import HeroSection from './HeroSection';
import AboutSection from './AboutSection';
import ProjectsSection from './ProjectsSection';
import SkillsSection from './SkillsSection';
import './styles.css';
const Home = () => {
const [arrowSize, setArrowSize] = useState(window.innerHeight / 6);
const heroSectionRef = useRef(null);
const [showName, setShowName] = useState(true);
const [nameSize, setNameSize] = useState('text-4xl sm:text-6xl');
const { scrollY } = useScroll();
const scaleX = useSpring(scrollY, {
stiffness: 100,
damping: 30,
restDelta: 0.001
});
useEffect(() => {
return scrollY.onChange((latest) => {
if (latest > 0) {
setShowName(false);
} else {
setShowName(true);
}
});
}, [scrollY]);
useEffect(() => {
const handleResize = () => {
const screenWidth = window.innerWidth;
if (screenWidth < 640) {
setNameSize('text-2xl');
} else {
setNameSize('text-4xl sm:text-6xl');
}
};
handleResize(); // Initial calculation
window.addEventListener('resize', handleResize); // Recalculate on window resize
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
useEffect(() => {
const arrowObserver = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
const newSize = window.innerHeight / 6;
setArrowSize(newSize);
}
},
{ threshold: [0, 0.5, 1] }
);
if (heroSectionRef.current) {
arrowObserver.observe(heroSectionRef.current);
}
return () => {
if (heroSectionRef.current) {
arrowObserver.unobserve(heroSectionRef.current);
}
};
}, []);
return (
<div className="snap-y snap-mandatory h-screen overflow-y-scroll">
{showName && (
<motion.div
className="fixed top-2 right-2 p-5 text-orange-500 z-50"
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 0.7 }}
transition={{
duration: 0.8,
delay: 0.5,
ease: [0, 0.71, 0.2, 1.01]
}}
>
<h1 className={nameSize}>[MY NAME]</h1>
</motion.div>
)}
{/* <HeroSection arrowSize={arrowSize} />
<AboutSection arrowSize={arrowSize} />
<ProjectsSection arrowSize={arrowSize} />
<SkillsSection arrowSize={arrowSize} />
<motion.div className="progress" style={{ scaleX }} /> */}
</div>
);
};
export default Home;
styles.css
:
/* Custom scrollbar styles */
::-webkit-scrollbar {
width: 12px;
}
::-webkit-scrollbar-track {
background: #a5f3fc; /* Cyan-200 color */
}
::-webkit-scrollbar-thumb {
background-color: #ff7f00; /* Orange color */
border-radius: 10px;
border: 3px solid #a5f3fc; /* Cyan-200 color to match the track */
}
::-webkit-scrollbar-thumb:hover {
background-color: #ff6600; /* Darker orange color on hover */
}
.line-drawing {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s forwards;
}
@keyframes draw {
to {
stroke-dashoffset: 0;
}
}
Homepage.css
:
/* Homepage specific styles */
.home-container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh;
}
section {
scroll-snap-align: center;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 20px;
transition: opacity 0.5s ease-in-out;
position: relative;
width: 100%;
}
/* Animation styles */
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
.animate-fade-in {
animation: fade-in 1s ease-in-out forwards;
}
.animate-fade-in-delay {
animation: fade-in 2s ease-in-out forwards;
animation-delay: 2s;
}
/* Line drawing animation */
.line-drawing {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s forwards;
}
@keyframes draw {
to {
stroke-dashoffset: 0;
}
}
here are one of the inner screens, which works when I do ‘npm start’:
import React, { useRef, useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import Arrow from './Arrow';
import { FaLinkedin, FaGithub, FaEnvelope } from 'react-icons/fa';
const HeroSection = ({ arrowSize }) => {
const heroSectionRef = useRef(null);
const [arrowSizeDynamic, setArrowSizeDynamic] = useState(arrowSize);
const [buttonSize, setButtonSize] = useState('text-base sm:text-lg');
const [textSize, setTextSize] = useState('text-xl sm:text-2xl');
const [titleSize, setTitleSize] = useState('text-4xl sm:text-6xl');
useEffect(() => {
const handleResize = () => {
if (heroSectionRef.current) {
const heroSectionHeight = heroSectionRef.current.clientHeight;
const contentHeight = heroSectionRef.current.scrollHeight;
const remainingSpace = heroSectionHeight - contentHeight;
const newSize = Math.max(arrowSize, remainingSpace / 2); // Adjust the divisor to control the size
setArrowSizeDynamic(newSize);
// Adjust button and text sizes based on screen width
const screenWidth = window.innerWidth;
if (screenWidth < 640) {
setButtonSize('text-sm px-4 py-2');
setTextSize('text-lg');
setTitleSize('text-4xl');
} else {
setButtonSize('text-base sm:text-lg px-6 py-3 sm:px-10 sm:py-5');
setTextSize('text-xl sm:text-3xl');
setTitleSize('text-5xl sm:text-9xl');
}
}
};
handleResize(); // Initial calculation
window.addEventListener('resize', handleResize); // Recalculate on window resize
return () => {
window.removeEventListener('resize', handleResize);
};
}, [arrowSize]);
return (
<section
ref={heroSectionRef}
className="section hero snap-start h-screen flex flex-col justify-between items-center text-center relative bg-cyan-200"
>
<div className="container mx-auto px-4 sm:px-10 relative z-10 mt-10">
<motion.h1
className={`${titleSize} mb-6 hero-title`}
initial={{ opacity: 0, y: -50 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1 }}
>
Hi! 👋
</motion.h1>
<motion.p
className={`${textSize} mb-4`}
initial={{ opacity: 0, y: -50 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1, delay: 0.5 }}
>
I'm [Redacted]
</motion.p>
<motion.p
className="text-lg sm:text-2xl mb-16 sm:mb-32"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1, delay: 1.5 }}
>
Passionate about things.
</motion.p>
<motion.div
className="flex justify-center space-x-4 sm:space-x-8 mb-8"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1, delay: 2 }}
>
<a href="https://www.linkedin.com/in/myname" target="_blank" rel="noopener noreferrer">
<FaLinkedin className="text-3xl sm:text-5xl text-blue-600 hover:text-blue-800" />
</a>
<a href="https://github.com/myusername" target="_blank" rel="noopener noreferrer">
<FaGithub className="text-3xl sm:text-5xl text-gray-800 hover:text-gray-600" />
</a>
<a href="mailto:[email protected]" target="_blank" rel="noopener noreferrer">
<FaEnvelope className="text-3xl sm:text-5xl text-orange-500 hover:text-orange-700" />
</a>
</motion.div>
<motion.a
href="/resume.pdf"
className={`inline-block ${buttonSize} bg-orange-500 text-white rounded-full hover:bg-orange-600 transition-colors mb-10`}
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 1, delay: 2.5 }}
download
>
Download Resume
</motion.a>
</div>
<Arrow size={arrowSizeDynamic} target="#about" />
</section>
);
};
export default HeroSection;
2
Answers
SOLVED: For some reason, just upgrading node via homebrew fixed the issue. not sure what original caused the issue, but it is very annoying since the error I got did not indicate there was an issue with my node.js installation
If you were already on
v23.2.0
when facing this issue, roll back to the LTS (v22.11.0
).