Back to "आपके फ्रन्टएण्ड बिल्ड पाइपिंग का आधुनिक रूप से पता लगाया जा रहा है: CDNNs से बन रहा है"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Frontend Tailwind Webpack

आपके फ्रन्टएण्ड बिल्ड पाइपिंग का आधुनिक रूप से पता लगाया जा रहा है: CDNNs से बन रहा है

Tuesday, 11 November 2025

परिचय

पिछले साल, मैंने ठोकर खाई है, प्रयोग किया है, टूटी हुई चीजों का उपयोग किया है, और धीरे - धीरे आधुनिक आधुनिक निर्मित इस ब्लॉग के लिए। यह कुछ गुरू-शिक्षित नहीं था। यह परीक्षण और त्रुटि, बहुत से त्रुटि, और लगन के एक स्पष्ट दर्शन से प्रेरित था कि मैं क्या प्राप्त करना चाहता था।

मैं एक फ्रन्टी या एक वेब-विप जादूगर नहीं हूँ. मैं एक है. NNT डेवलपर जो सीN-आधारित निर्भरता की सीमाओं के साथ निराश हो गया है और फैसला किया कि वहाँ एक बेहतर तरीका होना था. इस लेख में गड़बड़ी, यह सरल यात्रा यात्रा यात्रा से आसान है. <script> टैग जो कि वास्तव में काम करता है एक आधुनिक ब्रीजिंग को सूचित नहीं कर रहे हैं.

मैंने गलतीओं के साथ बहुत कुछ की (जो मैं दस्तावेज़ करूँगा), घंटे जो कि डिबगिंग cacratwaggin त्रुटि, और शायद फिर से पुनः लोड किया node_modules लेकिन मैंने लगन से काम लिया, और इस बात को सही साबित करने के इरादे से मैंने बहुत कुछ सीखा ।

यदि आप एक .NT डेवलपर वेब हालेल कॉन्फ़िगरेशन फ़ाइलें को घूर रहे हैं... ... आप पृथ्वी पर खुद को क्या मिल गया है सोच रहे हैं - यह लेख आपके लिए है.

मैं एक पुराना वेब प्रदर्शनर हूँ, डायल - अप के प्रारंभिक दिनों में मैं पैसे के लिए बनाया गया पहली साइट में... (कि पर्ल में एक शानदार बैकएण्ड नहीं था... एक और समय के लिए कहानी) बर्फ की साइट थी जो एक स्वचालित फोन लाइन से बंद हो गया था।

उन दिनों चिंता काफ़ी अलग थी. जावास्क्रिप्ट लगभग अज्ञात था. मुझे लगता है कि पानी भी कुएँ थे (उन दिनों मैं था) div नेटस्केप था layer) और आप LUCKT हो अगर आपके उपयोक्ता एक 56K कनेक्शन था. तो मैंने संतुलित करने के लिए सीखा (जब तक मेन्यू वस्तुओं के लिए टाइल्ड छवि के रूप में) ...

बाद में, मैं वेब फार्म में एक स्वचालित चित्र उपकरण पर काम भी किया था - यह भयानक था: यह एक पृष्ठ से छोटी तस्वीरें लाया, सीएसएस और एक स्पाइट छवि स्वचलित बनाया. लेकिन मेरे समय की तरह, यह नहीं होना था.

कम से कम, यह एक जुनून है कि मैं अपने पूरे पेशे को ले लिया है. कोई भी एक धीमी वेबसाइट पसंद करता है!

उचित होने के लिए, सीडीNINs स्वाभाविक रूप से बुराई नहीं कर रहे हैं.

पूरा- निर्धारित: इस ब्लॉग पर बिना किसी रोक - टोक के लिखा गया है. यह नहीं है आवश्यकता है कभी - कभी मुझे थोड़ा अजीब - सा सामान बनाने का सबसे अच्छा तरीका होता है, ताकि मैं थोड़ा अजीब - सा और दस्तावेज़ के सफर के बारे में कुछ सीख सकूँ ।

सीडीएनएस के साथ समस्या

शुरू - शुरू में मेरा तरीका सीधा था:

<!-- Old CDN-based approach -->
<script src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">

यह सब देखकर कई लोग निराश हो जाते हैं:

  • यूटिलिटीज़ समस्याएँ: CDNNs नीचे चला जाता है. मैं unpaks और facks बाहर है. जब वे नीचे हैं, आपकी साइट टूट गया है
  • व्यवहार अप्रचलित किया जा सकता है: सीडीएन प्रतिक्रिया भिन्‍न - भिन्‍न रूप से भिन्‍न हो सकती है ।
  • टाइमिंग विषय: जब स्क्रिप्ट को एक दूसरे के सापेक्ष लोड किया जाए तो आपके ऊपर कोई नियंत्रण नहीं है. इस कारण मुझे लाइब्रेरी आरंभ से अन्तहीन सिरदर्द हो गया है
  • बहु एचटीटीपी निवेदन: हर लाइब्रेरी को एक अलग निवेदन की आवश्यकता है, यहाँ तक कि HTTP/2 के साथ
  • कोई पेड़ का गर्भ नहीं: आप पूरे लाइब्रेरी को डाउनलोड करते हैं, भले ही आप सिर्फ इसका भिन्न इस्तेमाल करें
  • संस्करण बहाव: CDNNS शायद अलग संस्करणों में सेवा करे जब तक आप उन्हें साफ - साफ न कर लें, और यहाँ तक कि पिन्ड संस्करण CDN प्रबंधन के दौरान अलग तरीके से व्यवहार कर सकते हैं
  • बिल्ड समय की अनिश्‍चितता: जब तक उपयोगकर्ता द्वारा रिपोर्ट नहीं दी जाती है तब तक सहेजे जाने का कोई रास्ता नहीं
  • सीमा समायोजनमरे हुए कोड को पूरी तरह से मिटाया नहीं जा सकता
  • ऑफ़लाइन विकासकी जरूरत है: इंटरनेट कनेक्ट, जो ट्रेनों या विमानों पर काम करते वक्‍त परेशान है

तो मैं नियंत्रण करना चाहता था ... वास्तव में क्या मेरी साइट का नियंत्रण और काम की जरूरत है. मैं केवल जो मैं जरूरत थी उसे इकट्ठा करना चाहता था, सुनिश्चित करना चाहता था, भरोसेमंद लोड करने के लिए, और प्रदर्शन के लिए अनुकूल. यह सीनेट से दूर और एक bunding पक्ष की ओर.

