v2.5.2
Giriş yap

CRA'dan Vite'e Geçiş

React'in sitesinin arayüz güncellemesi sonrasında, react projesi oluşturmak için önerilen CRA artık önerilmemektedir.

Eğer nextjs gibi full-stack frameworkleri de kullanmak istemiyorsanız, en mantıklı çözüm Vite ile react projeleri oluşturmaktır.

Yeni oluşturacağınız projeler için sorun yok, zaten nasıl oluşturulacağı belli.

npm create vite
# ya da
yarn create vite
# ya da 
pnpm create vite

ancak artık varolan CRA projelerinizi de Vite'e geçirmek isteyebilirsiniz. Varolan projelerinizi Vite'e geçirirken dikkat etmeniz gereken şeyler aşağıda listelenmiştir.

  • JSX kodu olan bütün dosyalarınızın uzantısı .jsx olmalı. Yani CRA projenizde .js uzantılı içinde JSX kullandığınız bütün dosyaların adlarını .jsx e çevirmelisiniz.
  • .env dosyasından okuduğunuz ortam değişkenleri CRA projenizde process.env.REACT_APP_ ile başlarken vite projesinde import.meta.env.VITE_ şeklinde başlıyor. Bu yüzden ortam değişkenlerini buna göre değiştirmeniz gerekiyor.
  • CRA'da absolute path kullanıyorsanız, import Button from "../../components/button" yerine import Button from "components/button" gibi bir import işlemi yapıyorsunuzdur. Vite'de bunu ayarlamak için vite-jsconfig-paths paketine ihtiyacınız olacak.
Adım 1

İlk olarak Vite projenizi yukarıdaki gibi kurun. Ve CRA projenizdeki public/index.html de yaptığınız bir değişiklik varsa Vite projenizde ana dizinde bulunan index.html içinde düzenleyin.

Adım 2

CRA projenizde public/ içinde bulunan public dosyalarınızı Vite projenizde yine aynı dizin içine taşıyın.

Adım 3

CRA projenizde src/index.js dosyanızdaki kodlarınızı Vite projenizdeki src/main.jsx içine taşıyın.

Adım 4

CRA projenizde package.json içindeki dependencies ve devDependencies paketlerinizi Vite projenizde yine aynı dosya içine ekleyin. Eklerken vite projenizin package.json dosyaındaki paketlerini ezmediğinizden emin olun.

Adım 5

CRA projenizde src içinde JSX kodu geçen tüm dosyalarınızın uzantısını .jsx e dönüştürmeniz gerekiyor. Bunun için tek tek yapmak yerine, aşağıda verdiğim nodejs betiğini projenin ana dizininde changeJsxExtensions.js adıyla oluşturun ve içine şunları ekleyin:

const fs = require('fs');
const path = require('path');

const directoryPath = path.join(__dirname, 'src');

