التخلص من تطبيق create-react-app وإنشاء نموذج خاص بك لتطبيقات React

يدعو مؤلف المقال ، الذي ننشر ترجمته اليوم ، مطوري React إلى الابتعاد عن استخدام create-react-app(CRA) وإنشاء نموذجهم الخاص لتطبيقات React. هنا سنتحدث عن مزايا وعيوب CRA ، وكذلك سيتم اقتراح حل يمكن أن يحل محل create-react-app.







ما هو CRA؟



إنشاء تطبيق React عبارة عن مجموعة من الأدوات التي تم إنشاؤها وصيانتها بواسطة المطورين في Facebook. CRA مخصص لإنشاء تطبيقات React النموذجية بسرعة. باستخدام CRA ، يتم إنشاء قاعدة مشروع React بأمر واحد.



قدرات CRA



  • يسمح لك CRA بإنشاء قاعدة لمشروع React بأمر واحد:



    npx create-react-app my-app
    
  • استخدام CRA يحفظ المطور من الحاجة إلى دراسة متعمقة للأدوات المساعدة. يمكن للمطور التركيز على React وعدم القلق بشأن إعداد Webpack و Babel وآليات الأدوات الأخرى.
  • عند تطبيق CRA ، يحتاج المطور فقط إلى تبعية واحدة ذات صلة ببناء المشروع. هذا هو react-scripts. تتضمن هذه التبعية جميع تبعيات التجميع الأخرى ، ونتيجة لذلك اتضح ، على سبيل المثال ، أن أمرًا واحدًا يكفي لتثبيت التبعيات وتحديثها:



    npm install react-scripts@latest
    


CRA



  • CRA . eject, CRA- . customize-cra react-app-rewired, .
  • CRA . React- , React- . CRA « », , react-scripts — , React-. , , , react-scripts — , , «» (Babel) (Webpack), React- . , , , .
  • يبدو لي أن CRA مثقلة بالفرص التي ، في بعض المشاريع ، قد يتضح أنها مجهولة. على سبيل المثال ، بذرة التطبيق التي تم إنشاؤها باستخدام CRA لدعم SASS. بمعنى ، إذا كان مشروعك يستخدم CSS عاديًا أو أقل ، فلن يكون دعم SASS ضروريًا تمامًا. هنا ، إذا كنت مهتمًا ، يوجد ملف package.jsonتطبيق CRA بعد الأمر eject. هذا الملف "unrolled" التبعيات المقدمة سابقا react-scripts.


أحد البدائل لـ CRA هو تطوير القالب الخاص بك لإنشاء مشاريع React الأساسية بسرعة.



بديل لـ CRA



في تطوير بديل لـ CRA ، سنزوده بالقدرة على إنشاء مشاريع React الأساسية بسرعة باستخدام أمر واحد فقط. هذا يكرر إحدى الميزات المفيدة create-react-app. ونحن ، بالطبع ، لن ننقل عيوب CRA إلى نظامنا ، ونقوم بتثبيت التبعيات وإنشاء المشروع بشكل مستقل. لن يتضمن مشروعنا ميزتين أخريين مفيدتين من CRA (تخليص المطور من الحاجة إلى دراسة الآليات المساعدة ومخطط "التبعية الواحدة") ، نظرًا لأنها تحمل أيضًا عيوبًا (إخفاء الآليات الداخلية للأنظمة الفرعية المساعدة عن المطور وتعقيد تخصيص تكوينات بناء المشروع الخاصة بهم) ...



هذا هو المستودع الذي يحتوي على جميع الأكواد التي سنناقشها في هذه المقالة.



لنبدأ بتهيئة المشروع بالأدوات npmوتهيئة مستودع git الخاص به:



npm init
git init


لنقم بإنشاء ملف .gitignoreبالمحتوى التالي:



node_modules
build


سيسمح لنا هذا بعدم تضمين المجلدات الموجودة أسماؤها في الملف في المستودع.



الآن دعنا نفكر في التبعيات الأساسية التي نحتاجها لبناء وتشغيل تطبيق React.



مكتبات React و reaction-dom



هذه هي تبعيات وقت التشغيل الوحيدة التي نحتاجها:



npm install react react-dom --save


Transpiler (بابل)



يحول مترجم Babel كود ECMAScript 2015+ المتوافق مع المعايير إلى كود يعمل في كل من المتصفحات الجديدة والقديمة. تُستخدم Babel أيضًا ، بفضل استخدام الإعدادات المسبقة ، لمعالجة كود JSX:



npm install @babel/core @babel/preset-env @babel/preset-react --save-dev


هذا ما يبدو عليه تكوين Babel البسيط لتشغيل تطبيقات React وتشغيلها. يمكن إضافة هذا التكوين إلى ملف .babelrcأو إلى package.json:



{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ]
}


بابل يدعم العديد من الإعدادات المسبقة و الإضافات . يمكن إضافتها إلى المشروع عند الحاجة.



Bandler (Webpack)