वे वहाँ सेट करने के लिए आसान कर रहे हैं, और HTTP/2 और HTTP/3 गुणा करने के साथ, बहुत कम है यह करने के लिए इस्तेमाल किया जा सकता है. कई परियोजनाओं, विशेष रूप से छोटे लोगों या मॉडलों के लिए, सीडी एन एक पूरी तरह से सही विकल्प रहता है. लेकिन एक उत्पादन स्थल के लिए जहाँ मैं नियंत्रण चाहता था, स्थिर, अटली, और अधिक बुद्धि.

आज के जंगली जानवर का आना

मेरा मौजूदा सेटअप सारा जावास्क्रिप्ट विस्तार वेबपैक तथा पोस्ट कहीं भी सीएसएस के माध्यम से लागू होता है.

Vite के बजाय वेब बैग क्यों?

तकनीकी विवरणों में परिवर्तन करने से पहले, मुझे कमरे में हाथी को संबोधित करना चाहिए: जब विट, रोल अप, ई. एस.

ईमानदार जवाब सरल है: मैं पहले से ही वेब बैग पता था.

जब मैं अपने "मिंग वेब विकास" पाठ्यक्रम को सिखाने के लिए बड़े पैमाने पर उपयोग किया, और यह मैं समझ गया था उपकरण था। जब मैं इस ब्लॉग का निर्माण करने का फैसला किया गया था, मैं पहले से ही एक पहाड़ी वक्र का सामना कर रहा था - जब पेड़-चिंग, कोड अपिंग, मॉड्यूल, पोस्ट, पोस्ट, और इस सब कोर के साथ विस्तार के लिए।

यह आम तौर पर एक अच्छा अभ्यास है जब परियोजना पर काम करते हैं; 'नया' की सीमा 'न्यू' की सीमा. यह अनिश्‍चितता के लिए आसान है.

"एक पूरी तरह से नया निर्माण उपकरण" जोड़ कि अनावश्यक लग रहा था. वेब बैग काम करता है. यह प्रौढ़ है. यह उत्कृष्ट दस्तावेज और एक विशाल वातावरण है. सबसे महत्वपूर्ण बात है, मैं अपनी ऊर्जा को सीखने पर केंद्रित कर सकता है धारणाएँ किसी खास औज़ार के पहचान - पता लगाने के बजाय आधुनिक शोचना के बारे में.

क्या तेज़ है? बिल्कुल. Vite का विकास सर्वर स्थानीय ईएस मॉड्यूलों तथा ईएस- पॉक्सिंग का निर्माण बहुत तेजी से वेब बैग से है। सैकड़ों मॉड्यूलों के साथ बड़े परियोजनाओं के लिए, परिवर्तन नाटकीय है।

क्या आपको नई परियोजना के लिए वीाइट इस्तेमाल करना चाहिए? शायद, हाँ. यदि आप ताजा करने के लिए शुरू कर रहे हैं और मौजूदा वेब बैग ज्ञान नहीं है, Vite संभवतः बेहतर विकल्प है. यह तेजी से, सरल करने के लिए सरल है, और सामने उपकरण खोलने के लिए आधुनिक कदम का प्रतिनिधित्व करता है.

क्या मैं वेब बैग का उपयोग करने का पछतावा करता हूँ? और ईमानदारी से, इस ब्लॉग के पैमाने के लिए, वेबविल और Vite के बीच अंतर है - हम विकास के विकास समय में बात कर रहे हैं।

यह है कि कैसे मैं सामान का एक महत्वपूर्ण पहलू है, शुरू के साथ क्या EASY और उस नींव से निर्माण.

यहाँ विस्तृत सबक है कि उन्‍नति से सिद्धता पर विजय प्राप्त होती है. मैं सप्ताह "सबसे अच्छा" पैकिंग, tuncher की तुलना करने, आलेखों की तुलना में पढ़ने, और निर्णय पर एक आनंद प्राप्त करने के लिए खर्च कर सकता था. इसके बजाय, मैं वह उपकरण मैं जानता था, काम किया गया, और आगे बढ़ने के बजाय आगे बढ़ने के लिए. यह procttttttion मुझे सक्रिय किया.

शायद एक दिन मैं Vite में उत्प्रवासित हो सकता है. शायद मैं नहीं होगा. या किसी भी तरह, इस ब्लॉग में एक आधुनिक है, अति संभव रूप से कि काम करता है - और यह क्या बात है.

पैकेज स्ट्रक्चर

वह package.json अब दो अलग-अलग समूहों को बनाए रखता है. इस संरचना ने मुझे सही पाने के लिए कई प्रयास किए हैं - वास्तव में, Nuuget और Nuget बराबर हैं लेकिन nphm एक बहुत कम दोस्ताना है जब pucks जोड़ते हैं.

{
  "dependencies": {
    //NOTE - This is a pre-release of these enhancements, the 1.0.0 release is OUT NOW!
    "@mostlylucid/mermaid-enhancements": "^1.0.0-alpha0",
    "alpinejs": "^3.14.1",
    "codemirror": "5.65.13",
    "core-js": "^3.39.0",
    "easymde": "2.20.0",
    "flatpickr": "^4.6.13",
    "highlight.js": "^11.10.0",
    "highlightjs-cshtml-razor": "^2.1.1",
    "html-to-image": "^1.11.13",
    "htmx.org": "^2.0.1",
    "mermaid": "^11.0.2",
    "regenerator-runtime": "^0.14.1",
    "svg-pan-zoom": "^3.6.2"
  },
  //These are just used for build; not needed to RUN the app so we have a separate place for 'em
  "devDependencies": {
    "@babel/core": "7.26.9",
    "@babel/preset-env": "7.26.9",
    "@tailwindcss/aspect-ratio": "^0.4.2",
    "@tailwindcss/forms": "^0.5.7",
    "@tailwindcss/typography": "^0.5.12",
    "autoprefixer": "10.4.21",
    "babel-loader": "10.0.0",
    "cpx": "1.5.0",
    "css-loader": "7.1.2",
    "cssnano": "7.0.6",
    "daisyui": "^4.12.10",
    "mini-css-extract-plugin": "^2.9.4",
    "npm-run-all": "4.1.5",
    "postcss": "8.5.3",
    "postcss-cli": "11.0.1",
    "postcss-import": "^16.1.0",
    "rimraf": "6.0.1",
    "style-loader": "4.0.0",
    "tailwindcss": "3.4.17",
    "terser-webpack-plugin": "^5.3.10",
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4"
  }
}