function isJSX(fileContent) {
	const jsxElementRegex = /<[\w\s.:]+\/?>/; // Basit JSX elementlerini kontrol etmek için düzenli ifade
	const reactComponentRegex = /import.*from\s+['"]react(-router-dom|-icomoon)?['"]/; // React, react-router-dom ve react-icomoon içe aktarımını kontrol etmek için düzenli ifade
	const reactElementRegex = /<\w+(\s+\w+(\s*=\s*{[^}]*}|"[^"]*"|'[^']*'))*\s*\/?>/; // Karmaşık JSX elementlerini kontrol etmek için düzenli ifade
	const capitalizedFunctionComponentRegex = /function\s+[A-Z]\w*\s*\(/; // Fonksiyon bileşeni için düzenli ifade
	const capitalizedConstComponentRegex = /const\s+[A-Z]\w*\s*=\s*\(/; // Const bileşeni için düzenli ifade
	return (
		reactComponentRegex.test(fileContent) ||
		jsxElementRegex.test(fileContent) ||
		reactElementRegex.test(fileContent) ||
		capitalizedFunctionComponentRegex.test(fileContent) ||
		capitalizedConstComponentRegex.test(fileContent)
	);
}

function changeExtension(filePath) {
	const newFilePath = filePath.replace(/\.js$/, '.jsx');
	fs.rename(filePath, newFilePath, (err) => {
		if (err) throw err;
		console.log(`Renamed: ${filePath} -> ${newFilePath}\n`);
	});
}

function processDirectory(directory) {
	fs.readdir(directory, (err, files) => {
		if (err) {
			return console.log('Unable to scan directory:', err);
		}

		files.forEach((file) => {
			const filePath = path.join(directory, file);

			fs.stat(filePath, (err, stats) => {
				if (err) {
					console.log('Error reading file:', err);
					return;
				}

				if (stats.isDirectory()) {
					processDirectory(filePath);
				} else if (stats.isFile() && path.extname(file) === '.js') {
					fs.readFile(filePath, 'utf8', (err, data) => {
						if (err) {
							console.log('Error reading file:', err);
							return;
						}

						if (isJSX(data)) {
							changeExtension(filePath);
						}
					});
				}
			});
		});
	});
}

processDirectory(directoryPath);

daha sonra uzantı değişikliğini uygulamak için şu komutu çalıştırın:

node changeJsxExtensions.js

Bu betik src altında içinde JSX kodu geçen bütün dosyalarınızın uzantısını otomatik .jsx e çevirecektir.

Not: Eğer javascript yerine typescript kullanıyorsanız betiğin içindeki .jsx değerini .tsx e çevirin.

Adım 6

env ortam değişkenlerini Vite'e göre uyarlamak için .env dosyalarınızda REACT_APP_ ifadelerini VITE_ olarak değiştirin ve src altında kodlarda kullandıklarınızı otomatik değiştirmek için aşağıdaki nodejs betiğini ana dizine replaceEnvVariables.js adıyla oluşturup şunları ekleyin:

const fs = require("fs");
const path = require("path");

// Değişiklik yapılacak olan dosya uzantıları
const fileExtensions = [".js", ".jsx"];

// Analiz edilecek olan dizinler
const sourceDirectories = ["src"];

// Dizinlerdeki tüm dosyaları listeleme
function getFiles(dirPath, arrayOfFiles) {
	files = fs.readdirSync(dirPath);

	arrayOfFiles = arrayOfFiles || [];

	files.forEach(function (file) {
		if (fs.statSync(dirPath + "/" + file).isDirectory()) {
			arrayOfFiles = getFiles(dirPath + "/" + file, arrayOfFiles);
		} else {
			arrayOfFiles.push(path.join(dirPath, "/", file));
		}
	});

	return arrayOfFiles;
}

// process.env.REACT_APP_ değerlerini import.meta.env.VITE_ değerine döndüren fonksiyon
function replaceEnvVariables(content) {
	const regex = /process\.env\.REACT_APP_([a-zA-Z_]+)/g;
	return content.replace(regex, "import.meta.env.VITE_$1");
}

// Tüm dosyaları gezerek işlem yapma
function processFiles(files) {
	files.forEach((file) => {
		const ext = path.extname(file);

		// Uzantısı `.js` veya `.jsx` ise işlem yap
		if (fileExtensions.includes(ext)) {
			fs.readFile(file, "utf8", function (err, data) {
				if (err) {
					console.log(err);
				} else {
					const newContent = replaceEnvVariables(data);
					if (data !== newContent) {
						console.log(`Updated file: ${file}`);
						fs.writeFile(file, newContent, (err) => {
							if (err) throw err;
						});
					}
				}
			});
		}
	});
}

// Tüm dizinlerdeki dosyaları bul
let files = [];
sourceDirectories.forEach((dir) => {
	files = [...files, ...getFiles(dir)];
});

// İşlem yap
processFiles(files);

Betiği çalıştırmak için:

node replaceEnvVariables.js

İşlem sonrasında src altındaki dosyalarınızı (index.js) hariç Vite projenizde src içine taşıyın.

Adım 7

Vite projenizde path tanımlarını absolute path olarak kullanmak için devDependency olarak şu paketi kurun:

npm i -D vite-jsconfig-paths
# ya da
yarn add -D vite-jsconfig-paths
# ya da
pnpm add -D vite-jsconfig-paths

Daha sonra vite.config.js dosyanızı açın ve şöyle düzenleyin:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import jsconfigPaths from 'vite-jsconfig-paths'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), jsconfigPaths()],
})
Sonuç

