مطالب
استفاده از RequireJs در پروژه های Asp.Net MVC
 در پست قبلی با کلیات RequireJs آشنا شدید. در این به بررسی  و پیاده سازی مثال قبل در قالب یک پروژه Asp.Net MVC می‌پردازم:
ابتدا یک پروژه Asp.Net MVC ایجاد کنید. در فولدر scripts تمام فایل‌های جاوااسکریپ پروژه قرار خواهند داشت. اگر قصد داشته باشیم که فایل‌های جاوااسکریپی سایر فریم ورک‌ها را استفاده نماییم (مثل backbone.js و ExtJs و...) برای طبقه بندی بهتر فایل ها، بهتر است که یک فولدر با نامی مشخص بسازیم و فایل‌های مورد نیاز را در آن قرار دهیم. البته اگر از nuget برای نصب این فریم ورک‌ها استفاده نمایید عموما این کار انجام خواهد شد.
حال با استفاده از Package Manager Console و اجرای دستور زیر، اقدام به نصب requireJs کنید
PM> Install-package requireJs
ساختار فولدر scripts به صورت زیر خواهد شد(دو فایل r.js و require.js به این فولدر اضافه می‌شود)  

 

یک فولدر به نام MyFiles در فولدر Scripts بسازید و فایل‌های purchase.js و product.js و credits.js در پروژه قبل را در آن کپی نمایید. کد فایل‌های پروژه قبل به صورت زیر بوده است:
purchase.js
define(["credits","products"], function(credits,products) {
  console.log("Function : purchaseProduct");
  return {
    purchaseProduct: function() {
      var credit = credits.getCredits();
      if(credit > 0){
        products.reserveProduct();
        alert('purchase done');'
        return true;
 } alert('purchase cancel');   return false; } } });
در کد بالا از یک alert برای نمایش موفقیت یا عدم موفقیت عملیات استفاده کردم.
products.js
define(function(products) {
  return {
    reserveProduct: function() {
      console.log("Function : reserveProduct");
      return true;
    }
  }
});
credits.js
define(function() {
  console.log("Function : getCredits");
  return {
    getCredits: function() {
      var credits = "100";
      return credits;
    }
  }
});
در نتیجه فایل‌های زیر به ساختار فولدر scripts اضافه شده است:


برای قدم بعدی، در متد RegisterBundles فایل bundleConfig پروژه دستور زیر را وارد نمایید:
  bundles.Add( new ScriptBundle( "~/bundles/require" ).Include(
                      "~/Scripts/require.js" ) );
کاملا واضح است که نیاز به تغییر در فایل Layout_  پروژه نیز داریم؛ در نتیجه تغییرات زیر را در فایل اعمال نمایید:



همان طور که مشاهده می‌کنید ابتدا با استفاده از دستور Scripts.Render فایل‌های include شده برای requireJs را در صفحه لود می‌کنید. سپس در تگ scripts که نوشته شده است با استفاده از دستور require.config مکان فایل‌های مورد نیاز را به فریم ورک Require معرفی میکنیم. این بدان معنی است که فریم ورک هر زمان که نیاز به لود یک وابستگی برای فایل‌های جاوااسکریپ داشته باشد، این مکان معرفی شده را جستجو خواهد کرد.
حال برای استفاده و لود ماژول purchase در انتهای فایل Index فولدر Home تغییرات زیر را اعمال نمایید:
@section scripts
{
    <script type="text/javascript">
    require(['purchase'], function (purchase)
    {        
        purchase.purchaseProduct();
    });
</script>
}
در دستورات بالا با کمک دستور require(همان طور که در پست قبلی توضیح داده شد) ماژول purchase را لود می‌کنیم و بعد با فراخوانی تابع purchaseProduct به خروجی مورد نظر خواهیم رسید. در این جا من از دستور alert برای نمایش خروجی استفاده کردم! در نتیجه خروجی به صورت زیر خواهد بود:

 
نظرات مطالب
یکپارچه سازی Angular CLI و ASP.NET Core در VS 2017
برای تکرار مجدد: ساختار مدیریت پروژه‌های قدیمی MVC 5 در VS مانند پروژه‌های VSCode یا ASP.NET Core (در همان VS با همان نگارش) نیستند. یعنی هرفایلی که در فایل csproj ارجاعی نداشته باشد، در IDE نمایش داده نمی‌شود (اما در پروژه‌های VSCode و یا پروژه‌های جدید ASP.NET Core، به محض اضافه شدن یک فایل جدید به پوشه‌ی پروژه، این فایل در IDE هم نمایان می‌شود). بنابراین روی دکمه‌ی show all files در solution explorer کلیک کنید و فایل‌های جدید را include کنید (مانند قبل و تمام پروژه‌های دیگری از این دست).


یک نکته: علت اینکه پروژه‌های ASP.NET Core به این صورت پویا عمل می‌کنند، وجود NET Core CLI. هست. این CLI هم شبیه به Angular-CLI یک ابزار خط فرمان است که کار ایجاد یک پروژه‌ی جدید تا ساخت و توزیع برنامه را مدیریت می‌کند و در حقیقت VS فقط این فرامین خط فرمان را در پشت صحنه اجرا می‌کند. بنابراین بهتر است از ساختار پروژه‌ای استفاده کنید که اساسا برای ابزارهای CLI طراحی شده‌است.

مطالب
معماری module based در TypeScript قسمت اول
در صورت استفاده از TypeScript، قطعا با module‌ها و هدف استفاده‌ی از آن‌ها آشنایی دارید. در این مقاله می‌خواهیم با متداول‌ترین روش‌های بسته بندی آن‌ها آشنا شده و به صورت عملیاتی آن را پیاده نماییم. اولین روش commonjs میباشد. از آنجایی که این روش بیشتر برای برنامه‌های خارج از مرورگر میباشد، به همین قدر معرفی آن بسنده میکنیم. اما دو روش مهم دیگری که در typeScript برای ماژول‌ها اهمیت فراوانی دارند:

1) AMD یا Asynchronous Module Definition
2) در این روش از امکانات توکار کامپایلر typescript برای combine کردن فایل‌ها استفاده میشود

ابتدا AMD را بررسی مینماییم
این روش بدین صورت عمل میکند که هر ماژول، در صورتیکه بطور صریح نیاز به ماژول دیگری داشته باشد، آن را import کرده و به صورت async آن ماژول درخواستی را دریافت مینماید. بهترین ابزار برای انجام اینکار requirejs میباشد و در وبسایت رسمی آن، خودش را اینگونه معرفی کرده است:
RequireJS is a JavaScript file and module loader ، ما عملیات load کردن فایل‌ها را به requirejs واگذار میکنیم.
حال میخواهیم به پیاده سازی AMD با استفاده از typescript و البته requirejs بپردازیم.
بنده برای اینکار از IDE محبوب خود visual studio استفاده خواهم کرد. قطعا شما از IDE/Text editor مورد نظر خود میتوانید استفاده نمایید (البته با کمی تغییرات جزیی در محتوای آموزشی این مقاله).
ابتدا یک پروژه‌ی asp.net از نوع empty را بدون هیچ وابستگی ایجاد کرده و index.html را بدان اضافه مینماییم:

نام پروژه‌ی من AMD و فایل index.html بدان اضافه شده است. فرض کنید یک پوشه‌ی جدید را به نام modules به آن اضافه میکنیم و در آن دو فایل typescript ی را به نام‌های module1.ts و module2.ts، اضافه میکنیم.

محتویات module1 را اینگونه مینویسیم:

export module module1 {
    export abstract class firstCls {
        static f1(str: string) {
            console.log(str);
        }
    }
}

و همچنین module2 به شکل زیر خواهد بود:

import * as Amd from 'module1';

module module2 {
    export class secondCls {
        f2(str: string) {
            Amd.module1.firstCls.f1(str);
        }
    }
}

new module2.secondCls().f2(`amd work's`);

(دقت کنید بعد از کامپایل شدن لفظ import تبدیل به define میشود)

از طریق add - new item فایل tsconfig.json را به مسیر اصلی پروژه اضافه کنید. در صورتی که آن را پیدا نکردید، به صورت دستی فایل آن را ساخته و محتویات زیر را در آن کپی نمایید:

{
  "compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": false,
    "target": "es6",
    "module": "amd"
  },
  "exclude": [
    "node_modules"
  ]
}
exclude مسیرهایی هستند که قرار نیست کامپایل شوند. target نوع کد تولید شده را مشخص مینماید (در صورتیکه مرورگر شما از es6 پشتیبانی نمیکند، میتوانید target را به es5 تغییر دهید) و module نیز از نوع amd تعریف میشود. کاری که قرار است انجام دهیم این است که به محض فراخوانی module2 به صورت async ، ماژول module1 را load کرده تا بتوان از آن بهره برد. متاسفانه در حال حاضر هیچ مرورگری به صورت توکار این ویژگی را پشتیبانی نمیکند! به همین دلیل فعلا مجبور به استفاده از ابزار‌های third party همچون requirejs هستیم.

در ادامه به root پروژه رفته و دستور npm init را ارسال کرده تا فایل package.json تولید شود. همچنین برای requirejs نیز دستور زیر را ارسال مینماییم:

npm install requirejs --save-dev