डिपेंडेंसीज़ लाइब्रेरी स्थान पर आवश्यक हैं (अर्वूशन्स, HMMX, आसान, आदि.) डेविएशन्स निर्माण औज़ार (बज्भ्‍न, बाबेल, पोस्ट खोलेंर इत्यादि) हैं ।

स्क्रिप्ट बिल्ड करें

वह package.json स्क्रिप्ट ने गहरा प्रभाव डाला है:

{
  "scripts": {
    "clean": "rimraf ./.tmp ./wwwroot/css/dist ./wwwroot/js/dist",
    "copy:static": "cpx \"src/css/{raleway,easymde-overrides}.css\" \"wwwroot/css/dist\"",
    "copy:highlight": "cpx \"src/css/highlight/*.min.css\" \"wwwroot/css/highlight\"",
    "copy:all": "npm-run-all --parallel copy:static copy:highlight",
    "copy:watch": "cpx \"src/css/{raleway,easymde-overrides}.css\" \"wwwroot/css/dist\" --watch & cpx \"src/css/highlight/*.min.css\" \"wwwroot/css/highlight\" --watch",
    "tw:dev": "postcss ./src/css/main.css -o ./wwwroot/css/dist/main.css",
    "tw:prod": "postcss ./src/css/main.css -o ./wwwroot/css/dist/main.css --no-map --verbose",
    "tw:watch": "postcss ./src/css/main.css -o ./wwwroot/css/dist/main.css --watch",
    "js:dev": "webpack --env development",
    "js:prod": "webpack --mode production",
    "js:watch": "webpack watch --mode development",
    "dev": "npm-run-all clean --parallel copy:all tw:dev js:dev",
    "watch": "npm-run-all clean copy:all --parallel copy:watch tw:watch js:watch",
    "build": "npm-run-all clean copy:all --parallel tw:prod js:prod"
  }
}

यह सेटअप अलग चिन्ताओं को अलग करता है:

  • साफ करें: का प्रयोग कर पिछले बिल्ड आउटपुट हटाता है rimraf
  • नक़ल:* कार्य: स्थिर सीएसएस फ़ाइलों की नक़ल की जा रही है जिन्हें प्रक्रिया की आवश्यकता नहीं है (ये या तो 'कीफिंग') एक विशेष उद्देश्य के लिए की तरह मेरी मजेदार राकीटल फ़ॉन्ट को लोड कर रहे हैं या adkils जैसे कि प्रसंग स्विच स्विच करने के लिए.
  • टीटी:* कार्य: पोस्ट कहीं नहीं मिला
  • डा.:* कार्य: वेब संस्थापन के माध्यम से जावास्क्रिप्ट शैक्षिक करता है
  • सी/ सी/ बिल्डर: ज़रा सोचिए कि आप क्या कर सकते हैं ।

वह npm-run-all पैकेज तेजी से निर्माण के लिए समानांतर अंतराल सक्षम करता है.

आप नियत कर सकते हैं npm run build अपने स्थानीय निर्माण के दौरान स्वचालित चलाने के लिए लेकिन यह सीआई के लिए एक दर्द का एक सा है (आपको यह सुनिश्चित करने की आवश्यकता है).

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <SpaRoot>ClientApp\</SpaRoot>
  </PropertyGroup>

  <!-- Run npm install only when package.json changes -->
  <Target Name="NpmInstall" Inputs="$(SpaRoot)package.json" Outputs="$(SpaRoot)node_modules" BeforeTargets="Build">
    <Message Importance="high" Text="Running npm install in $(SpaRoot)" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm ci" />
  </Target>

  <!-- Run npm build before the .NET build -->
  <Target Name="NpmBuild" DependsOnTargets="NpmInstall" BeforeTargets="Build">
    <Message Importance="high" Text="Running npm run build in $(SpaRoot)" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
  </Target>

</Project>

यह करने के लिए सिर्फ अपने csprozj करने के लिए यह जोड़ने के लिए ... आप भी केवल डिबग करने के दौरान चलाने के लिए कह सकते हैं ... लेकिन मुझे लगता है कि यह गड़बड़ है. मैं सिर्फ इसे दस्ती रूप से चलाने के लिए पसंद करता हूँ. तो, मैं सिर्फ इसे चलाने के लिए पसंद करता हूँ. npm run watch सिर्फ वही करता है, जब किसी भी cs / js फ़ाइल में परिवर्तन यह ऑटो- रन पर आता है.

ध्यान दीजिए: बुरे लोगों की दुनिया में वे गर्म-बोर्ग दौड़ का उपयोग करते हैं जो कि बहुत चालाक है और आपको कृपा से घृणा करता है। NENT की कमजोर कोशिश।

वेब हाल्ट कॉन्फ़िगरेशन गहराई तक समर्थित नहीं है

वेब हॉलेज कॉन्फ़िगरेशन है जहां जादू होता है - और जहाँ मैं अपने समय की सबसे कठिन मुसीबतों का खर्च किया. यह पूरी तरह से अस्तित्व में नहीं था. यह अनगिनत sperm, स्टैकिंग, खोज, और वेब हॉल के माध्यम से पढ़ने की कोशिश कर रही है कि क्यों मेरा निर्माण ४७ फ़ाइलें बनाई जा रही हैं समझने की कोशिश कर रहे हैं.

यहाँ वर्तमान कॉन्फ़िगरेशन है (से. webpack.config.js) हर भाग क्या करता है की विस्तृत व्याख्या के साथ और क्यों यह वहाँ है:

const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');

