Photo by Bruno Nascimento on Unsplash

REACT MODULES

Create React App Projesi Nasıl NPM/UMD Modülüne Dönüştürülür?

Bu blog yazısının amacı CRA(Create React App) ile oluşturulmuş React Projenizi nasıl bir NPM/UMD Modülüne dönüştürebileceğiniz üzerine bir yapılmış ufak denemeleri içerir.

Frontend Development With JS
8 min readAug 12, 2023

--

Bundan önceki bir yazımda ufak bir projeyi NPM modülüne çevirmiştik.

GitHub ve NPM

Bu projeye ait git reposuna
https://github.com/odayibasi/number-multiplier

Bu proje ait npm reposuna https://www.npmjs.com/package/@odayibasi/number-multiplier

Bunu bileşeni sonradan oluşturduğumuz bir React JS projesinde veya React TS projesinden import ederek kullanabilmiştik.

Ama bu örnek benim asıl motivasyonum olan mevcutda yazılmış bir React projesini bir bileşen haline dönüştürmekten biraz uzaktaydı.

Zorluklar

  • CRA (Create React App) ile önceden oluşturduğum projeyi bu yeni NPM Component Boilerplate taşımak gerekiyor.
  • Bileşeni baştan bileşen gibi düşünerek geliştirilmiş bir örnekti. Halbuki benim durumumda mevcut React Uygulaması veya onun bir parçasını çıkarmak bu düşünme şeklinden farklılıklar içeriyor.
  • Webpack ve tsconfig, jsconfig konfigürasyonlarını bu NPM Component boilerplate projesine taşımak gerekiyor.
  • Styling ve Asset taşıması için ayrıca çalışmalar yapmak gerekiyor.

Motivasyon

Özetle benim istediğim aslında önceden geliştirdiğim bir React Projesinin tüm uygulamasını veya içerisinden herhangi bir bileşeni basitçe dışarıya çıkarabilecek bir UMD/NPM paketine dönüştürebilecek bir yöntem bulmaktı.

Bazı Kavramlar

Bu işlemlerin öncesinde bazı kavramları ve araçları iyi anlamak gerekiyor. Bundan dolayı Modules konusu ile ilgili yazmış olduğum aşağıdaki blogları öncelikle okumanızı öneririm.

UMD Nedir ?

UMD, “Universal Module Definition.” anlamına gelir. JavaScript modülleri için, zamanın en popüler script dosyası yükleme yöntemleri arasında uyumluluk sağlamayı amaçlayan bir modeldir:

  • CommonJS (Node.js tarafından kullanılır),
  • AMD (Asynchronous Module Definition, RequireJS tarafından kullanılır)
  • Global değişken tanımları (herhangi bir modül yükleyici kullanmayan tarayıcı script dosyaları için).

UMD, bir JavaScript kod parçasının kullanılan modül sistemini belirlemesine ve buna göre uyarlanmasına olanak tanır. UMD ile sarılmış (wrapped) bir modülün çalışabileceği anlamına gelir.

Örnek bir UMD dosyası aşağıdaki şekilde tanımlanması gerekir

(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.returnExports = factory();
}
}(typeof self !== 'undefined' ? self : this, function () {
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));

Bizim yapacağımız örneklerde ise projemizi webpack ile bir UMD script dosyasına dönüştürüp bunun içerisine package.json ekleyerek bunu bir NPM modülü haline getireceğiz.

Örnek Proje

Bu örnek projelerde basitten karmaşığa bir kaç senaryoyu deneyerek ilerlemek istiyorum. GitHub Linki

Initial

Öncelikle CRA kullanarak NumberMultiplier uygulaması gibi basit bir uygulama geliştirelim.

npx create-react-app sample

Bu işlemi yaptığınızda karşınıza aşağıdaki şekilde bir öneri çıkarıyor.

We suggest that you begin by typing:

cd sample
npm start

Söylediği öneriyi yerine getirelim. Ve aşağıdaki şekilde bir örneğin localhost:3000 portunda çalıştığını görebilirsiniz.

Şimdi yapmamız gereken NumberMultiplier örneğini alıp uygulamamızın içerisine yerleştirmek ve mevcut uygulamayı biraz değiştirmek.