حال requirejs به پروژه‌ی شما اضافه شده است.


برای مدیریت کردن فراخوانی initial module در پوشه‌ی modules که قبلا ساخته بودیم فایل main.js راساخته و کد‌های زیر را بدان اضافه مینماییم.

(لازم به ذکر است این فایل را میتوانیم با استفاده از typescript نوشته و  requirejs definitely typed  را به پروژه اضافه کرده و از مزایای intellisense بودن بهره ببریم)

کد‌های زیر را درون main.js مینویسیم:

require(['modules/module2.js'], modules_module2());

function modules_module2() {
    //additionals config goes here
}

از آنجاییکه ممکن است تعداد وابستگی فایل‌ها زیاد باشد و ترتیب load شدن آن‌ها نیز اهمیت داشته باشد، در این قسمت میتوان configهای بیشتری را همچون sequence در load کردن فایل‌ها، تعریف کرد که میتوانید در وبسایت رسمی requirejs آن را مطالعه بفرمایید.


حال فایل index.html را باز کرده و config برای فراخوانی requirejs, main.js را مینویسیم؛ به صورت زیر:

<h1>Hello requirejs and amd modules</h1>

<!--src means require js address-->
<!--data-main means initial require config-->

<script src="node_modules/requirejs/require.js" data-main="modules/main.js"></script>

<script></script>

پر واضح است که src آدرس فایل require.js و همچنین data-main آدرس initial require config پروژه را مشخص می‌کند.

اکنون پروژه را run کرده و می‌بینید که فایل‌های مورد نیاز به صورت async برای ما load میشوند. اگر از مرورگر کروم استفاده می‌نمایید، بدین صورت میتوانید network و همچنین console را مشاهد نمایید:


مشاهد میکنید که فایل‌های مورد نیاز load شده‌اند و همچنین amd work's در console نمایش داده شده است.

requirejs بدین صورت عمل میکند: بعد از یافتن هر فایل، با استفاده از regex کل فایل را بررسی کرده و به دنبال وابستگی‌های آن فایل میگردد (منظور همان import‌ها میباشد و آن فایل به صورت async لود میشود) و در فایل‌های بعدی نیز همین روال ادامه خواهد یافت. هر چند راهکارهایی برای بهبود کارآیی در آن اندیشیده شده است؛ بدین صورت که اساس کارش با استفاده از singleton میباشد و بعد از require کردن فایلی، هر دفعه که فراخوانی میشود، نیاز به پردازش مجدد ندارد. با این وجود ممکن است در بعضی مواقع و مخصوصا با اشتباهات سهوی برنامه نویسان از کارآیی نرم افزار مطبوع شما بکاهد.


کد‌های این برنامه را میتوانید از اینجا دریافت نمایید (ضمن اینکه وابستگی‌های اضافه‌تری مانند پوشه‌ی node_modules حذف شده‌اند؛ بنابراین npm install فراموش نشود)

دانلود AMD.zip  


در قسمت بعد به امکانات توکار کامپایلر typescript برای معماری ماژول‌ها میپردازیم

مطالب
آشنایی با ساختار IIS قسمت هفتم

در این قسمت بیشتر یک سری از ماژول‌ها را به شما در قالب جداول گروه بندی شده معرفی خواهیم کرد :

   همانطور که در قسمت‌های قبلی گفتیم سرور IIS آماده خصوصی سازی و کار بر اساس علائق شماست؛ ولی توجه داشته باشید حذف تمامی ماژول‌ها ممکن است اثرات جانبی هم داشته باشد. در اینجا ما ماژول هایی را به شما معرفی می‌کنیم که بدانید کار هر ماژول چیست تا مثلا با حذف ماژولی، امنیت وب سایت خود را به خطر نیندازید :

ماژول‌های سودمند یا utility

نام ماژول:

UriCacheModule

توضیح:

این ماژول نوعی کش برای URLها به شمار می‌رود. موقعی که url درخواست می‌شود، اطلاعات در اولین درخواست خوانده شده و کش می‌شود و اگر دوباره همان url درخواست شود، بدون خواندن تنظیمات و بر اساس تنظیمات قبلی، کار url مربوطه را انجام میدهد تا اطلاعات پیکربندی تغییر کند و بر اساس اطلاعات جدید، خود را به روز کند.

تگ قابل پیکربندی:

لازم ندارد

وابستگی:

ندارد

اثرات حذف آن:

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

نام ماژول :

FileCacheModule

توضیح :

فایل هندلِ فایل‌هایی که قبلا در سرور باز شده‌اند را کش می‌کند تا در صورت نیاز در دفعات بعدی سریعتر عمل کند.

تگ قابل پیکربندی :

لازم ندارد .

وابستگی :

ندارد.

اثرات حذف آن :

کارایی سیستم کاهش می‌یابد. سیستم در هر اجرای دستور مربوط به فایل‌ها باید فایل هندل را به دست آورد.

نام ماژول :

TokenCacheModule

توضیح :

توکن‌های امنیتی ویندوز که پسوردهایی بر اساس authentication schemes هستند را کش می‌کند (anonymous authentication, basic authentication, IIS client certificate authentication )

تگ قابل پیکربندی :

لازم ندارد

وابستگی :

ندارد

اثرات حذف آن :

کارایی سیستم به شدت پایین می‌آید. کاربر باید با هر درخواستی لاگین کند. یکی از اصلی‌ترین ضربه‌ها با حذف این ماژول این است که اگر مثلا یک پسورد از یک فایل html محافظت می‌کند و این صفحه به 50 تصویر ارجاع دارد، 51 بار باید درخواست لاگین اجرا گردد یا شاید هم بدتر

MANAGED ENGINE: ASP.NET INTEGRATION

نام ماژول :

ManagedEngine

توضیح :

مدیریت ماژول‌های native و مدیریت شده

تگ قابل پیکربندی :


وابستگی :

ندارد

اثرات حذف آن :

مشخصا غیرفعال شدن asp.net integrated و غیر فعال شدن تمامی ماژول‌ها و هندلر‌های تگ وب کانفیگ یا داخل فایل کانفیگ IIS که در مقالات قبلی به تفصیل بیان کرده‌ایم.

IIS 7 NATIVE MODULES

نام ماژول :

HttpCacheModule

توضیح :

مدیریت کش خروجی در htttp.sys بر اساس پیکربندی مثل تعریف سایز کش و ...

تگ قابل پیکربندی :

System.webServer/caching

وابستگی :

ندارد.

اثرات حذف آن :

محتوا دیگر به صورت کرنل مد، کش نمی‌شود و کش پروفایل هم ندید گرفته می‌شود و احتمالا بر کارآیی و استفاده از منابع هم اثر می‌گذارد.

نام ماژول :

DynamicCompressionModule

توضیح :

پیاده سازی in-memory compression در محتوای پویا

تگ قابل پیکربندی :

system.webServer/httpCompression and system.webServer/urlCompression.

وابستگی :

وابستگی ندارد چرا که به طور پیش فرض غیرفعال است.

نام ماژول :

StaticCompressionModule

توضیح :

پیادسازی فشرده سازی در محتوای ایستا و برای فایل‌های سیستمی از نوع in memory

تگ قابل پیکربندی :

system.webServer/httpCompression and system.webServer/urlCompression

وابستگی :

ندارد.

اثرات حذف آن :

در صورت عدم فشرده سازی بر مصرف ترافیک تاثیر گذار است.

نام ماژول :

DefaultDocumentModule

توضیح :

پیاده سازی یک لیست سند پیش فرض. درخواست‌ها مدام پشت سر هم می‌آیند و این درخواست‌های پشت سرهم، به سند پیش فرض هدایت می‌شوند. همان پنجره ای که شما به ترتیب فایل‌های index.htm,index.asp,default.aspx و... را تعیین می‌کنید.

تگ قابل پیکربندی :

system.webServer/defaultDocument

وابستگی :

ندارد.

اثرات حذف آن :

درخواست را به ریشه هدایت می‌کند. مثلا برای localhost صفحه 404 باز میگرداند و اگر directoryBrowsing فعال باشد لیستی از دایرکتوری ریشه را باز میگرداند.

نام ماژول :

DirectoryListingModule

توضیح :

پیادی سازی لیستی از محتویات یک دایرکتوری

تگ قابل پیکربندی :

system.webServer/directoryBrowse

وابستگی :

ندارد.

اثرات حذف آن :

اگر این ماژول و ماژول قبلی غیرفعال باشند response نهایی خالی است.

نام ماژول :

ProtocolSupportModule

توضیح :

پیاده سازی اختصاصی از response header

پیاده سازی تنظیمات trace و HTTP verbs.

پیاده سازی تنظیمات مربوطه به keep-alive بر اساس پیکربندی

تگ قابل پیکربندی :

system.webServer/httpProtocol

وابستگی :

ندارد.

اثرات حذف آن :

بازگرداندن پیام خطای "405 Method not allowed".

نام ماژول :

HttpRedirectionModule

توضیح :

پیاده سازی عملیات انتقال یا redirect

تگ قابل پیکربندی :

system.webServer/httpRedirect

وابستگی :

ندارد.

اثرات حذف آن :

خطر امنیتی: اگر منابعی با redirect کردن محافظت می‌شوند، از این پس در دسترسند.