تعد حزمة Webpack مسؤولة عن بناء المشروع ، وتشكيل ملف تطبيق واحد (حزمة) بناءً على كود المشروع ورمز تبعياته. عند استخدام تقنيات تحسين المشروع مثل تقسيم الكود ، يمكن أن تتضمن حزمة التطبيق ملفات متعددة.



npm install webpack webpack-cli webpack-dev-server babel-loader css-loader style-loader html-webpack-plugin --save-dev


يبدو تكوين Webpack البسيط لبناء حزم تطبيقات React كما يلي:



const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
  },
  resolve: {
    modules: [path.join(__dirname, 'src'), 'node_modules'],
    alias: {
      react: path.join(__dirname, 'node_modules', 'react'),
    },
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
    }),
  ],
};


يمكن إضافة محمل إقلاع مختلف هنا ، وفقًا لاحتياجات تطبيق معين . إذا كنت مهتمًا بهذا الموضوع ، ألق نظرة على المواد الخاصة بي ، حيث أتحدث عن تكوينات Webpack التي يمكنك استخدامها لإعداد تطبيقات React لاستخدامها في الإنتاج.



هذه هي كل التبعيات التي نحتاجها. لنقم الآن بإضافة ملف HTML للقالب ومكوِّن رطل React إلى المشروع.



قم بإنشاء مجلد في دليل المشروع srcوإضافة ملف إليه index.html:



<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>React Boilerplate</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>


أنشئ مكوِّن React في نفس المجلد HelloWorld:



import React from 'react';

const HelloWorld = () => {
  return (
      <h3>Hello World</h3>
  );
};

export default HelloWorld;


أضف الملف إلى نفس المجلد index.js:



import React from 'react';
import { render } from 'react-dom';

import HelloWorld from './HelloWorld';

render(<HelloWorld />, document.getElementById('root'));


وأخيرًا ، أضف إلى package.jsonتوصيفات البرامج النصية لإطلاق ( start) وبناء ( build) المشروع:



"scripts": {
    "start": "webpack-dev-server --mode=development --open --hot",
    "build": "webpack --mode=production"
  }


هذا كل شئ. لدينا الآن تطبيق React قابل للتطبيق تحت تصرفنا. يمكنك التحقق من ذلك عن طريق تشغيل الأوامر npm startو npm run build.



الآن دعنا نجهز نظامنا بالقدرة على إعداد قالب مشروع بأمر واحد. وهذا يعني أننا سنعيد إنشاء إحدى نقاط القوة في CRA. سنستخدم ملف JS قابل للتنفيذ والذي سيتم استدعاؤه عند إدخال الأمر المناسب في سطر الأوامر. على سبيل المثال ، قد يبدو أمر مثل هذا على النحو التالي:



reactjs-boilerplate new-project


لتنفيذ هذه الفكرة ، سنستخدم قسم bin في الملف package.json.



أولاً ، قم بتثبيت الحزمة fs-extra :



npm i fs-extra


لنقم الآن بإنشاء ملف JS قابل للتنفيذ start.js، والذي سيكون موجودًا في مجلد binمشروعنا. لنضع الكود التالي في هذا الملف:



#!/usr/bin/env node
const fs = require("fs-extra");
const path = require("path");
const https = require("https");
const { exec } = require("child_process");

const packageJson = require("../package.json");

const scripts = `"start": "webpack-dev-server --mode=development --open --hot",
"build": "webpack --mode=production"`;

const babel = `"babel": ${JSON.stringify(packageJson.babel)}`;

const getDeps = (deps) =>
  Object.entries(deps)
    .map((dep) => `${dep[0]}@${dep[1]}`)
    .toString()
    .replace(/,/g, " ")
    .replace(/^/g, "")
    //  ,     ,    
    .replace(/fs-extra[^\s]+/g, "");

console.log("Initializing project..");