Level 1 Commit:

Bu commit içerisinde ufak değişiklikler ekledim.

  • Projenin App → SampleUMDApp olarak değiştirdim.
  • Sass Paketini yükledim ve “SampleUMDApp.scss” styling ekledim
  • jsconfig.json ekleyerek import path src altından çalışmasını sağladım.
  • logo.svg asset/images altına taşıdım
  • NumberMultiplier bileşenini components/ klasörü altına girdim ve buna ve styling scss tanımladım.

Elimizde aşağıdaki şekilde arkaplanları renklendirilmiş, dışardan props olarak multiplier x5 olarak geçtiğim bir bileşen bulunuyor oldukça basit bir örnek.

Level 2 Commit:

Bu aşamada cra(create-react-app) scriptlerini eject ederek güncellemek istiyorum . Bu işlem öncesi kodun local en azından commitlenmiş olması gerekiyor

npm run eject

bu komut sonrasında bu işlemin geriye döndüremez bir işlem olduğunu söyleyecek

NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html

? Are you sure you want to eject? This action is permanent. › (y/N)

y diyerek yolumuza devam ediyoruz.

Mevcut kod yapımızda şu anda herhangi bir değişiklik yok

npm run start
npm run test
npm run build

komutları aynı şekilde çalışmaya devam ediyor..

Hatta basit bir deneme yapalım.

npm run build 

komutunu çalıştıralım. Bütün paketi build edip bizim için build altında sıkıştırılmış bir js dosyası ve css dosyası oluşturdu.

Bu js ve css dosyasının özelliği tarayıcının anlayabileceği şekilde kodun ve style dosyasının transpile olmuş olmasıdır. Webpack/Rollup bu işlemleri

  • JS için Babel kullanarak (Detay Oku)
  • SaSS için Sass Preprocessor kullanarak gerçekleştirir (Detay Oku)

Söylediği gibi serve -s build derseniz.

Aslında altı kırmızıya boyadığım index.html dosyasını bir local sunucuda çalıştırmış olacaksınız ve aynı görseli ekranda görebileceksiniz.

Level 3 Commit:

Bu aşamada

  • package.json içerisinde buildUMD çalıştıracak ve ekstra bunun bir UMD/NPM package olarak dışarıdan kullanılmasını sağlayacak güncellemeler yapacağız.
  • build.js kopyalarak build.umd.js dosyası oluşturuyoruz. Bu dosya üzerinden UMD build oluşturmayı sağlayacağız.
  • webpack.config.js bir kopyasını oluşturarak webpack.umd.config.js dosyası oluşturup, build.umd.js bu dosyayı çalıştırmasını sağlayacağız.

Özetle aslında ek bir build sistemi oluşturup bunlada UMD/NPM paketi oluşturmayı hedefliyoruz.

package.json dosyası üzerinde bir takım değişiklikler yapalım.

build.umd.js dosyası içerisine umd modülü oluşturma yönünde güncellememiz gerekiyor. Bu dosya build almamızı sağlayan bir script sadece webpack.config dosyasının yeni adresi olarak webpack.umd.config vermemiz yeterli olacaktır.

webpack.umd.config dosyasında biraz çıktı alma yöntemimizi değiştirmemiz gerekiyor..

öncelikle path.js içerisinde yeni bir path tanımlıyoruz . Artık appIndexJS değilde appUMDIndex.js kullanacağız. Bizim içinde bu SampleUMDApp bileşeni.

bu dosya içerisindeki output kısmını UMD oluşturmaya özelleştiriyoruz.

    output: {
// The build folder.
path: paths.appBuild,
filename: "static/js/[name].js",
chunkFilename: "static/js/[name].chunk.js",
assetModuleFilename: "static/media/[name].[hash][ext]",
library: "@odayibasi/sample-umd",
libraryTarget: "umd",
},

Bu kısımda br önemli nokta bu output içerisinde react ile ilgili kütüphanenin bir daha yüklenmemesini sağlamak bunun için externals kısmında aşağıdaki react ile ilgili kütüphaneleri ekliyoruz.

externals: {
react: "commonjs react",
"react-dom": "commonjs react-dom",
},