نام ماژول :

ServerSideIncludeModule

توضیح :

حمایت از فایل shtm یا shtml و ...

تگ قابل پیکربندی :

system.webServer/serverSideInclude

وابستگی :

ندارد.

اثرات حذف آن :

این فایل‌ها به صورت متنی نمایش داده می‌شوند

نام ماژول :

StaticFileModule

توضیح :

فایل‌های ایستا را به همراه پسوند ارسال می‌کند. مثل jpg,html و نوع محتوا را بر اساس staticContent/mimeMap پیکربندی می‌کند.

تگ قابل پیکربندی :

system.webServer/staticContent

وابستگی :

ندارد.

اثرات حذف آن :

فایل‌های ایستا دیگر ارائه نشده و به جای آن خطای 404 بازگشت داده می‌شود.

نام ماژول :

AnonymousAuthenticationModule

توضیح :

پیاده سازی سیستم شناسایی افراد ناشناس. همانطور که میدانید در یک وب سایت حداقل محتوایی برای افرادی بدون داشتن اکانت هم وجود دارد. برای اینکار یک شیء httpuser ایجاد می‌کند.

تگ قابل پیکربندی :

system.webServer/security/authentication/anonymousAuthentication

وابستگی :

ندارد.

اثرات حذف آن :

حداقل باید یک سیستم امنیتی برای شناسایی یا authenticate وجود داشته باشد. httpuser یک ساختار داده ای در IIS می‌باشد و در صورت نبودن هیچ سیستم شناسایی وجود نداشته و در نبود شیء httpuser سیستم خطای 401.2 را تولید می‌کند.

نام ماژول :

CertificateMappingAuthenticationModule

توضیح :

مجوز SSL را به Active Directory نگاشت می‌کند.

تگ قابل پیکربندی :

system.webServer/security/authentication/clientCertificateMappingAuthentication

وابستگی :

برای اینکه این ماژول وظیفه خود را انجام دهد باید تنظیمات SSL انجام شود و همچنین سیستم IIS جزئی از دامنه Active directory باشد

اثرات حذف آن :

درخواست‌ها، نرمال رسیدگی میشوند انگار SSL وجود ندارد.

نام ماژول :

BasicAuthenticationModule

توضیح :

پیاده سازی پایه‌ای و روتین شناسایی کاربران بر اساس آن چیزی که در استانداد زیر آمده است

RFC 2617.

تگ قابل پیکربندی :

system.webServer/security/authentication/basicAuthentication

وابستگی :

None.

اثرات حذف آن :

حداقل باید یک سیستم امنیتی برای شناساسایی یا authenticate وجود داشته باشد. httpuser یک ساختار داده‌ای در IIS می‌باشد و در صورت نبود، هیچ سیستم شناسایی یافت نشده و نبود شیء  httpuser در سیستم، خطای 401.2 را تولید می‌کند.

نام ماژول :

WindowsAuthenticationModule

توضیح :