module.exports = (env, argv) => {
    const isProduction = argv.mode === 'production';

    return {
        mode: isProduction ? 'production' : 'development',
        entry: {
            main: './src/js/main.js',
        },
        output: {
            filename: '[name].js',
            chunkFilename: '[name].[contenthash].js',
            path: path.resolve(__dirname, 'wwwroot/js/dist'),
            publicPath: '/js/dist/',
            module: true,
            clean: true,
        },
        experiments: {
            outputModule: true,
        },
        module: {
            rules: [
                {
                    test: /\.css$/i,
                    use: ['style-loader', 'css-loader'],
                },
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                ['@babel/preset-env', {
                                    targets: '> 0.25%, not dead',
                                    modules: false,
                                    useBuiltIns: 'usage',
                                    corejs: 3,
                                }],
                            ],
                        },
                    },
                },
            ],
        },
        resolve: {
            extensions: ['.js', '.mjs'],
            alias: {
                '@mostlylucid/mermaid-enhancements$': path.resolve(__dirname, 'node_modules/@mostlylucid/mermaid-enhancements/dist/index.min.js')
            }
        },
        optimization: {
            splitChunks: {
                chunks: 'all',
                minSize: 20000,
                maxSize: 100000,
                name: false,
            },
            runtimeChunk: {
                name: 'runtime',
            },
            minimize: isProduction,
            minimizer: isProduction ? [
                new TerserPlugin({
                    terserOptions: {
                        ecma: 2020,
                        compress: {
                            drop_console: true,
                            passes: 3,
                            toplevel: true,
                            pure_funcs: ['console.info', 'console.debug'],
                        },
                        mangle: {
                            toplevel: true,
                        },
                        format: {
                            comments: false,
                        },
                    },
                    extractComments: true,
                }),
            ] : [],
        },
        devtool: isProduction ? false : 'eval-source-map',
        performance: {
            hints: isProduction ? 'warning' : false,
        }
    };
};

कुंजी कॉन्फ़िगरेशन

कोड अलग करना तथा क्लंकिंग

optimization: {
    splitChunks: {
        chunks: 'all',
        minSize: 20000,
        maxSize: 100000,
        name: false,
    },
    runtimeChunk: {
        name: 'runtime',
    },
}

यह कॉन्फ़िगरेशन स्वचालित आपके कोड को छोटे भाग में विभाजित करता है:

  • फिर से कोशिश करें: 'सब': तुल्यकालित और अतुल्यकालिक आयात दोनों का विश्लेषण करता है
  • न्यूनतम आकार: 20000: सिर्फ मॉड्यूलों को 20K से बड़ा बनाने में ही एक भाग तैयार करता है
  • अधिकतम आकार: 100000: 100केबी से बड़ा विभाजन करने की कोशिश
  • बंद करें: वेब हाल ही में वेब हाल ही में एक अलग फ़ाइल में घूमता है जो लंबे समय से स्विच करने के लिए एक अलग फ़ाइल में घूम रहा है

अभ्यास में, यह अनेक फ़ाइलें बनाता है wwwroot/js/dist/:

  • main.js - आपका अनुप्रयोग प्रविष्टि बिन्दु
  • runtime.js - वेब हास मॉड्यूल तर्क लोड किया जा रहा है
  • [vendor].[contenthash].js - स्वचालित विभाजित विक्रेता फिर से करें
  • कोड- चौकों या आलसी- लोड मॉड्यूलों के लिए अतिरिक्त संयोजन

बाबुल का तख्तापलट

{
    test: /\.js$/,
    exclude: /node_modules/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: [
                ['@babel/preset-env', {
                    targets: '> 0.25%, not dead',
                    modules: false,
                    useBuiltIns: 'usage',
                    corejs: 3,
                }],
            ],
        },
    },
}

पुराने ब्राउज़रों का समर्थन करने के लिए बाबुल लेस आधुनिक जावास्क्रिप्ट:

  • लक्ष्य: मदद ब्राउज़र को >0.25% बाजार में हिस्सा देता है जो अभी भी बनाए गए हैं
  • मॉड्यूल: गलत: वेब बैग के लिए ईएस6 मॉड्यूल बनाए रखता है
  • उपयोग- इनिट: 'Ubin': आप जो उपयोग करते हैं उसके लिए सिर्फ बहुपंक्ति भरना शामिल करता है
  • कोस: 3बहुपंक्ति भर के लिए कोर- js संस्करण ३ इस्तेमाल करें

इसका अर्थ है कि मैं आधुनिक जावास्क्रिप्ट (जैसे किचक/ aswning, वैकल्पिक तार, नलबिंग) लिख सकता हूँ जब तक विस्तृत ब्राउज़र समर्थन बनाए रखने के दौरान।

उत्पादन न्यूनतम

minimizer: isProduction ? [
    new TerserPlugin({
        terserOptions: {
            ecma: 2020,
            compress: {
                drop_console: true,
                passes: 3,
                toplevel: true,
                pure_funcs: ['console.info', 'console.debug'],
            },
            mangle: {
                toplevel: true,
            },
            format: {
                comments: false,
            },
        },
        extractComments: true,
    }),
] : []

टी. वी.

  • **छिपा हुआ टैब (_o)**सभी मिटाएँ console.log() कथन
  • पास: 3: अधिकतम आकार कमी के लिए संपीडन तीन बार चलाएँ
  • शीर्ष तक: सही: शीर्ष-स्तर वेरिएबल नाम
  • साफ करें (_e): यदि चर में आबंटित हो तो भी विशिष्ट कंसोल विधियाँ मिटाएं
  • टिप्पणी: झूठे: आउटपुट से सभी टिप्पणियों को हटाएँ

इस ब्लॉग पर, यह आम तौर पर जावास्क्रिप्ट बंडल आकार को 60-70% से कम करता है जो अनमिनिट कोड की तुलना में होता है.

पिडगिन पिडगिन पाइपिंग

सीएसएस सीएसएस को कई प्लगइनों के साथ पोस्ट मानने के द्वारा प्रोसेस किया जाता है. यह कॉन्फ़िगरेशन (सेमी) postcss.config.js) वेब बैग की तुलना में दयालुतापूर्वक सरल है:

// postcss.config.js
module.exports = {
    plugins: {
        'postcss-import': {},
        tailwindcss: {},
        autoprefixer: {},
        cssnano: { preset: 'default' }
    }
}

अविष्टि कार्य इस तरह आगे आते हैं:

  1. पोस्ट्स- इम्प आयात: मरम्मत @import सीएसएस फ़ाइलों में कथन
  2. पूँछकीस: प्रक्रिया फ़्लिलल निर्देश बनाता है तथा यूटिलिटी क्लास तैयार करता है
  3. स्वचालित सहेजा जा रहा है: ब्राउज़र संगतता के लिए विक्रेता उपसर्ग जोड़ें
  4. नोबल गैस: अंतिम सीएसएस आउटपुट को न्यूनतम करता है

उछलना कॉन्फ़िगरेशन