Bir diğer konuda Styling kısmında css sürekli aynı isimde dosya üretebilmesi için MiniCssExtractPlugin kısmındaki dosya üretim kısmında ufak değişiklikler yapıyoruz.

      isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "static/css/[name].css",
chunkFilename: "static/css/[name].css",
}),

Şimdi sırada build çalıştırıp UMD/NPM paketimiz düzgün şekilde oluşup oluşmadığını kontrol etmemiz.

npm run build:umd

çalıştıralım ve artık main.js ve main.css dosyalarının olduğunu görebilirsiniz.

main.js dosyasının içerisine baktığımızda da UMD tanımlamasında olduğu gibi dışarıya sample-umd kütüphanesini çıkardığını görebilirsiniz.

Level 4 Commit:

Bu aşamadan sonraki kısım biraz deneme bunun için host-js isimli yeni bir React projesi oluşturacağız ve bunun içerisinden oluşturduğumuz UMD paketini kullanmaya çalışacağız.

npx create-react-app host-js
cd host-js
npm start

ile uygulamamızı başlatıyoruz. Uygulamamızda bu sefer sadece This is host app yazsın …

Bunun altına yaptığımız sample-umd paketini ekleyelim.

cd sample
pwd

sonra bununla gidip Host app olduğu yerde bu paketi locally install edin.

npm i /Users/onurdayibasi/Documents/github/odayibasi/convert-create-react-app-to-npm-package/sample

Not: Bu konunun detayları için React Bileşenleri Oluşturmak — (LocalPath) blog yazısını okuyun.

Host uygulamamızın App.js dosyasında ufak bir değişiklik yaparak. Hem bileşeni hemde onun style yüklüyoruz.

Artık uygulamamızın içinde bu UMD Modülünü kullanabilirsiniz.

Gelmeyen tek kısım Logo kısmı, bu kısmın üzerinde sonra duracağım.

Level 4 Commit:

Bu aşamada oluşturduğumuz modülü birde React TS projesinde deneyelim. Bu sefer ortamımızı Vite ile oluşturalım.

npx create-react-app host-ts-cra --template typescript
cd host-ts-cra
npm start

komutlarını çalıştırın uygulamanızı ekranda görebilirsiniz

Bundan sonra yapmamız gereken aynı host-js react projesinde olduğu gibi değişiklikler yapıp bileşeni React TS projesi içerisinde denemek.

Aynı adımları TS projesinde denediğinizde Could not find declaration file for module şeklinde bir hata alırsınız.

Bu demek oluyorki TS projesinde bu modülü tanımlayabilmemiz için bir takım declaration dosyalarını UMD modüle tarafına eklememiz gerekiyor.

types/ klasörü altına main.d.ts isimli bir dosya açıp burada SampleUMDApp bileşinin interface TS olarak oluşturuyorum.

Daha sonrasında package.json içerisinde aşağıdaki değişiklikleri yapıyorum.

Bu değişiklik ilgili type tanımlamalarımızı build içerisine aktarabiliriz.

    "build:umd": "node scripts/build.umd.js && cp -R  ./types/* ./build/static/js",

bir değişikliğide package.json tanım kısmında yapmamız gerekiyor. types olarak hangi dosyaya

  "types": "build/static/js/main.d.ts",

Sonrasında uygulamayı çalıştırdığımızda uygulamamızın çalıştığını görebilirsiniz.

Problem Çıkan Kısımlar

  1. Asset Loading sırasında path tanımlamarında sorun çıkarıyor.
  2. Vite ile oluşturulan React TS projelerinde aynı dosyayı okurken export default doğru tanımlamadın şeklinde uyarı veriyor.

Çözüm: Bu problemler için ek bir yazı yazdım linke buradan ulaşabilirsiniz.

Referanslar

LearnReactUI.dev

React Ekosisteminde kendi kariyerinizi daha ileriye götürmek için LearnReactUI.dev sitesine üye olmayı unutmayın. Bu site piyasada çalışan(real-world) Web Uygulaması geliştirmek isteyen React geliştiricileri için oluşturulmuş bir web sitesidir.

https://learnreactui.dev/

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--

No responses yet