((windows Authentication (NTLM or Negotiate (Kerberos

تگ قابل پیکربندی :

system.webServer/security/authentication/windowsAuthentication

وابستگی :

ندارد.

اثرات حذف آن :

حداقل باید یک سیستم امنیتی برای شناسایی یا authenticate وجود داشته باشد. httpuser یک ساختار داده ای در IIS می‌باشد و در صورت نبود، هیچ سیستم شناسایی یافت نشده و نبود شیء httpuser در سیستم، خطای 401.2 را تولید می‌کند.

نام ماژول :

DigestAuthenticationModule

توضیح :

پیاده سازی سیستم شناسایی دیاجست بر اساس

RFC 2617 .

تگ قابل پیکربندی :

system.webServer/security/authentication/digestAuthentication

وابستگی :

IIS باید بخشی از دامنه Active Directory باشد.

اثرات حذف آن :

حداقل باید یک سیستم امنیتی برای شناسایی یا authenticate وجود داشته باشد. httpuser یک ساختار داده ای در IIS می‌باشد و در صورت نبود، هیچ سیستم شناسایی یافت نشده و نبود شیء httpuser در سیستم، خطای 401.2 را تولید می‌کند.

نام ماژول :

IISCertificateMappingAuthenticationModule

توضیح :

پیاده سازی نگاشت مجوزهای IIS، نگهداری و ذخیره اطلاعات همه نگاشت‌ها و مجوزهای کاربری چون SSL client certificates  

تگ قابل پیکربندی :

system.webServer/iisClientCertificateMappingAuthentication

وابستگی :

اطلاعات SSL به همراه دریافت client certificates جهت پیکربندی این ماژول

اثرات حذف آن :

حداقل باید یک سیستم امنیتی برای شناسایی یا authenticate وجود داشته باشد. httpuser یک ساختار داده ای در IIS می‌باشد و در صورت نبود، هیچ سیستم شناسایی یافت نشده و نبود شیء httpuser در سیستم، خطای 401.2 را تولید می‌کند.

نام ماژول :

UrlAuthorizationModule

توضیح :

پیاده سازی authorization بر اساس قوانین پیکربندی شده

تگ قابل پیکربندی :

system.webServer/security/authorization

وابستگی :

ندارد.

اثرات حذف آن :

محتواهای محافظت شده توسط authorization دیگر محافظت نمی‌شوند.

نام ماژول :

IsapiModule

توضیح :

پیاده سازی ISAPI Extension 

تگ قابل پیکربندی :

system.webServer/isapiCgiRestriction

وابستگی :

ندارد.

اثرات حذف آن :

هندلر‌های معرفی شده در بخش IsapiModule و تگ handlers دیگر اجرا نمی‌شوند

نام ماژول :

IsapiFilterModule

توضیح :

پیاده سازی ISAPI filter 

تگ قابل پیکربندی :

system.webServer/isapiFilters

وابستگی :

ندارد.

اثرات حذف آن :

اگر برنامه ای از ISAPI filter استفاده می‌کند، در اجرا دچار مشکل خواهد شد.

نام ماژول :

IpRestrictionModule

توضیح :

یک سیستم تشخیص دسترسی  بر اساس آی پی‌های ورژن4

تگ قابل پیکربندی :

system.webServer/security/ipSecurity

وابستگی :

IPv4 stack باید نصب شود.

اثرات حذف آن :

کلاینت هایی که IP هایشان در IPsecurity لیست شده‌اند ندید گرفته میشوند

نام ماژول :

RequestFilteringModule

توضیح :

پیاده سازی یک مجموعه قدرتمند از قوانین امنیتی که درخواست‌های مشکوک را پس می‌زند.

تگ قابل پیکربندی :

system.webServer/security/requestFiltering

وابستگی :

ندارد.

اثرات حذف آن :

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

نام ماژول :

CustomLoggingModule

توضیح :

پیاده سازی اینترفیس ILogPlugin در سمت IIS، به مشتریان اجازه میدهد تا لاگ‌های خود را توسعه دهند. هر چند این روش توصیه نمی‌شود و توصیه کارشناس مایکروسافت استفاده از یک ماژول دست نویس از نوع RQ_LOG_REQUEST می باشد.

Implements the ILogPlugin interface on top of IIS. ILogPlugin is a previous COM implementation that allowed customers to extend IIS logging. We do not not recommend extending IIS using this interface. Instead, customers should write a module and subscribe to the RQ_LOG_REQUEST notification.

تگ قابل پیکربندی :

system.webServer/httpLogging and system.applicationhost/sites/site/logFile/customLogPluginClsid

وابستگی :

ندارد.

اثرات حذف آن :

مسلما پلاگین‌های‌های این اینترفیس از کار می‌‌افتند که سیستم ODBC Logging هم جز آن است.

نام ماژول :

CustomErrorModule

توضیح :

پیاده سازی مدیریت خطاهای ویژه

تگ قابل پیکبرندی :

system.webServer/httpErrors

وابستگی :

None.

اثرات حذف آن :

در صورتی که خطایی از هسته باشد، نتیجه یک صفحه، با توضیح مختصری از خطا خواهد بود. در غیر این صورت اگر خطا از برنامه یا کامپوننتی باشد جزئیات خطا فاش خواهد شد

نام ماژول :

HttpLoggingModule

توضیح :

پیاده سازی سیستم logging استاندارد http.sys

تگ قابل پیکربندی :

system.applicationHost/log and system.webServer/httpLogging

وابستگی :

ندارد.

اثرات حذف آن :

از کار افتادن سیستم لاگ

نام ماژول :

FailedRequestsTracingModule

توضیح :

پیاده سازی سیستم ردیابی درخواست‌های ناموفق و اجرای قوانین، طبق پیکربندی

تگ قابل پیکربندی :

system.webServer/tracing and system.webServer/httpTracing

وابستگی :

ندارد.

اثرات حذف آن :

Tracing http requests will no longer work.

نام ماژول :

RequestMonitorModule

توضیح :

پیاده سازی IIS Run-time State and Control Interface یا به اختصار RSCA . به کاربران اجازه می‌دهد از اطلاعات، حین اجرا، کوئری بگیرند. مثل درخواست درحال اجرای جاری، آغاز به کار یا توقف وب سایت و دامنه‌های اپلیکیشن در حال اجرای جاری

تگ قابل پیکربندی :

ندارد.

وابستگی :

ندارد.

اثرات حذف آن :

ابزارهای مرتبط با این موضوع از کار می‌افتند

نام ماژول :

CgiModule

توضیح :

پیاده سازی CGI در سمت IIS

تگ قابل پیکبرندی :

system.webServer/cgi and system.webServer/isapiCgiRestriction

وابستگی :

ندارد.

اثرات حذف آن :

برنامه‌های CGI متوقف می‌شوند

نام ماژول :

TracingModule

توضیح :

پیاده سازی سیستم ردیابی ETW

تگ قابل پیکربندی :

system.webServer/httpTracing

وابستگی :

ندارد.

اثرات حذف آن :

باعث از کار افتادن سیستم مربوطه می‌شود

نام ماژول :

ConfigurationValidationModule

توضیح :

اعتبارسنجی تنظیمات برنامه ASP.Net که به حالت integrate انتقال یافته است

تگ قابل پیکربندی :

system.webServer/Validation

وابستگی :

ندارد.

اثرات حذف آن :

عدم اعتبارسنجی و در نتیجه عدم نمایش خطاها

MANAGED MODULES:

نام ماژول :

OutputCache

توضیح :

پیاده سازی output caching

تگ قابل پیکربندی :

system.web/caching/outputCache

وابستگی :

نیاز به ManagedEngine .

اثرات حذف آن :

عدم اجرای output cache

نام ماژول :

Session

توضیح :

مدیریت سشن ها

تگ قابل پیکربندی :

system.web/sessionState

وابستگی :

نیاز به ManagedEngine . 

اثرات حذف آن :

سشن‌ها از دسترس خارج می‌شوند.

نام ماژول :

WindowsAuthentication

توضیح :

اینجا 

تگ قابل پیکربندی :

system.web/authentication

وابستگی :

نیاز به ManagedEngine .

اثرات حذف آن :

این حالت قابل اجرا نخواهد بود

نام ماژول :

FormsAuthentication

توضیح :

اینجا 

تگ قابل پیکربندی :

system.web/authentication

وابستگی :

نیاز به ManagedEngine .

اثرات حذف آن :

این حالت قابل اجرا نیست و کاربران مجوز دار هم نمی‌توانند به منابع محافظت شده دسترسی داشته باشند.

نام ماژول :

DefaultAuthentication

توضیح :

اطمینان از وجود شی Authentication در context مربوطه 

تگ قابل پیکربندی :

system.web/authentication

وابستگی :

نیاز به ManagedEngine .  

اثرات حذف آن :

اگر مد Forms authentication انتخاب شده باشد بر روی بعضی از کاربران ناشناس کار نخواهد کرد و رویداد DefaultAuthentication.OnAuthenticate اجرا نخواهد شد.

نام ماژول :

RoleManager

توضیح :

اینجا 

تگ قابل پیکربندی :


وابستگی :

نیاز به ManagedEngine .

اثرات حذف آن :

این قابلیت در دسترس نمی‌باشد

نام ماژول :

UrlAuthorization

توضیح :

اینجا 

تگ قابل پیکربندی :

system.web/authorization.

وابستگی :

نیاز به ManagedEngine .  

اثرات حذف آن :

باعث از کار افتادن asp.net authorization و فاش شدن بعضی اطلاعات و همچنین دیگر تهدیدات امنیتی

نام ماژول :

AnonymousIdentification

توضیح :

اینجا 

تگ قابل پیکربندی :


وابستگی :

نیاز به ManagedEngine . 

اثرات حذف آن :

The anonymous identification feature used by the ASP.NET Profile will not work.

نام ماژول :

Profile

توضیح :

اینجا 

تگ قابل پیکربندی :


وابستگی :

ManagedEngine module must be installed.

اثرات حذف آن :

ASP.Net Profile از کار خواهد افتاد

نام ماژول :

UrlMappingsModule

توضیح :

 تبدیل یک Url واقعی به یک Url کاربرپسند 

تگ قابل پیکبرندی :


وابستگی :

نیاز به ManagedEngine .

اثرات حذف آن :

نگاشت Url‌ها صورت نمی‌گیرد

نظرات مطالب
VS Code برای توسعه دهندگان ASP.NET Core - قسمت اول - نصب و راه اندازی
- بله. باید با پشت صحنه‌ی CLR و نوشتن Task برای آن آشنا باشید. کامپایلر csc.exe را باید به همراه تعاریف فایل csproj و وابستگی‌های آن فراخوانی و اجرا کنید. البته امکان دیباگ را هم نخواهید داشت.
- در کل چون پروژه‌های Full .NET Framework از ساختار پروژه‌ی csproj قدیمی استفاده می‌کنند که تمام تعاریف فایل‌ها باید در آن‌ها ثبت شوند، آنچنان مناسب کار با VSCode نیستند. پروژه‌های NET Core. ساختار جدیدی از فایل csproj را ارائه می‌کنند و دیگر در آن‌ها فایل‌ها نیازی به ثبت در فایل csproj را ندارند. به همین جهت به خوبی با مدل کاری VSCode که مبتنی بر پوشه‌ها است، سازگار می‌شوند. همچنین برای NET Core. یک CLI طراحی شده که اساس آن‌را تشکیل می‌دهد. این CLI هست که از ایجاد پروژه تا افزودن ارجاعات، ساخت و اجرا را به سادگی مدیریت می‌کند و همچنین چندسکویی است. یک چنین CLI ایی برای Full .NET Framework وجود ندارد و در حد batch نویسی برای csc.exe است؛ چون ویژوال استودیو تا به امروز تمام پیچیدگی‌های آن‌را مدیریت کرده و نیازی به این CLI نبوده. اما در سایر سکوهای کاری این CLI هست که مدیریت تمام امور را انجام می‌دهد.
مطالب
شروع کار با webpack - قسمت سوم
در مطلب قبلی با فایل‌های پیکربندی وبپک، وب سرور وبپک، لودر‌ها و ... آشنا شدیم .


استفاده از preLoader‌ها در وبپک 
پیش‌تر با Loader‌ها آشنا شدیم و دلیل استفاده‌ی از آنها نیز ذکر و Loader تایپ اسکریپت را نیز نصب کرده و با استفاده از آن فایل‌های پروژه را ترنسپایل کردیم. اما ممکن است که همه‌ی کارها در استفاده از یک Loader خلاصه نشوند. ممکن است بخواهید از یک ابزار Linting مانند jsHint  قبل از اجرای Loader ها بهره ببرید و این دقیقا کاری است که به preLoader‌ها سپرده می‌شود. به عنوان مثال پیش لودر jsHint را نصب خواهیم کرد. اضافه کردن preLoader‌ها در فایل پیکربندی وبپک تفاوتی با Loader‌ها نخواهد داشت و دارای همان قسمت‌هایی است که برای Loader‌ها تعریف کردیم.
پیش از هر کاری ابتدا jsHint را نصب کرده و سپس loader آن را نیز نصب می‌کنیم. دستورات مورد نیاز، در ادامه آورده شده اند:
npm install -D jsHint jsHint-loader
سپس در ادامه به فایل پیکربندی وبپک مراجعه کرده و قسمت preLoader را به آن اضافه می‌کنیم:
module.exports = {
    entry:['./shared.js','./main.ts']
    ,output:{
        filename:'bundle.js'
    }
    ,watch :true
    ,module:{
        preLoaders:[
            {
                test:/\.js$/
                ,exclude:/node_modules/
                ,loader:'jshint-loader'
            }
        ],
        loaders:[
            {
                test:/\.ts$/
                ,exclude:/node_modules/
                ,loader:'ts-loader'
            }
        ]
    }
    
}

حال وب سرور وبپک را اجرا می‌کنیم. در خط فرمان نتیجه‌ی اجرا شدن jsHint در تصویر قابل مشاهده است که از دو فایل پروژه ایراد گرفته است:


همچنین برای تکمیل قابل ذکر است که وبپک دارای postLoaders نیز می‌باشد که پس از Loader‌های اصلی اجرا می‌شوند.
لیست کاملی از Loader‌ها را می‌توانید در اینجا مشاهده کنید .تمامی لودرهای وبپک

Minify کردن باندل‌ها با استفاده از وبپک

در صورتی که باندل ساخته شده تا به اینجای کار را باز کرده باشید، مشاهده کرده‌اید که باندل ساخته شده Minify شده نیست. ساده‌ترین روش جهت Minify کردن باندل ساخته شده در هنگام فراخوانی وبپک با استفاده از یک پرچم در خط فرمان می‌باشد. دستور مورد نیاز در ادامه آورده شده است.
// در حالتی که به صورت محلی وبپک نصب شده است
npm run webpack -- -p
// درحالتی که وبپک به صورت سراسری اجرا می‌شود
webpack -p
حال در صورتی که به باندل ساخته شده مراجعه کنید، باندل در حالت Minify شده قرار دارد.

اضافه کردن فایل پیکربندی مخصوص بیلد‌های اصلی پروژه

قطعا شما نیز در حین توسعه‌ی پروژه از دستورات لاگ یا اندازه گیری زمان اجرای یک قطعه کد و ... استفاده می‌کنید و حضور این کد‌ها در باندل نهایی دلیلی ندارد. یک راهکار این است که کدهایی را که فقط جهت توسعه‌ی پروژه و دیباگ بودند و سودی در نتیجه‌ی نهایی ندارند، به صورت دستی پاک کنیم و در صورتی که حجم این طور دستورات بالا باشند، قطعا کار جالبی نخواهد بود و همچنین حذف کلی این دستورات نیز در ادامه برای برگشت به پروژه ممکن است مشکل زا باشد.
راهکاری که با وبپک می‌توان پیش گرفت این است که از یک Loader جهت بیلد‌های اصلی استفاده کرده و مثلن تمامی کامنت‌ها و دستورات لاگ کننده و ... را از بیلد نهایی حذف کنیم. جهت اینکار یک فایل پیکربندی مخصوص را به بیلدهای اصلی به پروژه اضافه می‌کنیم و اسم فایل را webpack.prod.config.js می‌گذاریم.
قدم بعدی نصب یک loader می‌باشد که وظیفه‌ی حذف مواردی را دارد که برای آن مشخص خواهیم کرد. این لودر strip-loader نام دارد و با دستور زیر آن را در پروژه اضافه می‌کنیم.
npm install -D strip-loader
سپس وارد فایل پیکربندی که فقط جهت تولید باندل‌های اصلی پروژه ایجاد کرده‌ایم (webpack.prod.config.js) می‌شویم و کد‌های زیر را وارد می‌کنیم.
// webpack.prod.config.js
 //تنظیمات قبلی را می‌خوانیم
var devConfig = require("./webpack.config.js");
// لودری که وظیفه‌ی حذف کردن دارد را وارد می‌کنیم
var stripLoader = require("strip-loader");

// مانند قبل یک آبجکت با موارد مورد نظر برای لودر می‌سازیم
var stripLoaderConfig = {
    test:[/\.js$/,/\.ts$/],
    exclude :/node_modules/
    ,loader:stripLoader.loader("console.log")
}

// اضافه کردن به لیست لودرهای قبلی
devConfig.module.loaders.push(stripLoaderConfig);

// و در آخر اکسپورت کردن تنظیمات جدید وقبلی
module.exports = devConfig;
در توضیح کد‌های بالا در خط اول ابتدا فایل پیکربندی را که در توسعه‌ی عادی پروژه استفاده می‌شد، می‌خوانیم و در آبجکتی با نام devConfig ذخیره می‌کنیم. مزیت اینکار این می‌باشد که از تعریف تنظیمات تکراری و مورد نیاز جلوگیری می‌کند (نکته : اگر بخاطر داشته باشید در مطلب قبلی ذکر شد که فایل‌های پیکربندی در فرمت commonjs می‌باشند و در نتیجه امکان وارد کردن آنها با استفاده از تابع require امکان پذیر است).
خط بعدی نیز loader ی که وظیفه‌ی حذف موارد مورد نظر ما را دارد وارد می‌کنیم و در ادامه یک آبجکت را با تعاریفی که قبلن از لودر‌ها داشتیم می‌سازیم. تنها نکته در قسمت تعریف اسم لودر می‌باشد.
loader:stripLoader.loader("console.log")
در کد بالا مواردی را که مورد نیاز است از سورس اصلی در سورس نهایی حذف شود، به لودر معرفی می‌کنیم. در اینجا تمامی دستوراتی که شامل console.log می‌شوند از بیلد نهایی باندل حذف خواهند شد.
تنها مرحله‌ی باقی مانده، فراخوانی وبپک با استفاده از فایل پیکربندی جدید می‌باشد. برای اینکار با استفاده از پرچم config محل فایل جدید پیکربندی را به وبپک معرفی می‌کنیم تا از فایل پیکربندی پیش فرض قبلی استفاده نکند.
// در حالتی که وبپک به صورت محلی نصب شده است
npm run webpack -- --config webpack.prod.config.js -p
// در حالتی که وبپک به صورت سراسری نصب شده باشد
webpack --config webpack.prod.config.js -p
پس از اجرای این دستور و باز کردن صفحه‌ی index.html خواهید دید که پیغامی در کنسول مرورگر ظاهر نخواهد شد و دستورات console.log همگی حذف شده‌اند.
توجه داشته باشید که اگر برای ساخت باندل از وبپک استفاده کرده‌اید، برای میزبانی فایل‌های پروژه از وب سرور وبپک استفاده نکنید و از وب سروری دیگر (مانند http-server یا IIS و ...) استفاده کنید؛ چرا که باندل توسط وب سرور وبپک دوباره ساخته می‌شود و تغییرات از بین می‌روند. در صورتی که می‌خواهید از وب سرور وبپک برای میزبانی بیلد نهایی پروژه نیز استفاده کنید، فایل پیکربندی بیلد نهایی را نیز به وب سرور وبپک با استفاده از دستور زیر معرفی کنید:
// زمانی که وبپک به صورت محلی در پروژه نصب شده است
npm run webpackserver -- --config webpack.prod.config.js  -p
//در حالتی که وبپک به صورت گلوبال ( سراسری ) نصب می‌باشد
webpack-dev-server --config webpack.prod.config.js  -p

مدیریت فایل و فولدرها با استفاده وبپک
تا به اینجای کار اگر به ساختار چینش فایل‌ها در پروژه دقت کنید خواهید دید که همگی فایل‌ها در مسیر اصلی پروژه قرار دارند و این روش مناسبی برای مدیریت فایل‌ها و فولدرها در پروژه‌های واقعی و بزرگ نیست. در ادامه قصد داریم این مسئله را حل کرده و ساختار مشخصی را برای محل قرارگیری فایل‌های پروژه با کمک وبپک ایجاد کنیم.
در اولین قدم فولدری را برای اسکریپت‌ها با نام js ایجاد کرده و اسکریپت‌ها را به این فولدر انتقال می‌دهیم.
در قدم دوم برای فایل‌های استاتیک پروژه مانند صفحات html و ... فولدر دیگری را با نام assets ایجاد می‌کنیم و این گونه فایل‌ها را در آن قرار خواهیم داد.
تا اینجای کار در صورتی که وبپک را اجرا کنید، مسیرهای جدید را پیدا نخواهد کرد و دچار خطا خواهد شد. پس به فایل پیکربندی ( webpack.config.js ) مراجعه کرده و وبپک را از ساختار جدید پروژه خبردار می‌کنیم.
// new webpack.config.js file
//ماژول توکار نود جی اس
var path = require("path");

module.exports = {
    // مشخص کردن زمینه برای فایل‌های ورودی
    context:path.resolve("js"),
    entry:['./shared.js','./main.ts']
    ,output:{
       // مشخص کردن محل قرارگیری باندل ساخته شده
        path:path.resolve("build/js"),
      // درخواست از سمت چه مسیری برای باندل خواهد آمد ؟
        publicPath:"assets/js",
        filename:'bundle.js'
    }
    ,
    devServer:{
        //راهنمایی برای وب سرور جهت اینکه فایل‌ها را از چه محلی سرو کند
        contentBase:"assets"
    }

    ,watch :true
    ,module:{
        
        loaders:[
            {
                test:/\.ts$/
                ,exclude:/node_modules/
                ,loader:'ts-loader'
            }
        ]
    }
    
}
در خط اول فایل پیکربندی جدید، ماژول توکار path از نود جی اس را وارد می‌کنیم و سپس کلید جدیدی را به تنظیمات وبپک با نام context اضافه می‌کنیم که زمینه‌ی فایل‌های ورودی را مشخص خواهد کرد. قبلا ذکر شد که فولدری با نام js را ساخته و اسکریپت‌ها را در آن قرار می‌دهیم. پس با کمک ماژول path این مسیر را به وبپک معرفی می‌کنیم.
context:path.resolve("js")
تغییر بعدی را در تنظیمات برای ساخت باندل داریم که مشخص کردن مسیر قرارگیری جدید باندل می‌باشد که با کلید جدیدی با نام path، مسیر قرارگیری باندل پس از ساخته شدن را به وبپک اطلاع می‌دهیم و در ادامه کلید دیگری با نام publicPath اضافه شده که راهنمایی برای وب سرور وبپک می‌باشد تا با استفاده از آن درخواست‌هایی که به مسیر مشخص شده می‌آیند، از مسیری که در کلید path نامیده شده سرو شوند.
// تغییرات در شی output
// این کلید جدید مسیر قرار گیری جدید باندل را به وبپک اطلاع می‌دهد
path:path.resolve("build/js"),
//  راهنما برای وب سرور وبپک جهت میزبانی مسیر زیر از کلید بالا
publicPath:"assets/js",
آخرین تغییر در فایل پیکربندی، مربوط به اضافه شدن آبجکت جدید devServer می‌باشد که در آن کلیدی اضافه شده که مسیر اصلی فایل‌های میزبانی شده را اعلام می‌کند. به طور مثال فایل html اصلی پروژه را بالاتر اشاره کردیم که در این مسیر قرار می‌دهیم.
در نهایت وارد فایل index.html می‌شویم و مسیر جدید باندل را به آن معرفی میکنیم.
//index.html

<html>
    <head>
        first part of webpack tut!
    </head>
    <body>
        <h1>webpack is awesome !</h1>
        <script src="assets/js/bundle.js"></script>
    </body>
</html>
قابل مشاهده است که مسیر باندل ذکر شده در اینجا وجود خارجی ندارد و وبپک آن را با کمک تنظیماتش، به صورت پویا پیدا خواهد کرد. در تصویر زیر سعی بر روشن‌تر شدن این مسئله شده است.


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


ساخت فایل‌های سورس مپ  (source map)


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

// فعال کردن ساخت سورس مپ‌ها 
npm run webpack -- -d 
// یا  در هنگام نصب گلوبال
webpack -d
// جهت استفاده به همراه وب سرور
npm run webpackserver -- -d
// یا به صورت نصب گلوبال
webpack-dev-server -d
راه دوم با استفاده از انجام تغییرات در فایل پیکربندی وبپک می‌باشد؛ به این صورت که کلیدی را به این فایل اضافه می‌کنیم.
// webpack.config.js
// کلید جدید اضافه شده در فایل پیکربندی
devtool:"#source-map"
حال در هنگام فراخوانی وبپک فایل سورس مپ نیز ساخته خواهد شد و احتیاجی به استفاده از پرچم خط فرمان در هنگام فراخوانی نیست.
با اجرای وب سرور وبپک خواهید دید که سورس مپ‌ها در منوی توسعه دهنده‌ی مرورگر قابل دستیابی می‌باشند.

ساخت چندین باندل گوناگون

قصد داریم به پروژه، دو صفحه‌ی دیگر را نیز با نام‌های aboutme و contact اضافه کنیم. هر یک از این صفحات اسکریپت مخصوص به خود را خواهد داشت و باندل نهایی نیز شامل تمامی آنها خواهد شد. در صورتی که این خروجی مطلوب ما نباشد و به طور مثال بخواهیم مکانیزمی شبیه به lazy loading اسکریپت‌ها را داشته باشیم و فقط زمانی اسکریپت‌ها بارگذاری شوند که به آنها احتیاج باشد، برای انجام این کار با وبپک به صورت زیر عمل خواهیم کرد.
دو صفحه‌ی html جدید را با عناوین ذکر شده‌ی بالا به پوشه‌ی assets اضافه می‌کنیم و برای هریک نیز اسکریپتی با همان نام خواهیم ساخت و در پوشه‌ی js قرار می‌دهیم.
محتوای صفحات بدین شکل می‌باشد.
// index.html file
<html>
<head>

    <title>
        third part of webpack tut!
    </title>
</head>

<body>
    <nav>
        <a href="aboutme.html">about me</a>
        <a href="contact.html">contact</a>
    </nav>
    <h1>webpack is awesome !</h1>
    <script src="assets/js/shared.js"></script>
    <script src="assets/js/index.js"></script>
</body>

</html>

// aboutme.html file
<html>

<head>

    <title>
        about me page !
    </title>
</head>

<body>
    <nav>
        <a href="index.html">index</a>
        <a href="contact.html">contact</a>
    </nav>
    <h1>webpack is awesome !</h1>
    <script src="assets/js/shared.js"></script>
    <script src="assets/js/aboutme.js"></script>
</body>

</html>

// contact.html file

<html>

<head>

    <title>
        contact me page !
    </title>
</head>

<body>
    <nav>
        <a href="index.html">index</a>
        <a href="aboutme.html">about me</a>
    </nav>
    <h1>webpack is awesome !</h1>
    <script src="assets/js/shared.js"></script>
    <script src="assets/js/contact.js"></script>
</body>

</html>
در هر یک از صفحات یک اسکریپت مخصوص آن صفحه و همچنین یک اسکریپت با نام shared.js که قبلا فرض کردیم نقش ماژولی را دارد که در سرتاسر پروژه از آن استفاده می‌شود، اضافه شده است. حال این تغییرات را در فایل پیکربندی وبپک به آن معرفی می‌کنیم.
var path = require("path");
var webpack = require("webpack");
// وارد کردن پلاگینی از وب پک برای ساخت تکه‌های مختلف اسکریپت‌ها 
// معرفی اسکریپت shared.js
var commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin("shared.js");
module.exports = {
    context:path.resolve("js"),
    //entry:['./shared.js','./main.ts']
   // معرفی اسکریپت‌های جدید به وبپک
    entry:{
        index:"./main.js",
        aboutme:"./aboutme.js",
        contact:"./contact.js"
    }
    ,output:{
        path:path.resolve("build/js"),
        publicPath:"assets/js",
     //   filename:'bundle.js'
     // به جای یک باندل کلی از وبپک میخاهیم برای هر ورودی باندلی جدید بسازد
        filename:"[name].js"
    }
    // رجیستر کردن پلاگین 
    ,plugins:[commonChunkPlugin]
    ,
    devServer:{
        contentBase:"assets"
    }
    //,devtool:"#source-map"
    ,watch :true
    ,module:{...
    }
    
}
جهت انجام این کار از یک پلاگین وبپک با نام CommonsChunkPlugin کمک گرفته‌ایم که به ما کمک می‌کند اسکریپت shared.js را به عنوان یک وابستگی در تمامی صفحاتمان داشته باشیم. نحوه‌ی کار این پلاگین نیز از نامش مشخص است و نقاط Common را می‌توان با آن مشخص کرد. تغییر بعدی نیز در کلید entry می‌باشد که اسکریپت‌های جدید را با استفاده از اسمشان به وبپک معرفی کرده‌ایم و سپس در کلید output نیز به وبپک خبر داده‌ایم که برای هر ورودی، باندل جداگانه‌ی خود را بسازد. تکه کد  filename:[name].js به وبپک می‌گوید که باندل‌های جداگانه، با نام خود اسکریپت ساخته شوند و در نهایت کلید جدید plugins به وبپک پلاگین CommonsChunkPlugin را اضافه می‌کند.
حال با اجرای وبپک می‌توان دید که سه باندل ساخته شده که همگی به اسکریپت shared.js وابستگی دارند و اگر این اسکریپت را از صفحات HTML حذف کنید، با خطا رو به رو خواهید شد. این پلاگین قدرت ساخت باندل‌هایی با خاصیت مشخص کردن وابستگی‌ها و همچنین تو در تویی‌ها خاص را نیز دارد. برای مطالعه‌ی بیشتر می‌توانید به اینجا مراجعه کنید: پلاگین commonsChunk

در قسمت بعدی با استفاده از وبپک فایل‌های css، فونت‌ها و تصاویر را نیز باندل خواهیم کرد.

فایل‌های مطلب:
سورس تا قبل از قسمت ایجاد تغییرات در ساختار فایل‌های پروژه :dntwebpack-part3-beforeFileAndFolderManagment.zip
سورس برای بعد از ایجاد تغییرات در ساختار فایل‌های پروژه : dntwebpack-part3AfterFileOrganization.zip

مطالب
AngularJS #3
در این مقاله مفاهیم انقیاد داده (Data Binding)، تزریق وابستگی (Dependency Injection)،هدایت گر‌ها (Directives) و سرویس‌ها را بررسی خواهیم کرد و از مقاله‌ی آینده، به بررسی ویژگی‌ها و امکانات AngularJS در قالب مثال خواهیم پرداخت.
 
انقیاد داده (Data Binding)
سناریو هایی وجود دارد که در آن‌ها باید اطلاعات قسمتی از صفحه به صورت نامتقارن (Asynchronous) با داده‌های دریافتی جدید به روز رسانی شود. روش معمول برای انجام چنین کاری؛ دریافت داده‌ها از سرور است که عموما به فرم HTML میباشند و جایگزینی آن با بخشی از صفحه که قرار است به روز رسانی شود، اما حالتی را در نظر بگیرید که با داده هایی از جنس JSON طرف هستید و اطلاعات صفحه را با این داده‌ها باید به روز رسانی کنید. معمولا برای حل چنین مشکلی مجبور به نوشتن مقدار زیادی کد هستید تا بتوانید به خوبی اطلاعات View را به روز رسانی کنید. حتما با خودتان فکر کرده اید که قطعا راهی وجود دارد تا بدون نوشتن کدی، قسمتی از View را به Model متناظر خود نگاشت کرده و این دو به صورت بلادرنگ از تغییرات یکدیگر آگاه شوند. این عمل عموما به مفهوم انقیاد داده شناخته می‌شود و Angular هم به خوبی از انقیاد داده دوطرفه پشتیبانی می‌کند.
برای مشاهده این ویژگی در Angular، مثال مقاله‌ی قبل را به کد‌های زیر تغییر دهید تا پیغام به صورت پویا توسط کاربر وارد شود:
<!DOCTYPE html>
<html ng-app>
<head>
    <title>Sample2</title>
</head>
<body>
    <div>
        <input type="text" ng-model="greeting.text" />
        <p>{{greeting.text}}, World!</p>
    </div>
    <script src="../Scripts/angular.js"></script>
</body>
</html>
بدون نیاز به حتی یک خط کد نویسی! با مشخص کردن input به عنوان Model از طریق ng-model، خاصیت greeting.text که در داخل {{ }} مشخص شده را به متن داخل textbox  مقید (bind) کردیم.  نتیجه می‌گیریم که جفت آکلود {{ }} برای اعمال Data Binding استفاده می‌شود.
حال یک دکمه نیز بر روی فرم قرار می‌دهیم که با کلیک کردن بر روی آن، متن داخل textbox را نمایش دهد.
<!DOCTYPE html>
<html ng-app>
<head>
    <title>Sample2</title>
</head>
<body>
    <div ng-controller="GreetingController">
        <input type="text" ng-model="greeting.text" />
        <p>{{greeting.text}}, World!</p>
        <button ng-click="showData()">Show</button>
    </div>
    <script src="../Scripts/angular.js"></script>
    <script>
        var GreetingController = function ($scope, $window) {
            $scope.greeting = {
                text: "Hello"
            };

            $scope.showData = function () {
                $window.alert($scope.greeting.text);
            };
        };
    </script>
</body>
</html>
به کمک ng-click، تابع showData به هنگام کلیک شدن، فراخوانی می‌شود. window$ نیز به عنوان پارامتر کلاس GreetingController مشخص شده است. window$ نیز یکی از سرویس‌های پیش فرض تعریف شده توسط Angular است و ما در اینجا در سازنده‌ی کلاس آن را به عنوان وابستگی درخواست کرده ایم تا توسط سیستم تزریق وابستگی توکار، نمونه‌ی مناسب آن در اختیار ما بگذارد. window$ نیز تقریبا معادل شی window است و یکی از دلایل استفاده از آن ساده‌تر شدن نوشتن آزمون‌های واحداست.
حال متنی را داخل textbox نوشته  و دکمه‌ی show را فشار دهید. متن نوشته شده را به صورت یک popup  مشاهده خواهید کرد.
همچنین شی scope$ نیز نمونه‌ی مناسب آن توسط سیستم تزریق وابستگی Angular، در اختیار Controller قرار می‌گیرد و نمونه‌ی در اختیار قرارگرفته، برای ارتباط با View Model و سیستم انقیاد داده استفاده می‌شود.
معمولا انقیاد داده در الگوی طراحی (ModelView-ViewModel(MVVM مطرح است و به این دلیل که این الگوی طراحی به خوبی با الگوی طراحی MVC سازگار است، این امکان در Angular گنجانده شده است. 
   
تزریق وابستگی (Dependency Injection)
تا به این جای کار قطعن  بار‌ها و بار‌ها اسم آن را خوانده اید. در مثال فوق، پارامتری با نام scope$ را برای سازنده‌ی کنترلر خود در نظر گرفتیم و ما بدون انجام هیچ کاری نمونه‌ی مناسب آن را که برای انجام اعمال انقیاد داده با viewmodel استفاده می‌شود را دریافت کردیم. به عنوان مثال، window$ را نیز در سازنده‌ی کلاس کنترلر خود به عنوان یک وابستگی تعریف کردیم و تزریق نمونه‌ی مناسب آن توسط سیستم تزریق وابستگی توکار Angular صورت می‌گرفت.
اگر با IOC Container‌ها در زبانی مثل #C کار کرده باشید، قطعا با IOC Container فراهم شده توسط Angular هم مشکلی نخواهید داشت.
اما یک مشکل! در زبانی مثل #C که همه‌ی متغیر‌های دارای نوع هستند، IOC Container با استفاده از Reflection، نوع پارامترهای درخواستی توسط سازنده‌ی کلاس را بررسی کرده و با توجه به اطلاعاتی که ما از قبل در دسترس آن قرار داده بودیم، نمونه‌ی مناسب آن را در اختیار در خواست کننده می‌گذارد.
اما در زبان جاوا اسکریپت که متغیر‌ها دارای نوع نیستند، این کار به چه شکل انجام می‌گیرد؟
Angular برای این کار از نام پارامتر‌ها استفاده می‌کند. برای مثال Angular از نام پارامتر scope$ می‌فهمد که باید چه نمونه ای را به کلاس تزریق کند. پس نام پارامتر‌ها در سیستم تزریق وابستگی Angular نقش مهمی را ایفا می‌کنند.
اما در زبان جاوا اسکریپت، به طور پیش فرض امکانی برای به دست آوردن نام پارامتر‌های یک تابع وجود ندارد؛ پس Angular چگونه نام پارامتر‌ها را به دست می‌آورد؟ جواب در سورس کد Angular و در تابعی به نام annotate نهفته است که اساس کار این تابع استفاده از چهار عبارت با قاعده (Regular Expression) زیر است.
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
تابع annotate تابعی را به عنوان پارامتر دریافت می‌کند و سپس با فراخواندن متد toString آن، کدهای آن تابع را به شکل یک رشته در می‌آورد. حال کدهای تابع را که اکنون به شکل یک رشته در دسترس است را با استفاده از عبارات با قاعده‌ی فوق پردازش می‌کند تا نام پارامتر‌ها را به دست آورد. در ابتدا کامنت‌های موجود در تابع را حذف می‌کند، سپس نام پارامتر‌ها را استخراج می‌کند و با استفاده از "," آن‌ها را جدا می‌کند و در نهایت نام پارامتر‌ها را در یک آرایه باز می‌گرداند.
استفاده از تزریق وابستگی، امکان نوشتن کدهایی با قابلیت استفاده مجدد و نوشتن ساده‌تر آزمون‌های واحد را فراهم می‌کند. به خصوص کدهایی که با سرور ارتباط برقرار می‌کنند را می‌توان به یک سرویس انتقال داد و از طریق تزریق وابستگی، از آن در کنترلر استفاده کرد. سپس در آزمون‌های واحد می‌توان قسمت ارتباط با سرور را با یک نمونه فرضی جایگزین کرد تا برای تست، احتیاجی به راه اندازی یک وب سرور واقعی و یا مرورگر نباشد.
    
Directives
یکی از مزیت‌های Angular این است که قالب‌ها را می‌توان با HTML نوشت و این را باید مدیون موتور قدرتمند تبدیل گر DOM بدانیم  که در آن گنجانده شده است و به شما این امکان را می‌دهد تا گرامر HTML را گسترش دهید.
تا به این جای کار با attribute‌های زیادی در قالب HTML روبرو شدید که متعلق به HTML نیست. به طور مثال: جفت آکولاد‌ها که برای انقیاد داده به کار برده می‌شود، ng-app که برای مشخص کردن بخشی که باید توسط Angular کامپایل شود، ng-controller که برای مشخص کردن این که کدام بخش از View متعلق به کدام Controller است و ... تمامی Directive‌های پیش فرض Angular هستند.
با استفاده از Directive‌ها می‌توانید عناصر و خاصیت‌ها و حتی رویداد‌های سفارشی برای HTML بنویسید؛ اما واقعا چه احتیاجی به تعریف عنصر سفارشی و توسعه گرامر HTML وجود دارد؟
HTML یک زبان طراحی است که در ابتدا برای تولید اسناد ایستا به وجود آمد و هیچ وقت هدفش تولید وب سایت‌های امروزی که کاملا پویا هستند نبود. این امر تا جایی پیش رفته است که HTML را از یک زبان طراحی تبدیل به یک زبان برنامه نویسی کرده است و احتیاج به چنین زبانی کاملا مشهود است. به همین دلیل جامعه‌ی وب مفهومی را به نام Web Components  مطرح کرده است. Web Components به شما امکان تعریف عناصر HTML سفارشی را می‌دهد. برای مثال شما یک تگ سفارشی به نام datepicker می‌نویسید که دارای رفتار و ویژگی‌های خاص خود است و به راحتی عناصر HTML رابا استفاده از آن توسعه می‌دهید. مطمئنا آینده‌ی وب این گونه است، اما هنوز خیلی از مرورگرها از این ویژگی پشتیبانی نمی‌کنند.
یکی دیگر از معادل‌های  Web Component‌های امروز را می‌توان ویجت‌های jQuery UI دانست. اگر بخواهم تعریفی از ویجت ارائه دهم به این گونه است که یک ویجت؛ کدهای HTML، CSS و javascript مرتبط به هم را کپسوله کرده است. مهم‌ترین مزیت ویجت ها، قابلیت استفاده‌ی مجدد آن‌هاست، به این دلیل که تمام منطق مورد نیاز را در خود کپسوله کرده است؛ برای مثال ویجت datepicker که به راحتی در برنامه‌های مختلف بدون احتیاج به نوشتن کدی قابل استفاده است.
خب، متاسفانه Web Component‌ها هنوز در دنیای وب امروزی رایج نشده اند و ویجت‌ها هم آنچنان  قدرت Web Component‌ها را ندارند. خب Angular با استفاده از امکان تعریف Directive‌های سفارشی به صورت cross-browser امکان تعریف عناصر سفارشیه همانند web Component‌ها را به شما می‌دهد. حتی به عقیده‌ی عده ای Directive‌ها بسیار قدرتمند‌تر از Web Components عمل می‌کنند و راحتی کار با آن‌ها بیشتر است.
با استفاده از Directive‌ها می‌توانید عنصر HTML سفارشی مثل </ datepicker>،  خاصیت سفارشی مثل ng-controller، رویداد سفارشی مثل ng-click را  تعریف کنید و یا حتی حالت و اتفاقات رخ داده در برنامه را زیر نظر بگیرید.
و این یکی از دلایلی است که می‌گویند Angular دارای ویژگی forward-thinking است.
البته Directive‌ها یکی از قدرتمند‌ترین امکانات فریم ورک AngularJS است و در آینده به صورت مفصل بر روی آن بحث خواهد شد.
    
سرویس‌ها در AngularJS
 حتما این جمله را در هنگام نوشتن برنامه‌ها با الگوی طراحی MVC بار‌ها و بار‌ها شنیده اید که در Controller‌ها نباید منطق تجاری و پیچیده ای را پیاده سازی کرد و باید به قسمت‌های دیگری به نام سرویس‌ها منتقل شوند و سپس در سازنده‌ی کلاس کنترلر به عنوان پارامتر تعریف شوند تا توسط Angular نمونه‌ی مناسب آن به کنترلر تزریق شود. Controller‌ها نباید پیاده کننده‌ی هیچ منطق تجاری و یا اصطلاحا business برنامه باشد و باید از لایه‌ی سرویس استفاده کنند و تنها وظیفه‌ی کنترلر باید مشخص کردن انقیاد داده و حالت برنامه باشد.
دلیل استفاده از سرویس‌ها در کنترلر ها، نوشتن ساده‌تر آزمون‌های واحد و استفاده‌ی مجدد از سرویس‌ها در قسمت‌های مختلف پروژه و یا حتی پروژه‌های دیگر است.
معمولا اعمال مرتبط در ارتباط با سرور را در سرویس‌ها پیاده سازی می‌کنند تا بتوان در موقع نوشتن آزمون‌های واحد یک نمونه‌ی فرضی را خودمان ساخته و آن را به عنوان وابستگی به کنترلری که در حال تست آن هستیم تزریق کنیم، در غیر این صورت احتیاج به راه اندازی یک وب سرور واقعی برای نوشتن آزمون‌های واحد و در نتیجه کند شدن انجام آزمون را در بر دارد. قابلیت استفاده‌ی مجدد سرویس هم به این معناست که منطق پیاده سازی شده در آن نباید ربطی به رابط کاربری و ... داشته باشد. برای مثال یک سرویس به نام userService باید دارای متد هایی مثل دریافت لیست کاربران، افزودن کاربر و ... باشد و بدیهی است که از این سرویس‌ها می‌شود در قسمت‌های مختلف برنامه استفاده کرد. همچنین سرویس‌ها در Angular به صورت Singleton در اختیار کنترلر‌ها قرار می‌گیرند  و این بدین معناست که یک نمونه از هر سرویس ایجاد شده و به بخش‌های مختلف برنامه تزریق می‌شود. 
    
مفاهیم پایه ای AngularJs به پایان رسید. در مقاله بعدی یک مثال تقریبا کامل را نوشته و با اجزای مختلف Angular بیشتر آشنا می‌شویم.
   
با تشکر از مهدی محزونی برای بازبینی مطلب
نظرات مطالب
آموزش TypeScript #1
بله امکان پذیر است. اما با توجه به این نکته که فلسفه وجودی TypeScript این است که در پروژه هایی با مقیاس پزرگ برای سازمان دهی کدهای سمت کلاینت مورد استفاده قرار گیرند و یکی از روش‌های سازمان دهی کدها این است که کد‌های TypeScript در فایل هایی جداگانه با پسوند ts ذخیره شده تا کامپایل و تبدیل به کد JavaScript شوند(مهم‌ترین مزیت این روش این است که از نوشتن کد‌های تکراری جلوگیری می‌شود). اما در صورتی که مایل به نوشتن کد به صورت Embed در تگ Script هستید باید از پروژه‌های متن بازی همچون TypeScript Compile یا ts-htaccess  استفاده کنید.
مطالب
یک نکته درباره Angular routeProvider
بعد از مطالعه پست‌های ^ و ^    نکته ای به ذهنم رسید که بیان آن از بنده و مطالعه آن توسط شما خالی از لطف نیست. اگر مثال‌های پیاده سازی شده در پست‌های ^ و ^ را با AngularJs نسخه 1.2 اجرا نمایید به طور حتم با خطا روبرو می‌شوید و نتیجه مورد نظر حاصل نمی‌شود. در این پست نیز توسط یکی از دوستان اشاره ای به این مطلب شد.
دلیل خطا این است که از نسخه 1.2 به بعد در Angular سیستم مسیر یابی به این شکل امکان پذیر نیست و بخش مسیریابی به یک فایل دیگر به نام angular-route.js منتقل شده است. در نتیجه اگر به سبک نسخه‌های قبلی Angular از سیستم مسیریابی استفاده نمایید با خطا مواجه خواهید شد و خطای مورد نظر هم مربوط به عدم توانایی در تزریق وابستگی routeProvider$ به ماژول مورد نظر است. حال راه حل چیست؟
کافیست در هنگام تعریف ماژول، ngRoute را به عنوان وابستگی ماژول تعیین نمایید. و از طرفی فایل اسکریپتی angular-route.js را بعد از angular.js فراخوانی کنید.
بررسی مثال:
کد‌های زیر مربوط به مثال‌های پست قبلی می‌باشد که شرح کامل آن در این پست است:
var myFirstRoute = angular.module('myFirstRoute', []);
   
myFirstRoute.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/pageOne', {
        templateUrl: 'templates/page_one.html',
        controller: 'ShowPage1Controller'
      }).
      when('/pageTwo', {
        templateUrl: 'templates/page_two.html',
        controller: 'ShowPage2Controller'
      }).
      otherwise({
        redirectTo: '/pageOne'
      });
}]);
 
 
myFirstRoute.controller('ShowPage1Controller', function($scope) {
    $scope.message = 'Content of page-one.html';
});
  
  
myFirstRoute.controller('ShowPage2Controller', function($scope) {
    $scope.message = 'Content of page-two.html';
});
برای هماهنگ کردن مثال بالا با نسخه 1.2 باید به روش زیر عمل نمود:
var myFirstRoute = angular.module('myFirstRoute',['ngRoute']);
   
myFirstRoute.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/pageOne', {
        templateUrl: 'templates/page_one.html',
        controller: 'ShowPage1Controller'
      }).
      when('/pageTwo', {
        templateUrl: 'templates/page_two.html',
        controller: 'ShowPage2Controller'
      }).
      otherwise({
        redirectTo: '/pageOne'
      });
}]);
تنها تغییر، مشخص کردن ngRoute به عنوان وابستگی ماژول myFirstRoute است(خط اول). نکته دیگر لود فایل angular-route.js قبل از فراخوانی فایل بالا و بعد از فراخوانی فایل angular.js است:
<body ng-app="app">
   
    <div>
        <div>
        <div>
            <ul>
                <li><a href="#pageOne"> Show page one </a></li>
                <li><a href="#pageTwo"> Show page two </a></li>
            </ul>
        </div>
        <div>
            <div ng-view></div>
        </div>
        </div>
    </div>
   
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
     <script src="angular-route.js"></script>
    <script src="app.js"></script>
   
  </body>

