حسان امینی لو
حسان امینی لو
خواندن ۹ دقیقه·۲ سال پیش

ساخت "کامپوننت پکیج" روی NPM

بعضی وقتا توی پروژه های بزرگ که یک زبان طراحی مشترک دارن المان های صفحه تکرار میشه. مثلا همه دکمه ها تو همه جای سایت یک شکل هستن، پیام های خطا، لینک ها، کارت ها، سایه ها و ... . اگر این اتفاق تو یک پروژه بیوفته خب میتونیم همه این المان ها رو یکبار طراحی کنیم و توی هر صفحه ای که نیاز بود ازشون استفاده کنیم.

داستان اونجایی جالب میشه که ممکنه چندتا پروژه داشته باشید که همه شون از یک دیزاین سیستم دارن استفاده میکنن، رابط کاربری بین همه این پروژه ها یک شکل هست. چه روی موبایل باشه چه روی اپلیکیشن دسکتاپ و چه روی وب همه و همه یک سری کامپوننت دارن که بین شون مشترکه.

اینجاست که میتونید تمام المان هایی که یک بار طراحی کردید رو تبدیل به یک NPM پکیج کنید و مثل یه پکیج عادی بین همه شون به اشتراک بذارید. اگر تغییری هم کردن کافیه فقط یک جا رو تغییر بدید و ببینید که تغییراتتون بین همه پروژه ها اعمال شده به راحتی اجرای npm update


توی این مطلب بهتون میگم چطور میتونید اینکارو انجام بدید و از چه ابزار هایی باید استفاده کنید و چطور کنار قرارشون بدید که نتیجه مطلوب رو بگیرید. این نکته یادتون باشه که اینکار زمانی خوبه که شما کامپوننت ها یا توابع مشترکی دارید که میخواید بین چندتا پروژه share کنید.


نقشه مون چیه؟

برای اینکه این پکیج رو بسازیم باید یه پروژه خام npm ایجاد کنیم. بعد میتونیم تو کامپوننت ها یا فانکشن هایی که میخوایم بین پروژه ها share بشه رو بنویسیم. میتونیم برای اینکه بتونیم اینا رو ببینیم از storybook استفاده کنیم. در کنارش میتونیم از linter و prettier برای اینکه کدمون هم تر تمیز باشه استفاده کنیم. قطعا Typescript هم باید داشته باشیم. برای استایل ها من از styled-components و tailwind استفاده میکنم. در نهایت برای بیلد کردن پکیج و انتشارش از rollup کمک میگیرم. دقت کنید که جزییات توی این مطلب خیلی اهمیت داره پس خیلی با دقت و حوصله باید انجامش بدید که نتیجه بگیرید.

خب بزن بریم


ستاپ اولیه پروژه و Typescript

همونطور که گفتم باید یه پروژه خام npm بسازیم پس یه فولدر بسازید با هر اسمی که دوست دارید. برید داخل فولدر و دستور npm init یا yarn init رو اجرا کنید. جواب سوالاشو بدید تا تموم شه و در نهایت یه دونه فایل package.json ایجاد میشه. این فایلیه که بعدا برای import کردن به پروژه parent قراره بگه چه dependency هایی داره و چه فایل هایی رو باید استفاده کنه. حالا به اونجا هم میرسیم ولی فعلا باید توی فولدر یه دونه فایل package.json داشته باشید:


حالا نوبت نصب پکیج هاست. فعلا اینا رو نصب کنید:

yarn add -D typescript prettier eslint eslint-config-prettier @types/react @types/react-dom

اینا همه devDependency بود، اینارو هم به عنوان dependency نصب کنید:

yarn add react react-dom

نوبت کانفیگ typescript هست، به خاطر همین یه دونه فایل به اسم tsconfig.json درست کنید و اینا رو توش قرار بدید

نکته مهم این فایل ایناس:

  • مقدار declaration که میگه برای فایل ها تایپ شون هم تعریف کنه
  • مقدار declarationDir که میگه کجا قرار بده این فایل تایپ ها رو
  • مقدار jsx که ست شده روی react-jsx که سینتکس مون رو بشناسه