वह tailwind.config.js फ़ाइल निर्दिष्ट करता है कि कहां भरा जाल क्लास के नाम की तलाश करता है. प्राप्त कर रहा है content सही पथ गंभीर था - एमआईएस एक पथ और दलदली जाल उन फ़ाइलों के लिए वर्ग नहीं तैयार करेगा:

module.exports = {
    content: ["./Views/**/*.cshtml", "./EmailSubscription/**/*.cshtml"],
    safelist: ["dark", "light"],
    darkMode: "class",
    theme: {
        fontFamily: {
            body: ["Raleway", "sans-serif"],
        },
        extend: {
            colors: {
                "custom-light-bg": "#ffffff",
                "custom-dark-bg": "#1d232a",
                primary: "#072344",
                secondary: "#00aaa1",
                // ... more custom colours
            },
        },
    },
    plugins: [
        require("@tailwindcss/aspect-ratio"),
        require("@tailwindcss/typography"),
        require("daisyui"),
    ],
};

कुंजी फीचर:

  • सामग्रीस्कैन्स: .cshtml क्लास नामों के लिए फ़ाइलें (मार्चर दृश्य तथा ई- मेल टैम्प्लेट को शामिल करें)
  • सुरक्षित सूची: इन क्लासों में हमेशा इन क्लासों को शामिल कीजिए, फिर चाहे वे स्कैन किए गए हों
  • गहरा- चैनल: "क्लास": क्लास आधारित गहरे मोड स्विच सक्षम करता है
  • प्रसंग.एक्सप्रयोगमनपसंद रंग व जगह मान जोड़ें
  • प्लगइन: क्लोजिंग प्लगइन तथा गुलदान्ड अवयव लाइब्रेरी शामिल करता है

tillio इन फ़ाइलों को निर्माण समय पर स्कैन करता है, केवल यूटिलिटी क्लास को निकालते हैं जो आप वास्तव में उपयोग करते हैं. यह क्यों अंतिम सीएसएस फ़ाइल पूर्णेज लाइब्रेरी से बहुत छोटा है.

जावास्क्रिप्ट प्रविष्टि बिन्दु

वह main.js फ़ाइल है जहां सब कुछ एक साथ आता है. यह फ़ाइल आयात करता है और सभी निर्भरता प्रारंभ करता है, और यह सामान्य रूप से बढ़ता जा रहा है जैसा कि मैंने ब्लॉग में अतिरिक्त विशेषताएँ जोड़ दी हैं:

// src/js/main.js
import hljsRazor from "highlightjs-cshtml-razor";
import mermaid from "mermaid";
import Alpine from 'alpinejs';
import htmx from "htmx.org";
import hljs from "highlight.js";
import EasyMDE from "easymde";
import 'easymde/dist/easymde.min.css';
import flatpickr from "flatpickr";
import 'flatpickr/dist/flatpickr.min.css';

// Expose libraries globally for Razor views
window.Alpine = Alpine;
window.hljs = hljs;
window.htmx = htmx;
window.mermaid = mermaid;
window.EasyMDE = EasyMDE;
window.flatpickr = flatpickr;

// Import custom modules
import { typeahead } from "./typeahead";
import { submitTranslation, viewTranslation } from "./translations";
import { codeeditor } from "./simplemde_editor";
import { globalSetup } from "./global";
import { comments } from "./comments";

// Attach to namespace
window.mostlylucid = window.mostlylucid || {};
window.mostlylucid.typeahead = typeahead;
window.mostlylucid.comments = comments();
window.mostlylucid.translations = {
    submitTranslation: submitTranslation,
    viewTranslation: viewTranslation
};

// Initialise Alpine
Alpine.start();

यह तरीका कई फायदे प्रस्तुत करता है:

  1. एकल आयात बिंदु: सभी निर्भरता को एक प्रविष्टि फ़ाइल के माध्यम से लोड किया गया
  2. सरल संस्करण: पैकेज्स लॉक्स विशिष्ट संस्करण
  3. तरू- बालालाइब्रेरी से उपयोग किए गए कोड हटाये
  4. वैश्विक एक्सपोजर: लाइब्रेरी के द्वारा राजेर दृश्य पर उपलब्ध window
  5. मनपसंद मॉड्यूलआयात योग्य मॉड्यूल में अनुप्रयोग विशेष कोड व्यवस्थित करें

खाका टैम्प्लेट एक्पर

में _Layout.cshtml, मैं अब केवल इकट्ठा संपत्ति का उल्लेख है:

<head>
    <link href="/css/dist/main.css" asp-append-version="true" rel="stylesheet" />
</head>
<body>
    <!-- Content -->
    <script src="~/js/dist/main.js" type="module" asp-append-version="true"></script>
</body>

नोट मैं निर्दिष्ट करें module ब्राउज़र को पता लगाने के लिए कि यह किस प्रकार के जेएस फ़ाइल है (S) asp-append-version एक साफ छोटा सा टैग सहायक जो कि क्वैरी वाक्यांश के लिए फ़ाइल सामग्री का भंडार जोड़ता है, प्रभावी कैशिंग जब फ़ाइल परिवर्तन होते हैं.

सिर्फ शेष सीडीएन निर्भरता हैं:

  • गूगल साइन इनअन्य कार्य के लिए बाहरी सीडीएन आवश्यक है
  • बक्सा चिह्न: प्रतीक फ़ॉन्ट (पराकर दिया जा सकता है, लेकिन कम से कम लाभ)
  • उममी विश्लेषण: तीसरी बार, मैं आपका दौरा Google नहीं देख रहा हूँ?

पाइपलाइन दृश्य बिल्ड करें

यहाँ कैसे पूरा निर्माण प्रक्रिया स्रोत फ़ाइलों से उत्पादन के लिए प्रवाहित करता है:

graph TD
    A[Source Files] --> B[npm run build]
    B --> C[Clean Task]
    C --> D[rimraf wwwroot/css/dist wwwroot/js/dist]

    B --> E[Copy Task]
    E --> F[cpx: Copy static CSS files]
    F --> G[wwwroot/css/dist/raleway.css]
    F --> H[wwwroot/css/dist/easymde-overrides.css]

    B --> I[Tailwind Task]
    I --> J[PostCSS Pipeline]
    J --> K[postcss-import]
    K --> L[Tailwind CSS]
    L --> M[Autoprefixer]
    M --> N[cssnano]
    N --> O[wwwroot/css/dist/main.css]

    B --> P[Webpack Task]
    P --> Q[Entry: src/js/main.js]
    Q --> R[Babel Transpilation]
    R --> S[Module Resolution]
    S --> T[Tree Shaking]
    T --> U[Code Splitting]
    U --> V[Terser Minification]
    V --> W[wwwroot/js/dist/main.js]
    V --> X[wwwroot/js/dist/runtime.js]
    V --> Y[wwwroot/js/dist/vendor chunks]

    O --> Z[ASP.NET Core Static Files]
    W --> Z
    X --> Z
    Y --> Z
    G --> Z
    H --> Z

    Z --> AA[Browser]

    style A stroke:#0ea5e9,stroke-width:3px
    style Z stroke:#f59e0b,stroke-width:3px
    style AA stroke:#10b981,stroke-width:3px

यह बहुत जटिल लग रहा है लेकिन वास्तव में है कि क्या वेबपीक करता है, यह खुद के अधिकांश संभालता है (एक जटिल तरीके से है कि Vite की तरह की जरूरत नहीं है लेकिन.)

परफ़ॉर्मेंस सुधार

फिर से, वास्तव में नहीं POrogher. लेकिन यह एक पूर्ण गोली की तरह अब लोड करता है. आप अभी भी बादलों के साथ विषय प्राप्त कर सकते हैं 'Rffffres' (जिसे आदमी कुछ लोड करता है) लेकिन यह कुछ हद तक होता है.

डेवलपर अनुभव लाभ

प्रदर्शन के अतिरिक्‍त, आधुनिक निर्माण कार्य में वृद्धि के प्रवाह को उल्लेखनीय रूप से बढ़ा देता है:

सुरक्षा और इंस्टिलिटेंस टाइप करें

वेब पासवर्ड के माध्यम से काटा जा रहा है सही जावास्क्रिप्ट मॉड्यूल प्रस्ताव सक्षम करता है, जिसका अर्थ है:

  • वीएस कोड में इंस्टेंसेंसेन्सआयात मॉड्यूल के लिए स्वचालित- पूर्णता
  • परिभाषा पर जाएँ: सीधे लाइब्रेरी स्रोत कोड पर नेविगेट करें
  • इनलाइन दस्तावेज़: अंजूटा ID में प्रकट होते हैं

जब दस मास की गाभिन ऊँटनियाँ आज़ाद छोड़ दी जाएँगी, npm run watch) मुझे अच्छी तरह से पता है, साथ ही (फफई के साथ) Cart इकाई जांच इसका मतलब है कि मजबूत प्रतिक्रियाओं का मतलब है.

गर्म मॉड्यूल बदलना

विकास के दौरान, npm run watch पास- आंतरिक फ़ीडबैक सक्षम करता है:

npm run watch

यह देखने के मोड में वेब बैग चलाता है, केवल परिवर्तित मॉड्यूलों को फिर से बनाने के लिए:

  • विशिष्ट फिर से प्रारंभ करने का समय: 200-400ms
  • ब्राउज़र स्वचालित ताज़ा करेंएक जैसे ब्राउज़र का उपयोग कर रहा है या एक जैसे औजार का उपयोग कर रहा है
  • अनुप्रयोग की स्थिति सुरक्षित है: HMR अद्यतन के दौरान अनुप्रयोग स्थिति बनाए रखता है (जहाँ समर्थित है)

डिपेंडेंसी प्रबंधन

मॉडम के लॉक फ़ाइल (y)package-lock.json) यह सुनिश्चित करता है कि वातावरण के पार नियमित रूप से बनाए रखें:

npm ci  # Clean install from lock file

यह विकास, सीआई/सीडी, तथा उत्पादन वातावरण में एक ही वितरणात्मक संस्करण की गारंटी देता है.

इन का उल्लेख इन लोगों के रूप में करने के लिए किया जाता है, जहां निर्भरता पत्थर में सेट कर रहे हैं. आप एक पैकेज लॉक के बिना कर सकते हैं लेकिन फिर आप पर निर्भर कर रहे हैं placacs के लेखकों पर; अक्सर अलग-अलगताओं के कुछ छोटी छूट नहीं.

स्क्रिप्ट बिल्ड करें

निर्देशित NPM स्क्रिप्ट आम कार्य आसान करता है:

npm run dev      # One-time development build
npm run watch    # Continuous development builds
npm run build    # Production build with optimisations
npm run clean    # Remove build artefacts

आम पैटर्न और समाधान

शैक्षिक लाइब्रेरी का विरोध करना विश्‍वव्यापी रूप से

कुछ पुस्तकालयों को राजिक दृश्य या इनलाइन स्क्रिप्ट में उपयोग के लिए वैश्विक एक्सपोजर की जरूरत होती है:

// Make library available globally
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();

तब में .cshtml फ़ाइलें:

<div x-data="{ open: false }">
    <!-- Alpine.js works because it's on window -->
</div>

जावास्क्रिप्ट मॉड्यूलों से सीएसएस उपयोग करें

कुछ लाइब्रेरी में सीएसएस जो आयात की आवश्यकता है:

import EasyMDE from "easymde";
import 'easymde/dist/easymde.min.css';  // Imported CSS is processed by Webpack

वेब बग़ैरल css-loader और style-loader इन आयातों को संभालता है:

  • निर्माण के दौरान सीएसएस बनाया जाता है
  • इसके द्वारा अभिलेखित किया गया <style> सीएसएस फ़ाइलों को टैग या अलग करना
  • स्वचालित उपसर्ग तथा न्यूनतम किया गया

zy भारी लाइब्रेरी लोड किया जा रहा है

पुस्तकालयों के लिए विशिष्ट पृष्ठों पर आवश्यक, गतिशील आयात प्रयोग करें:

// Only load Mermaid when needed
async function initMermaid() {
    const mermaid = await import('mermaid');
    mermaid.default.initialize({ startOnLoad: true });
}

// Call when needed
if (document.querySelector('.mermaid')) {
    initMermaid();
}

वेब बग़ैर सहेजे कोड कोड स्वचालित आयात करता है- गतिशील रूप से अलग कर दिया गया है, पर लोड हो रहा है.

आम तौर पर मेहमान - नवाज़ी से निपटना

कुछ पुरानी लाइब्रेरीों में ES6 मॉड्यूल के बजाए सामान्यJSUS इस्तेमाल किया जाता है:

// CommonJS require syntax
const hljs = require('highlight.js');

// Or use dynamic import
import('highlight.js').then(hljs => {
    // Use hljs
});

वेब बैग दोनों मॉड्यूल सिस्टमों को पारदर्शी रूप से संभालता है, सामान्यJS को ES में परिवर्तित करता है जहाँ ज़रूरत है.

सामान्य वाद - विवाद सहना

स्रोत नक्शे विकास में गुम है

सुनिश्चित करें devtool कॉन्फ़िगर्ड है webpack.config.js:

devtool: isProduction ? false : 'eval-source-map',

यह स्रोत नक्शे को आसान डिबगिंग के लिए विकास में बनाता है.

सीएसएस वर्ग पानी के साथ समस्या को साफ कर रहा है

यदि षिल स्कैन की क्लासों को हटा दें जो आप इस्तेमाल कर रहे हैं, जाँच करें content कॉन्फ़िगरेशनः

// tailwind.config.js
module.exports = {
    content: [
        './Views/**/*.cshtml',
        './Components/**/*.cshtml',
        // Add any other paths where classes are used
    ],
}

वैकल्पिक, उपयोग safelist गतिशील वर्गों के लिए:

safelist: [
    'bg-blue-500',
    'text-red-600',
    {
        pattern: /bg-(red|green|blue)-(400|500|600)/,
    }
]

मॉड्यूल नहीं मिला

वेब बग़ैर मॉड्यूल हल नहीं किया जा सकता है, जाँच करें:

  1. आयात पथ सही करें: सापेक्ष पथ इससे प्रारंभ होते हैं ./ या ../
  2. फ़ाइल विस्तार: जोड़ें .mjs को resolve.extensions जब आवश्यक हो
  3. अलाएसेस: इस्तेमाल resolve.alias जटिल पथों के लिए
resolve: {
    extensions: ['.js', '.mjs', '.json'],
    alias: {
        '@components': path.resolve(__dirname, 'src/js/components/'),
    }
}

परफ़ॉर्मेंस जारी रखें

यदि सक्षम किया जाता है तोः

  1. कैशिंग सक्षम करें: वेबहॉल का कैश काफी तेज़ हो जाता है
  2. बाबेल स्कोप कम करें: बाबुल प्रक्रिया से अधिक डिरेक्ट्रीज़ों को अलग करें
  3. उन्नयन उपकरण: वेब बैग और बाबुल के नए संस्करण तेज़ी से काम कर रहे हैं
  4. समानांतर निर्माण: इस्तेमाल thread-loader बहु- विशाल ट्रांसमिटे के लिए
// Enable Webpack caching
cache: {
    type: 'filesystem',
},

शिक्षा ने कठिन मार्ग सीखा

मैं इस यात्रा में किया गया कुछ ग़लतियों को साझा करने के लिए, तो आप उन्हें दूर कर सकते हैं:

गलत कदम # 1: एक बार में सब कुछ शैक्षिक करने की कोशिश

मेरी पहली कोशिश में शामिल सभी सीडीएन संदर्भों को एक करने के लिए और सब कुछ इकट्ठा करने की कोशिश करने के लिए वेब बैग के माध्यम से. निर्माण टूट गया. मैं पता चला कि बढ़ रहा तेरा दोस्त है - एक बार, जाँच अच्छी तरह से, फिर अगले करने के लिए कदम.

बुद्धि # 2: मोड्यूल प्रकार समझ नहीं पाया

मैं पता लगाने की कोशिश क्यों कुछ पुस्तकालय लोड नहीं होगा बाहर बारी, साझाJS (S)require()(S6 मॉड्यूल)import( क) बिना समझ के वेब गेट उन्हें कैसे काम करता है ध्वनिमय ग़लतियों की ओर ले जाता है. experiments: { outputModule: true } विन्यास मेरे आरंभिक सेटअप में नहीं था, और मैं बाहर काम नहीं कर सका मेरे मॉड्यूल लोड नहीं कर रहे थे.

रात के वक्‍त वुल्फ्ब स्टोर के बारे में जानकारी लेने का हल आ गया ।

गलत पकड़ #3: ओवर-ग्रेसन कोड विभाजित

एक बिंदु पर, मेरा कॉन्फ़िगरेशन सब कुछ के लिए फिर से बनाई जा रही थी. minSize: 10000 (१०केबी) जिसका मतलब था कि वेब बैग छोटे उपयोगिता कार्यों के लिए अलग फ़ाइलें बना रहा था. अधिक से अधिक सुधार किया गया और 2MB के लिए चला गया... पृष्ठ लोड 50+2-10-छोटे अनुरोधों का एक पानी हो गया या बड़ी मात्रा में डाउनलोड करने के लिए इंतजार कर रहा है. मैं जानता था कि कोड विभाजन अच्छा है, लेकिन आप सरल दहलीज़ की जरूरत है. यही कारण है कि मेरे मौजूदा विन्यास का उपयोग करता है. minSize: 20000 (२०केबी).

गलत पकड़ #4: के बारे में भूल जाने के लिए .mjs एक्सटेंशन

कुछ NMP पैकेज वितरित ईएस6 मॉड्यूल के साथ .mjs विस्तार. वेब बग़ैर इन्हें डिफ़ॉल्ट से हल नहीं किया जाएगा. मैं एक अवशोषित समय बिताया क्यों @mostlring I needed to add .jstoहल करो.

एक बार आप इसे जानते हैं, लेकिन पता है कि पता है?

MUR # 5: वेब संस्थापना बिल्ड नहीं कर रहा है

इससे पहले कि मैं वेब एजेंट सिस्टम कैश सक्षम नहीं कर सका. एक बार जब मैंने कलिंगिंग, 2-3 सेकंड के लिए डाल दिया. यह विकास फूल के लिए एक खेल परिवर्तन था लेकिन मुझे सप्ताह का पता लगाने के लिए ले लिया.

गलत पकड़ # 6: शुद्धीकरण वर्ग मैं वास्तव में इस्तेमाल किया

मेरे पसंदीदा डिबगिंग अनुभव: सीएसएस वर्ग जो विकास में अच्छी तरह काम किया गया वह अचानक गायब हो गया । safelist विन्यास, लेकिन केवल बाद में मैं पागल हो रहा था अगर मैं घंटों के बारे में सोच रहा था. मैं (उदाहरण के लिए उदाहरण) mostlylucid.pagingtaghelper परियोजना का उपयोग करें 'डिममुली ब्लॉक' जहाँ मैं अपने जाल कॉन्फ़िग परिवर्तनों को सरल कर देता हूँ सिर्फ गुप्त ब्लॉक रखने के द्वारा.