نظرات مطالب
یکپارچه سازی Angular CLI و ASP.NET Core در VS 2017
مرحله
معادل آن در پروژه‌های قدیمی MVC 5
  ایجاد یک پروژه‌ی جدید ASP.NET Core در VS 2017  
 یک پروژه‌ی جدید Web API را ایجاد کنید. 
  تنظیمات یک برنامه‌ی ASP.NET Core خالی برای اجرای یک برنامه‌ی Angular CLI  
 به این موارد نیازی نخواهید داشت. چون پروژه‌های MVC 5 برخلاف ASP.NET Core، پوشه‌هایی را که دستی به آن اضافه نکنید، به صورت خودکار به پروژه اضافه نمی‌کند. بنابراین فایل‌های Angular-CLI را به Solution Explorer وارد نکنید و بهترین روش کار کردن با آن‌ها از طریق VSCode است. در اینجا برای back-end (کار با Web API) از VS کامل استفاده کنید و برای front-end از VSCode. 
  افزودن یک کنترلر Web API جدید  
 کلیات آن با MVC 5 یکی است. 
  تنظیمات فایل آغازین یک برنامه‌ی ASP.NET Core جهت ارائه‌ی برنامه‌های Angular  
 معادل قسمت URL Rewrite آن، از نکته‌ی web.config مطلب «مسیریابی در Angular - قسمت اول - معرفی»، قسمت «تفاوت بین آدرس‌های HTML 5 و Hash-based» استفاده کنید. 
  ایجاد ساختار اولیه‌ی برنامه‌ی Angular CLI در داخل پروژه‌ی جاری
 یکی هست. 
  تنظیم محل خروجی نهایی Angular CLI به پوشه‌ی wwwroot  
 یکی هست. فقط شاید علاقمند باشید مسیر "" (پوشه‌ی ریشه) را بجای wwwroot تنظیم کنید. 
 فراخوانی کنترلر Web API برنامه در برنامه‌ی Angular CLI  
 یکی هست. 
  نصب وابستگی‌های برنامه‌ی Angular CLI  
 یکی هست. 
  روش اول اجرای برنامه‌های مبتنی بر ASP.NET Core و Angular CLI  
 یکی هست. 
  روش دوم اجرای برنامه‌های مبتنی بر ASP.NET Core و Angular CLI  
 در اینجا نیازی به آن نیست ولی در کل مطالعه‌ی نکات آن مفید است.
 فایل‌های bat ارائه شده و یا روش NPM Task Runner در نظرات   یکی هستند.