CRA projenizde CSS işlemleri için ne kullanıyorsunuz bilemiyorum, ben tailwind kullandığım için, Vite projesine en başta tailwind'i kuruyorum, ek bir ayar yapmama gerek kalmıyor.

Ancak sass, less gibi pre-processor'ler kullanıyorsanız Vite için ayarlarını bir araştırmanızı öneririm.

Bunun dışında, artık Vite projenizi ayağa kaldırıp olası bir hata olup olmadığını kontrol ederek devam edebilirsiniz.

Not: Eğer Vite'de absolute path tanımı olarak vite-jsconfig-paths kullanmak yerine şu makaledeki gibi bir tanım kullanıyorsanız, yani import Button from "../../components/button" yerine import Button from "~/components/button" şeklinde, o zaman aşağıdaki nodejs betiğini updateImportPaths.js adıyla oluşturup içine şunları ekleyin:

const fs = require("fs");
const path = require("path");

// Değişiklik yapılacak olan dosya uzantıları
const fileExtensions = [".js", ".jsx"];

// Analiz edilecek olan dizinler
const sourceDirectories = ["src"];

// Yeni başlangıç karakteri
const newStartChar = "~/";

// Paket isimleri
const packageNames = Object.keys(require("./package.json").dependencies);

// Dizinlerdeki tüm dosyaları listeleme
function getFiles(dirPath, arrayOfFiles) {
	files = fs.readdirSync(dirPath);

	arrayOfFiles = arrayOfFiles || [];

	files.forEach(function (file) {
		if (fs.statSync(dirPath + "/" + file).isDirectory()) {
			arrayOfFiles = getFiles(dirPath + "/" + file, arrayOfFiles);
		} else {
			arrayOfFiles.push(path.join(dirPath, "/", file));
		}
	});

	return arrayOfFiles;
}

// Başlangıç karakterini güncelleme
function replaceStartChar(content) {
	const regex = /export\s+(.*)\s+from\s+['|"]([^'|"]*)['|"]|import\s+(.*)\s+from\s+['|"]([^'|"]*)['|"]/g;
	return content.replace(regex, function (match, p1, p2, p3, p4) {
		let importPath;

		if (p1 !== undefined && p2 !== undefined) {
			importPath = p2;
		} else {
			importPath = p4;
		}

		// Paket ismi veya paketin alt dizini ise dokunma
		const isPackageOrSubPackage = packageNames.some((packageName) => {
			return (
				importPath.startsWith(packageName) &&
				(importPath[packageName.length] === "/" ||
					importPath[packageName.length] === undefined)
			);
		});

		if (isPackageOrSubPackage) {
			return match;
		}

		// Başına `~/` ekle
		if (importPath.startsWith(".") === false) {
			return match.replace(importPath, `${newStartChar}${importPath}`);
		}

		return match;
	});
}

// Tüm dosyaları gezerek işlem yapma
function processFiles(files) {
	files.forEach((file) => {
		const ext = path.extname(file);

		// Uzantısı `.js` veya `.jsx` ise işlem yap
		if (fileExtensions.includes(ext)) {
			fs.readFile(file, "utf8", function (err, data) {
				if (err) {
					console.log(err);
				} else {
					const newContent = replaceStartChar(data);
					if (data !== newContent) {
						console.log(`Updated file: ${file}`);
						fs.writeFile(file, newContent, (err) => {
							if (err) throw err;
						});
					}
				}
			});
		}
	});
}

// Tüm dizinlerdeki dosyaları bul
let files = [];
sourceDirectories.forEach((dir) => {
	files = [...files, ...getFiles(dir)];
});

// İşlem yap
processFiles(files);

Ve şu şekilde çalıştırın:

node updateImportPaths.js

Bu betik, CRA projelerinizdeki bütün absolute importlarınızın başına ~/ ekleyecektir. Elbette bunu yaparken paket import'larını hariç tutacaktır.

Unutmayın: Bütün bu işlemleri yaparken olası hataları önlemek için CRA projenizin mutlaka yedeğini alın ya da versiyon kontrol sistemlerini kullandığınızden emin olun ki bir hata olursa geriye dönebilin.

tayfunerbilen
549 gün önce yazdı - 1533 kez görüntülendi.
Önceki React'de index.html Koşullu Render Sonraki React Router Vercel 404 Sorunu