بقیه شون هم قطعا مهم هستن ولی این ۳ تا چیز های تعیین کننده هستن.


الان نوبت کامپوننت ها و فایل های اصلیه. یه فولدر بسازید به اسم src یا lib یا هرچی دوست داشتید ولی معمولا اسمش src هست. برای مثلا من یکم خرت و پرت گذاشتم توش:

  • فولدر Components: قراره فقط کامپوننت هامون داخلش باشن به تفکیک فولدر و استوری هاشون و استایل ها و تست ها.
  • فولدر hooks: اینجا هوک هایی رو قرار میدیم که پر استفاده هستن.
  • فایل index.ts: همه component ها و hook ها رو اینجا import میکنیم.
  • فایل styles.css: استایل های global و مخصوصا استایل های tailwind رو اینجا قرار میدیم.

شمایل داخل فولدر کامپوننت ها:

من برای نمونه ۳ تا کامپوننت قرار دادم اینجا و همه شون رو داخل فایل index.ts آوردم که جای دیگه بشه خوند
من برای نمونه ۳ تا کامپوننت قرار دادم اینجا و همه شون رو داخل فایل index.ts آوردم که جای دیگه بشه خوند


و داخل یه دونه از این کامپوننت ها هم این شکلیه:

استوری هاش، استایل هاش، خود کامپوننت به همراه تایپ هاش. بعدا میتونید تست هاش هم بذارید اینجا
استوری هاش، استایل هاش، خود کامپوننت به همراه تایپ هاش. بعدا میتونید تست هاش هم بذارید اینجا


دقت کنید که ساختار این فولدر ها و فایل ها و ... دست خودتونه. من این مدلی مینویسم معمولا ولی شما هر طور که دوست دارید بذاریدشون. نکته مهمش فقط اینه که یه دونه فایل index باید داشته باشن که بتونیم تو جاهای دیگه import شون کنیم.


استایل ها

حالا نوبت نصب بقیه کتابخونه هاست مثل tailwind و styled-components. من از این ۲ تا برای استایل ها استفاده می‌کنم ولی شما میتونید از هرچی دوست داشتید استفاده کنید. خوبی tailwind اینه که فقط استایل هایی رو به صفحه اضافه میکنه که استفاده شده و چیز اضافی تولید نمیکنه. styled-components هم برای جاهایی که tail نمیتونه کارمونو راه بندازه به درد میخوره.

برای styled-components:

yarn add styled-components

برای نصب و ستاپ tailwind:

yarn add -D tailwindcss postcss autoprefixer postcss-import

دقت کنید که tailwind یک devDependency هست ولی styled-components یک dependency.


بعد از دریافت tailwind باید کارای ستاپش هم انجام بدیم که خیلی کار سختی نیست، توی root پروژه یه دونه فایل به اسم tailwind.config.js و یه فایل دیگه به اسم postcss.config.js بسازید و این ها رو توش قرار بدید.

داخل اون فایل styles.css که توی src هم بود این ۳ خط رو فقط کافیه بذارید اولش.

@tailwind base; @tailwind components; @tailwind utilities;

خب ستاپ tailwind تمومه، styled-components هم کار خاصی نداره. فقط یه دونه devDependency داره برای ساپورت typescript که توی قسمت بیلد نصبش می‌کنیم.


استوری بوک

الان که کارمون با ساختن کامپوننت ها و اضافه کردن tail و styled تموم شد، باید یه محیطی فراهم کنیم که بتونیم توش کامپوننت هامون رو ببینیم برای همین از Storybook استفاده می‌کنیم. قبلا تو یه مطلب مفصل در موردش صحبت کردم که میتونید اینجا پیداش کنید:

https://virgool.io/@hesanam/%D8%A7%D8%B3%D8%AA%D9%88%D8%B1%DB%8C-%D8%A8%D9%88%DA%A9-%D9%88-react-%DB%8C%D9%87-%D8%AA%D8%B1%DA%A9%DB%8C%D8%A8-%D9%87%DB%8C%D8%AC%D8%A7%D9%86-%D8%A7%D9%86%DA%AF%DB%8C%D8%B2-b53uegmbw5rj