//     npm-
exec(
  `mkdir ${process.argv[2]} && cd ${process.argv[2]} && npm init -f`,
  (initErr, initStdout, initStderr) => {
    if (initErr) {
      console.error(`Everything was fine, then it wasn't:
    ${initErr}`);
      return;
    }
    const packageJSON = `${process.argv[2]}/package.json`;
    //  ,   
    fs.readFile(packageJSON, (err, file) => {
      if (err) throw err;
      const data = file
        .toString()
        .replace(
          '"test": "echo \\"Error: no test specified\\" && exit 1"',
          scripts
        )
        .replace('"keywords": []', babel);
      fs.writeFile(packageJSON, data, (err2) => err2 || true);
    });

    const filesToCopy = ["webpack.config.js"];

    for (let i = 0; i < filesToCopy.length; i += 1) {
      fs.createReadStream(path.join(__dirname, `../${filesToCopy[i]}`)).pipe(
        fs.createWriteStream(`${process.argv[2]}/${filesToCopy[i]}`)
      );
    }
    // npm,   ,   .gitignore,        ;    .     GitHub-  raw- .gitignore
    https.get(
      "https://raw.githubusercontent.com/Nikhil-Kumaran/reactjs-boilerplate/master/.gitignore",
      (res) => {
        res.setEncoding("utf8");
        let body = "";
        res.on("data", (data) => {
          body += data;
        });
        res.on("end", () => {
          fs.writeFile(
            `${process.argv[2]}/.gitignore`,
            body,
            { encoding: "utf-8" },
            (err) => {
              if (err) throw err;
            }
          );
        });
      }
    );

    console.log("npm init -- done\n");

    //  
    console.log("Installing deps -- it might take a few minutes..");
    const devDeps = getDeps(packageJson.devDependencies);
    const deps = getDeps(packageJson.dependencies);
    exec(
      `cd ${process.argv[2]} && git init && node -v && npm -v && npm i -D ${devDeps} && npm i -S ${deps}`,
      (npmErr, npmStdout, npmStderr) => {
        if (npmErr) {
          console.error(`Some error while installing dependencies
      ${npmErr}`);
          return;
        }
        console.log(npmStdout);
        console.log("Dependencies installed");

        console.log("Copying additional files..");
        //     
        fs.copy(path.join(__dirname, "../src"), `${process.argv[2]}/src`)
          .then(() =>
            console.log(
              `All done!\n\nYour project is now ready\n\nUse the below command to run the app.\n\ncd ${process.argv[2]}\nnpm start`
            )
          )
          .catch((err) => console.error(err));
      }
    );
  }
);


الآن ، دعنا نربط ملف JS القابل للتنفيذ بالأمر من package.json:



"bin": {
    "your-boilerplate-name": "./bin/start.js"
  }


لنقم بإنشاء ارتباط محلي للحزمة:



npm link


الآن ، بعد تنفيذ هذا الأمر ، إذا قمنا بتنفيذ أمر من النموذج في المحطة الطرفية your-boilerplate-name my-app، فسيتم استدعاء ملفنا القابل للتنفيذ start.js. فإنه سيتم إنشاء مجلد جديد باسم my-appنسخ الملفات package.json، webpack.config.jsو .gitignore، وكذلك المجلد src، وتثبيت تبعيات المشروع الجديد my-app.



رائع. الآن يتم تشغيل كل شيء على جهاز الكمبيوتر الخاص بك ويسمح لك بإنشاء مشاريع React الأساسية بتكوين البناء الخاص بها باستخدام أمر واحد.



يمكنك المضي قدمًا ونشر القالب الخاص بك في سجل npm . للقيام بذلك ، تحتاج أولاً إلى إرسال المشروع إلى مستودع GitHub. ثم اتبع هذه التعليمات.



تهانينا! لقد أنشأنا للتو بديلاً في بضع دقائق فقط create-react-app. لا يتم تحميل الحل الخاص بنا بميزات غير ضرورية (يمكن إضافة التبعيات إلى المشاريع التي تستند إليها عند الحاجة). باستخدامه ، يمكنك بسهولة ضبط تكوين بناء المشروع ليناسب احتياجاتك.



بالطبع ، حلنا في أضيق الحدود. لا يمكن اعتبار المشاريع التي تم إنشاؤها على أساسها جاهزة للاستخدام في الإنتاج. من أجل إعدادهم للعمل الحقيقي ، نحتاج إلى تجهيز القالب الخاص بنا ببعض إعدادات Webpack المسؤولة عن تحسين تصميمات المشروع.



لقد أعددت نموذج تفاعلات النموذج المعياريمما يسمح لك بإنشاء مشاريع جاهزة للإنتاج. يستخدم التكوين المناسب للبناء والفحص والخطافات المسؤولة عن فحص المشروع قبل إنشاء الالتزامات. جرب هذا النموذج. إذا كانت لديك أي أفكار لتحسينها ، أو إذا قررت المساهمة في تطويرها ، فانضم إلى العمل عليها.



النتيجة



إليكم ما تحدثنا عنه في هذا المقال:



  • لقد غطينا الإيجابيات والسلبيات create-react-app.
  • لقد طبقنا في مشروعنا ميزة CRA مفيدة لإنشاء تطبيقات React فارغة بأمر واحد. وتخلصنا من عيوب CRA.
  • لقد زودنا مشروعنا بالحد الأدنى من تكوينات Webpack و Babel المطلوبة لإنشاء تطبيقات React وتشغيلها.
  • أنشأنا مكون React HelloWorld.js، ووفرنا القدرة على بناء مشروع وتشغيله باستخدام خادم التطوير.
  • أنشأنا ملف JS قابل للتنفيذ وربطناه بالأمر المناسب باستخدام قسم binالملف package.json.
  • لقد استخدمنا الفريق npm linkلإنشاء رابط محلي لمشروعنا ونكون قادرين على إنشاء مشاريع أساسية جديدة منه مع فريق واحد.


آمل أن تساعدك هذه المادة في تطوير المشاريع بناءً على React.



هل تستخدم تطبيق create-react-app عند إنشاء مشروعات React جديدة؟






All Articles