<!--
    Preserve Tailwind & DaisyUI classes used in embedded pager views.
    Without this, TailwindCSS tree-shaking removes classes from the embedded library views.
-->
<span class="hidden
    btn btn-sm btn-active btn-disabled join join-item badge badge-sm select select-bordered select-sm label label-text
    px-3 py-2 py-1 text-sm font-medium border rounded whitespace-nowrap cursor-not-allowed
    text-gray-700 text-gray-600 text-gray-400 text-white bg-white bg-gray-100 bg-blue-600 border-gray-300 border-blue-600
    hover:bg-gray-50 hover:bg-blue-700
    dark:bg-gray-800 dark:bg-gray-700 dark:bg-blue-500 dark:text-gray-300 dark:text-gray-500 dark:text-gray-200
    dark:border-gray-600 dark:border-blue-500 dark:hover:bg-gray-700 dark:hover:bg-blue-600">
</span>

जब Rilling यह वर्ग के लिए cllutml फ़ाइलों को स्कैन करता है, यदि यह उन्हें नहीं देखता. तो यह गुप्त ब्लॉक उन्हें हटा देता है. तो इसे सुनिश्चित करने के लिए मैं वर्ग की आवश्यकता है तब भी यदि वे केवल एम्बेडेड लाइब्रेरी दृश्य में उपयोग कर रहे हैं. कर्नेल विकासकर्ताओं को भी जरूरत होती है कि सीएसएस व्हीलेज के उपयोग की आवश्यकता होगी.


module.exports = {
content: ["./Views/**/*.cshtml", "./EmailSubscription/**/*.cshtml"],
-//^^^^ This is what Tailwing knows where to look for classes duritng the tree Shake. 
+//^^^^ This is what Tailwind knows where to look for classes during the tree-shake.
  
  ...

future: {...}

}

जैसा कि उल्लेख किया गया है, 'क्लासीय' दृष्टिकोण वर्ग को एक सुरक्षित सूची के लिए जोड़ने के लिए है... लेकिन मैं एक पागल आदमी हूँ, तो HTML जीता है.

मुझे सही - सही समझ में आया: लगन

एक बात जो मैंने करनी शुरू की थी. हर गलती का संदेश सीखने का मौका था. मुझे इन औज़ारों के बारे में कुछ नया सिखाया था. मैं एक स्पष्ट दर्शन था - मैं एक स्पष्ट दृष्टि था कि भारी भारी बोझ है, और जब तक मैं वहाँ मिल नहीं गया था.

कंटेनमेंट

सीडीएन- आधारित निर्भरता को इस ब्लॉग के लिए परिवर्तित कर दिया गया है, लेकिन यह आसान नहीं था. प्रदर्शन काफी अच्छा है, डेवलपर अनुभव काफी अच्छा है, और मेरे पास बहुत अधिक नियंत्रण है, लेकिन यह परीक्षण और त्रुटि के महीनों में यहाँ पाने के लिए.

कुंजी भागरः

  1. टाइलिंग आकार लोड किया जा रहा है: ट्री-शिंग तथा न्यूनतमीकरण उपयोग किए गए कोड को मिटा दें
  2. कोड विभाजन सुधार: ब्राउज़र केवल क्या जरूरत है लोड करता है
  3. आधुनिक जावास्क्रिप्ट सक्षम करें: बाबुल की ट्रांसमिटिंग नयी भाषा विशेषताओं को समर्थन देती है जबकि ब्राउज़र संगतता को बनाए रखने के दौरान
  4. पोस्ट नज़रअंदाज़ करें (m): Tilpo की हवा Jase और csasso छोटे से स्टाइलशीट
  5. .ENT के साथ जुड़ा हुआ समुद्रहीन है: एमएस बिल्ड को स्वचालित चालू करने के लिए
  6. लगन की वजह से सिद्ध इंसान सिद्ध हो जाता है: आप एक सामनेवाले विशेषज्ञ होने की जरूरत नहीं है - आप सिर्फ एक स्पष्ट दर्शन और यह करने की तत्परता की जरूरत है

एक अतिरिक्त के लिए. NEEN.N कोरसी विकासकर्ता जो साधारण सी सी. यह एक ही तरह से महसूस करते हैं. शुरू करो, एक ही तरह से छोटा है. विकास में चीजों को तोड़ने के लिए एक समय, और विकास में चीजों को तोड़ने के लिए नहीं डर है. आप डिबगिंग से पहले कभी दस्तावेज़ से ही सीख सकते हैं.

कॉन्फ़िगरेशन जो मैंने यहाँ साझा किया है इसका प्रतिनिधित्व करने के महीने. आपकी यात्रा अलग होगा, और यह ठीक है. यह एक शुरुआत बिंदु के रूप में इस्तेमाल करें, सुसमाचार नहीं. आपकी जरूरतों के लिए इसे अनुकूल रूप में, प्रयोग करें, प्रयोग, प्रयोग, और असफलता से नहीं किया जा रहा है, वे प्रक्रिया का हिस्सा हैं.

क्या यह ब्लॉग इंजनर पर है? मैं सीनेट का उपयोग कर सकता हूँ और अन्य चीजों पर मेरे समय खर्च किया जा सकता है. लेकिन मैं आधा अधिक के रूप में नहीं सीखा होता, और मैं यह लेख आप के साथ साझा करने के लिए नहीं होगा. कभी कभी गंतव्य के बारे में नहीं है, यह आप जिस तरह से सीख रहे हैं के बारे में है और दूसरों को उस अनुभव से सिखाने में सक्षम कर सकता है.

यदि आप अभी भी सीडी-नेट पर निर्भर कर रहे हैं अपने सामने की निर्भरता के लिए, मैं आपको एक कोशिश देने के लिए प्रोत्साहित करते हैं. एक पुस्तकालय के साथ शुरू करो. देखो यह कैसा महसूस करता है. यह कैसे महसूस करता है. serrocent. ss. sterds काफी उल्लेखनीय है, और जब तक सीखने के वक्र वास्तविक है, भुगतान यह इसके लायक है.

आगे पढ़ा जा रहा है

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.