توی این مطلب کامل توضیح دادم. اما اینجا برای این پروژه کارمون نسبتا راحته. توی root اصلی پروژه این دستور رو اجرا کنید:

npx storybook init

این دستور هم dependency ها رو نصب میکنه، هم فایل های اصلی مورد نیاز رو براتون میسازه. بعد از اینکه کار این دستور تموم شد باید کاری کنیم که استوری بوک استایل های tailwind رو اجرا کنه، برای همین وارد فولدر storybook. بشید و محتویات فایل preview.js و main.js رو به این شکل تغییر بدید. (وارد لینک بشید و فایل ها رو کپی کنید و حتما کامنت هاش رو بخونید)

این کار برای اینکه که storybook از webpack برای بیلد کردن کامپوننت ها استفاده میکنه و کاری که ما باید انجام بدیم اینه که این کانفیگ رو دستکاری کنیم. خب بعد اینکه محتوای فایل ها رو تغییر دادید باید یه مشت کتابخونه نصب کنید و ۲ تا دونه هم حذف کنید. اینا رو نصب کنید:

yarn add -D @storybook/addon-postcss @storybook/builder-webpack5 @storybook/manager-webpack5 postcss-loader style-loader less less-loader eslint-plugin-storybook css-loader babel-loader

و این ها رو حذف کنید:

yarn remove @storybook/builder-webpack4 @storybook/manager-webpack4

بعد از اینکار دستور yarn storybook رو اجرا کنید و استوری بوک تون باید بیاد بالا. اگه مشکل داشت فایل ها رو یه بار دیگه چک کنید یا کامنت بذارید زیر همین پست.

همونطور که قبلا هم دیدید یه سری فایل داشتیم که با stories تموم میشد اسمشون، میتونید محتواش رو توی اون مقاله ببینید ولی خلاصه اش میشه این:

نمونه استوری که برای Card نوشتم
نمونه استوری که برای Card نوشتم


برای بقیه هم میتونید بنویسید. فایل های استوری ها رو میتونید اینجا پیدا کنید.


بیلد نهایی

اینجاست که نوبت rollup میرسه، از rollup برای باندل کردن نهایی استفاده می‌کنیم که بتونیم این پروژه رو تبدیل به یک پکیج کنیم و بتونیم جاهای دیگه ازش استفاده کنیم. کانفیگ rollup کار نسبتا ساده ای هست ولی یکسری نکات ظریف داره که باید دقت کنید. اول dependency های لازم رو نصب کنید:

yarn add -D rollup rollup-plugin-babel rollup-plugin-node-resolve rollup-plugin-peer-deps-external rollup-plugin-postcss rollup-plugin-typescript2 babel-plugin-import @babel/core @rollup/plugin-commonjs @rollup/plugin-node-resolve rollup-plugin-less @types/styled-components

بعد باید یه دونه فایل rollup.config.js توی root پروژه ایجاد کنید. محتوای فایلش رو از اینجا میتونید پیدا کنید. (وارد لینک بشید و محتواش رو کپی کنید)


یه تغییر کوچیک هم باید داخل فایل package.json ایجاد کنیم. وارد فایل بشید و این مقادیر رو اضافه کنید:

&quotmain&quot: &quotbuild/index.js&quot, &quotmodule&quot: &quotbuild/index.esm.js&quot, &quottypes&quot: &quotbuild/src/index.d.ts&quot, &quotfiles&quot: [&quotbuild&quot],

این مقادیر به پکیج های دیگه میگن که اگر میخوان از این پکیج استفاده کنن کدوم فایل ها رو باید بخونن.

  • برای commonjs آدرس build/index.js
  • برای ESModules آدرس build/index.esm.js
  • برای خوندن تایپ ها از build/src/index.d.ts
  • و files هم میگه که زمان publish شدن کدوم فایل ها رو توی پکیج قرار بده

بعد باید حتما react و react-dom رو توی قسمت peerDependency ها هم اضافه کنیم، اینطوری اگه تو پروژه تعیین میشه که حتما این dependecy ها رو باید داشته باشه. بنابراین قسمت peerDependecy های فایل package.json این شکلی میشه:

&quotpeerDependencies&quot: {
&quotreact&quot: &quot>=16.8.0&quot,
&quotreact-dom&quot: &quot>=16.8.0&quot
},


توضیح فایل کانفیگ rollup که استفاده کردیم:

  • قسمت اول مربوط به input هست که آدرس فایل index داخل فولدر src رو بهش دادیم
  • قسمت دوم مربوط به output هست که آدرس رو از فایل package.json خوندیم. (این فایل رو بالاتر ادیت کردیم)
  • قسمت external که اشاره میکنه به پکیج های اکسترنال که نمیخوایم rollup کاری داشته باشه باهاشون (اگه اشتباه میگم بهم بگید حتما)
  • و در آخر plugins که توضیحش بیشتره که مطلب دیگه خیلی طولانی میشه، اونا رو به همون شکل اونجا قرار بدید.


برای اینکه مطمئن بشیم همه چیز درست سر جاش قرار گرفته، توی package.json یه دونه script جدید بسازید به اسم build مثلا و مقدارش رو rollup -c قرار بدید.

و در نهایت دستور

yarn build

اگه همه چیز درست باشه باید اینو ببینید:

بیلد شده و آماده برای پرواز
بیلد شده و آماده برای پرواز


نکته مهم: اینجا هیچکدوم از روش های optimization روی بیلد نهایی استفاده نشده، بنابراین حجم باندل نهایی تون خیلی بالاست. برای اینکه مطلب طولانی نشه من اونا رو skip کردم ولی توی پروژه های واقعی باید حتما برای نقشه داشته باشید

تست پکیج

بعد از اینکه این کار ها انجام شد، لازمه که تست کنید ببینید واقعا کار میکنه؟ توی یه پروژه ری-اکتی دیگه باید import اش کنید و ببینید چطور کار میکنه و اگه خطایی داره برطرف کنید. یه راهش اینه که توی npm منتشر اش کنید ولی خب برای یه پکیج private چنین کاری هم نشدنیه و هم کار احمقانه ای هست. چون ممکنه کامپوننت های شما مختص به پروژه خودتون باشه و نمیخواید دست کس دیگه ای بیوفته. بنابراین میتونید توی پروژه مقصد دستور npm link به همراه اسم کتابخونه تون رو بزنید که یه کپی از پروژه توی فولدر node_modules اش ایجاد کنه و از اون استفاده کنه.

اینطوری میتونید بی دردسر تستش هم بکنید و اگر نهایی شد منتشرش کنید. (حالا یا روی یه private npm server یا روی ریپو اصلی npm)

انتشار پکیج

وارد ساید npm بشید و اگه قبلا ثبت نام نکردید sign up کنید. بعد از اینکه ثبت نامتون تموم شد برید داخل پروژه دستور npm publish رو بزنید. احتمالا این ارور رو میبینید:

داره میگه که تو کی هستی بابا، اول برو خودتو احراز هویت کن?. خب حله پس این دستور رو بنویسید:

npm adduser

بعد ازتون username و password میخواد. وارد کنید. اگر two-step verification هم فعال باشه ازتون میخواد رمز یکبار مصرفی که به ایمیل تون فرستاده رو هم وارد کنید که برید انجامش بدید. در نهایت میگه که شما لاگین شدید و تبریک این حرفا.

یه بار دیگه بزنید npm publish

حله
حله


حالا دیگه پکیج تون روی npm وجود داره. میتونید خیلی راحت توی هر پروژه ی دیگه ای که نیاز بود خیلی راحت بزنید

npm install hesanam-lib

و پکیج تون رو نصب کنید. دقت کنید که برای این مقاله من از این روش استفاده کردم ولی احتمالا برای پروژه های داخل سازمانی یا باید npm private تهیه کنید که پولی هست و یا از راه حل هایی مثل monorepo و ... استفاده کنید که توضیح اونا مفصله.


خب تبریک میگم اگه تا اینجای مطلب رو همراه من اومدید!



rollup pluginstyled componentsحسانپکیج npmreact
برنامه نویس از جلو
شاید از این پست‌ها خوشتان بیاید