ایجاد یک پروژه در روز (به جهت تست کدها و کتابخانههای جدید و یا ارتقاع کدهای موجود ) یکی از کارهای متداول برنامه نویسان است. در VsCode وقتی مجبور به ایجاد این پروژهها برای برنامه نویسان فول استک باشید این کار به خودی خود یک چالش محسوب میشود، چون میبایست پروژههای BackEnd , FrontEnd را به صورت جداگانه ایجاد کنیم وسپس تمامی ارتباطهای لازم را فراهم کنیم که وقت و انرژی زیادی میطلبد. با استفاده از این پلاگین به سادگی میتوان هر دو پروژه را به صورت گام به گام و به یک باره ایجاد کرد.
// نصب لودرهای مورد نظر npm install css-loader style-loader -D
//index.html file <html> <head> <title>webpack part 4</title> </head> <body> <h1>webpack is awesome</h1> <p>part 4 of tutorial</p> <div>i have a background</div> <h1>تست فونت !</h1> <script src="/assets/js/bundle.js"> </script> </body> </html>
//webpack.config.js var path = require("path"); var webpack = require("webpack"); module.exports = { context: path.resolve("js"), entry: ['./main.js'] , output: { path: path.resolve("build/js"), publicPath: "assets/js", filename: 'bundle.js' }, devServer: { contentBase: "assets" } , watch: true , module: { loaders: [ { test: /\.css$/ , exclude: /node_modules/ , loader: 'style-loader!css-loader' } ] } }
loader:'style-loader!css-loader'
// main.js file require("./../assets/main.css"); console.log(`i'm bundled by webpack`);
// main.css body{ background-color: #DAA520; }
در تصویر بالا مشخص است که در تگ Head صفحه، یک تگ جدید style، توسط وبپک ایجاد شده و استایل ما به صفحه تزریق شدهاست. همچنین اگر وبپک را به حالت Minify کردن باندل ببریم (در مطلب قبلی نحوهی این کار ذکر شد)، باندل نهایی برای فایلهای css نیز Minify خواهد شد.
استفاده از Sass با کمک وبپک
روش استفاده از Sass نیز تفاوتی با css نخواهد داشت و فقط کافی است Loader آن را در پروژه نصب کنیم و در نهایت آن را در فایل پیکربندی، به وبپک معرفی کنیم. با دستور زیر لودر Sass را در پروژه وارد میکنیم:
// نصب لودر sass npm install -D sass-loader node-sass
( node-sass به عنوان وابستگی لودر sass، در کنار آن نصب شده است)
حال به فایل پیکربندی میرویم و لودر جدید را به قسمت لودرها اضافه میکنیم:
// webpack.config.js module: { loaders: [ { test: /\.css$/ , exclude: /node_modules/ , loader: 'style-loader!css-loader' } ,{ test:/\.scss$/ ,exclude:/node_modules/ ,loader:'style-loader!css-loader!sass-loader' } ] }
در پوشهی assets نیز فایل جدیدی را با عنوان main.scss ساخته و محتوای زیر را در آن وارد میکنیم:
// main.scss $background-color:#DAA520; body{ background-color: $background-color; }
سپس در فایل main.js به جای وارد کردن فایل css قبلی، فایل scss جدید را با کمک require وارد میکنیم و در ادامه وبپک را اجرا میکنیم. خواهیم دید که مانند قبل بدون مشکلی وبپک اجرا شده، فایل scss را به css ترجمه کرده و سپس به کمک بقیه لودرها، به باندل اضافه میکند. استفاده از بقیهی فریمورکهای css مانند Less و ... نیز با کمک لودر آنها به همین صورت قابل انجام است.
استفاده از Autoprefixer
همان طور که تمامی قابلیتهای نسخهی جدید جاوااسکریپت در همهی مرورگرها به صورت سراسری پشتیبانی نمیشود، برای css نیز چنین مشکل مشابهی وجود دارد و برای استفادهی بهینهی از برخی قابلیتها نیاز داریم تا prefixهای مورد نیاز مرورگرهای مختلف را به فایلهای css مان اضافه کنیم. میتوانیم این روند را با کمک یک لودر وبپک، ساده و به صورت خودکار کرد. برای نصب این لودر دستور زیر را وارد میکنیم:
npm install -D autoprefixer-loader
و بعد از نصب شدن آن، در فایل پیکربندی وبپک به لودرهایی که برای فایلهای css و scss اضافه کرده بودیم، این لودر را نیز به صورت زنجیر وار اضافه میکنیم:
//webpack.config.js module: { loaders: [ { test: /\.css$/ , exclude: /node_modules/ , loader: 'style-loader!css-loader!autoprefixer-loader' } ,{ test:/\.scss$/ ,exclude:/node_modules/ ,loader:'style-loader!css-loader!autoprefixer-loader!sass-loader' } ] }
در هر دو لودری که برای css و scss ساخته بودیم، از لودر autoprefixer استفاده کردیم. برای تست اینکه این لودر بدون مشکل کار میکند، در فایل main.scss تغییر زیر را ایجاد میکنیم:
//main.scss $background-color:#DAA520; body{ background-color: $background-color; display: flex; }
حال با اجرای وبپک خواهیم دید که prefixهای مورد نیاز توسط لودر اضافه شده اند ( این لودر از کتابخانهی postcss کمک میگیرد).
باندل کردن تصاویر و فونتها با کمک وبپک
تا اینجا با نحوهی وارد کردن فایلهای استایل، مانند css و ... به باندل آشنا شدیم. در ادامه قصد داریم که تصاویر و فونتها را نیز وارد باندل کنیم. روند کار شبیه به گذشته است و این کار نیز به کمک لودرهای وبپک انجام خواهد شد.
جهت باندل کردن تصاویر و فونتها، به لودر جدیدی با نام url-loader احتیاج داریم. قبل از هر چیزی این لودر را در پروژه با کمک npm نصب میکنیم:
npm install -D url-loader file-loader
(لودر file-loader به عنوان وابستگی مورد نیاز است)
روند همچنان مثل گذشته است و پس از نصب لودر، وارد فایل پیکربندی شده و لودر جدید را به وبپک معرفی میکنیم:
//webpack.config.js file module: { loaders: [ { test: /\.css$/ , exclude: /node_modules/ , loader: 'style-loader!css-loader!autoprefixer-loader' } ,{ test:/\.scss$/ ,exclude:/node_modules/ ,loader:'style-loader!css-loader!autoprefixer-loader!sass-loader' },{ test:/\.(png|jpg|ttf|eot)$/ ,exclude:/node_modules/ ,loader:'url-loader?limit=100000' } ] }
در لودر اضافه شده، پسوند فایلهایی را که قصد داریم به باندل وارد شوند، معرفی میکنیم. در اینجا فرمتهای png , jpg ,ttf, eot ذکر شدهاند.
تنها نکتهی جدید، در مشخص کردن نام لودر وجود دارد و آن نیز قسمت پس از علامت ؟ میباشد. هنگام مشخص کردن اینکه از چه لودری قصد استفاده داریم، میتوانیم با استفاده از ؟ پارامترهایی را به لودر مورد نظر ارسال کنیم. در اینجا به پارامتر limit، مقدار 100000 را دادهایم که برای این لودر به این معناست که اگر حجم فایل در حال پردازش، حجمی بیشتر از این مقدار را داشت، این فایل را به صورت یک لینک جدا از باندل قرار بده. ولی اگر حجمی کمتر از این مقدار داشت، لودر به صورت خودکار فایل را به فرمت Base64 انکود میکند و در درون باندل قرار میدهد.
برای تست اینکه آیا این لودر به درستی کار میکند یا نه، یک تصویر نمونه را در فولدر assets قرار میدهیم و سپس در فایل main.scss تغییرات زیر را انجام میدهیم.
حجم عکس قرار داده شده نزدیک به 400 کیلوبایت است و با مقدار محدودیت مشخص شده، تصویر مورد نظر از باندل توسط وبپک خارج میشود و به صورت جداگانه در بیلد نهایی قرار میگیرد. در تصویر زیر مشخص است که مرورگر درخواست جداگانه ای برای تصویر ارسال کرده است:
حال محدودیت حجم فایل را بالا میبریم و میتوان دید که تصویر در باندل نهایی به صورت انکود شده قرار گرفته است .
قطعا انجام این کار برای تصاویری با حجم بالا مناسب نخواهد بود و برنامه نویس بسته به نیاز بایستی مقدار محدودیت حجم را برای لودر مشخص کند.
در تعریف بالا دیدیم که فرمتهای مورد نیاز برای وارد کردن فونت را نیز علاوه بر تصاویر، برای وبپک مشخص کردهایم. روند وارد کردن فونتها به باندل نیز تفاوتی با تصاویر ندارد و کافی است تعاریف مورد نیاز را در فایلهای css داشته باشیم.
برای مثال فونت ساحل در پوشهی assets قرار داده شده و در فایل main.scss تغییرات زیر انجام شدهاند:
// main.scss $background-color:#DAA520; div{ background-image: url("galaxy.jpg"); } @font-face { font-family: Sahel; src: url('Sahel.eot'); src: url('Sahel.eot?#iefix') format('embedded-opentype'), url('Sahel.woff') format('woff'), url('Sahel.ttf') format('truetype'); font-weight: normal; } @font-face { font-family: Sahel; src: url('Sahel-Bold.eot'); src: url('Sahel-Bold.eot?#iefix') format('embedded-opentype'), url('Sahel-Bold.woff') format('woff'), url('Sahel-Bold.ttf') format('truetype'); font-weight: bold; } @font-face { font-family: Sahel; src: url('Sahel-Black.eot'); src: url('Sahel-Black.eot?#iefix') format('embedded-opentype'), url('Sahel-Black.woff') format('woff'); font-weight: 900; } body{ background-color: $background-color; font-family: 'Sahel'; display: flex; }
تصویر زیر، نتیجهی اجرای وبپک برای تولید باندل است. در تصویر میتوان دید که هم فونتها و هم فایلهای تصاویر، توسط وبپک شناسایی شده و وارد باندل شدهاند:
روش دیگری برای وارد کردن تصاویر نیز موجود است؛ به این صورت که به فرض مثال یک تگ img در اسکریپت ساخته و سپس پروپرتی src آن را با کمک require برابر با آدرس تصویر مورد نظر قرار میدهیم. این روش نیز برای وبپک قابل فهم بوده و فایل وارد باندل میشود. در ادامه مثالی از این روش آورده شده است:
var img = document.createElement("img"); img.width="200px"; img.height="200px"; img.src= require("path to some image");
چند نکتهی پایانی :
1. در فایل پیکربندی همیشه پسوند فایلهایی را که در کلید entry قرار داشتند، مشخص کردیم:
entry:['./main.js','./shared.ts']
با کلیدی با نام resolve در فایل پیکربندی میتوان مشخص کرد در صورتیکه پسوند فایلی مشخص نبود، به ترتیب مشخص شده به دنبال آن بگردد. به طور مثال:
// webpack.config.js resolve:{ extensions:['','.js','.ts'] }
در تعریف بالا ذکر میشود در صورتیکه پسوند فایل ورودی مشخص نبود، ابتدا به دنبال فایل بدون پسوند، سپس فایلهایی با پسوند js و در نهایت به دنبال فایلهایی با پسوند ts بگرد. توجه داشته باشید که ترتیب مشخص کردن پسوند فایلها مهم است و وبپک بر اساس این ترتیب به دنبال فایل مورد نظر خواهد گشت.
حال میتوان مقدار کلید entry را اینطور تعریف کرد:
entry:['./main','./shared']
2.استفاده از فایلهای css ی که در درونشان فونتهای مورد نیاز لینک شدهاند تنها با استفاده از لودر css قابل انجام نیست. به طور مثال استفاده از کتابخانهی بوت استرپ تنها با این لودر ممکن نیست و بایستی لودر url-loader نیز در پروژه نصب شده باشد تا در هنگامیکه وبپک به فونتها برخورد کرد، بتواند آنها را وابسته به شرایط، وارد باندل نهایی کند.
فایلهای پروژه: dntwebpack-part4.zip
لینکهای هفته سوم دی
وبلاگها ، سایتها و مقالات ایرانی (داخل و خارج از ایران)
ASP. Net
- ویدیویی دربارهی ASP.Net 4 (بهبودهای حاصل شده در web forms از جهت کار با اسکریپتها خصوصا با تاکید بر jQuery و همچنین ذکر اینکه با آمدن ASP.Net MVC ، وب فرمها کهنه نشده و همچنان توسعه و بهبود داده خواهند شد)، یا مقالهای در این مورد
طراحی و توسعه وب
PHP
اسکیوال سرور
سی شارپ
عمومی دات نت
مسایل اجتماعی و انسانی برنامه نویسی
متفرقه
نگاهی به گزینههای مختلف مهیای جهت میزبانی SignalR
1) OWIN
2) ASP.NET Hosting
3) Self Hosting
4) Cloud و ویندوز Azure
1) OWIN
اگر به اسمبلیهای همراه با SignalR دقت کنید، یکی از آنها Microsoft.AspNet.SignalR.Owin.dll نام دارد. OWIN مخفف Open web server interface for .NET است و کار آن ایجاد لایهای بین وب سرورها و برنامههای وب میباشد. یکی از اهداف مهم آن ترغیب دنیای سورس باز به تهیه ماژولهای مختلف قابل استفاده در وب سرورهای دات نتی است. نکتهی مهمی که در SignalR و کلیه میزبانهای آن وجود دارد، بنا شدن تمامی آنها برفراز OWIN میباشد.
2) ASP.NET Hosting
بدون شک، میزبانی ASP.NET از هابهای SignalR، مرسومترین روش استفاده از این فناوری میباشد. این نوع میزبانی نیز برفراز OWIN بنا شده است. نصب آن توسط اجرای دستور پاور شل ذیل در یک پروژه وب صورت میگیرد:
PM> Install-Package Microsoft.AspNet.SignalR
3) خود میزبانی یا Self hosting
خود میزبانی نیز برفراز OWIN تهیه شده است و برای پیاده سازی آن نیاز است وابستگیهای مرتبط با آن، از طریق NuGet به کمک فرامین پاور شل ذیل دریافت شوند:
PM> Install-Package Microsoft.AspNet.SignalR.Owin PM> Install-Package Microsoft.Owin.Hosting -Pre PM> Install-Package Microsoft.Owin.Host.HttpListener -Pre
مراحل تهیه یک برنامه ثالث (برای مثال خارج از IIS یا یک وب سرور آزمایشی) به عنوان میزبان Hubs مورد نیاز به این شرح هستند:
الف) کلاس آغازین میزبان باید با پیاده سازی اینترفیسی به نام IAppBuilder تهیه شود.
ب) مسیریابیهای مورد نیاز تعریف گردند.
ج) وب سرور HTTP یا HTTPS توکار برای سرویس دهی آغاز گردد.
باید توجه داشت که در این حالت برخلاف روش ASP.NET Hosting، سایر اسمبلیهای برنامه جهت یافتن Hubهای تعریف شده، اسکن نمیشوند. همچنین هنگام کار با jQuery مباحث عنوان شده در مورد تنظیم دسترسیهای Cross domain نیز باید در اینجا اعمال گردند. به علاوه اجرای وب سرور توکار آن به دلایل امنیتی، نیاز به دسترسی مدیریتی دارد.
برای پیاده سازی یک نمونه، به برنامهای که تاکنون تهیه کردهایم، یک پروژه کنسول دیگر را به نام ConsoleHost اضافه کنید. البته باید درنظر داشت در دنیای واقعی این نوع برنامهها را عموما از نوع سرویسهای ویندوز NT تهیه میکنند.
در ادامه سه فرمان پاور شل یاد شده را برای افزودن وابستگیهای مورد نیاز فراخوانی نمائید. همچنین باید دقت داشت که این دستور بر روی پروژه جدید اضافه شده باید اجرا گردد.
using System; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using Microsoft.Owin.Hosting; using Owin; namespace SignalR02.ConsoleHost { public class Startup { public void Configuration(IAppBuilder app) { app.MapHubs(new HubConfiguration { EnableCrossDomain = true }); } } [HubName("chat")] public class ChatHub : Hub { public void SendMessage(string message) { var msg = string.Format("{0}:{1}", Context.ConnectionId, message); Clients.All.hello(msg); } } class Program { static void Main(string[] args) { using (WebApplication.Start<Startup>("http://localhost:1073/")) { Console.WriteLine("Press a key to terminate the server..."); Console.Read(); } } } }
سمت کلاینت استفاده از آن هیچ تفاوتی نمیکند و با جزئیات آن پیشتر آشنا شدهاید؛ برای مثال در کلاینت جیکوئری خاصیت connection.hub.url باید به مسیر جدید سرور هاب تنظیم گردد تا اتصالات به درستی برقرار شوند.
دریافت پروژه کامل مرتبط با این 4 قسمت (البته بدون فایلهای باینری آن، جهت کاهش حجم 32 مگابایتی)
SignalRSamples.zip
نسخه 0.4 Blazor
بررسی امکانات Bootstrap 4
اجزای جاوا اسکریپتی بوت استرپ 3
- در حال حاضر، کاملترین بستهی راست به چپ بوت استرپ 3 را در این آدرس میتوانید دریافت کنید.
- مثال پیوست شده در انتهای بحث، فایلهای کاملی دارد و آزمایش شده.
Url Routing در ASP.Net WebForms
نمونه آنرا در مطلب « پیاده سازی دکمه «بیشتر» یا «اسکرول نامحدود» به کمک jQuery در ASP.NET MVC » (کامنت آخر آن) پیاده سازی شده میتوانید مشاهده و دریافت کنید. از این قابلیت در سایت جاری در حال استفاده است. مثلا اگر به قسمت مطالب در بالای صفحه مراجعه کنید، چنین آدرسی قابل مشاهده است:
https://www.dntips.ir/postsarchive#/page/1/date/desc
در پایین صفحه اگر دراپ داونهای مرتب سازی را تغییر دهید، نام فیلد یا صعودی و نزولی بودن آدرس تغییر میکنند. شماره صفحه نیز با هر بار کلیک بر روی دکمهی بیشتر یکی اضافه میشود. همچنین این آدرسها را میشود ذخیره و عینا بازیابی کرد.
Popover بوت استرپ برای کار با منابع remote طراحی نشدهاست و نیاز است توابع API آنرا به همراه jQuery Ajax ترکیب کرد تا به تصویر فوق رسید.
مرحلهی اول: اکشن متدی که یک partial view را باز میگرداند
فرض کنید اکشن متدی که لیست کاربران رای دادهی به یک مطلب را باز میگرداند، چنین شکلی را دارد:
public ActionResult RenderResults(string param1) { var users = new[] { new User{ Id = 1, Name = "Test 1", Rating = 3}, new User{ Id = 2, Name = "Test 2", Rating = 4}, new User{ Id = 3, Name = "Test 3", Rating = 5} }; return PartialView("_RenderResults", model: users); }
@using RemotePopOver.Models @model IList<User> <ul id="ratings1" data-title="Ratings" class="list-unstyled"> @foreach (var user in Model) { <li> @user.Name <span class="badge pull-right">@user.Rating</span> </li> } </ul>
مرحلهی دوم: دریافت اطلاعات partial view با استفاده از jQuery Ajax و سپس درج آن در یک popover
میخواهیم با حرکت ماوس بر روی دکمهی سفارشی ذیل، یک popover ظاهر شده و محتوای خودش را از اکشن متد فوق تامین کند.
<span id="remotePopover1" aria-hidden="true" data-param1="test" data-popover-content-url="@Url.Action("RenderResults", "Home")" class="glyphicon glyphicon-info-sign btn btn-info"></span>
در ادامه نحوهی استفادهی از این ویژگیها را در jQuery Ajax مشاهده میکنید:
@section Scripts { <script type="text/javascript"> $(document).ready(function () { $('body').on('mouseenter', 'span[data-popover-content-url]', function () { var el = $(this); $.ajax({ type: "POST", url: $(this).data("popover-content-url"), data: JSON.stringify({ param1: $(this).data("param1") }), contentType: "application/json; charset=utf-8", dataType: "json", // controller is returning a simple text, not json complete: function (xhr, status) { var data = xhr.responseText; if (status === 'error' || !data) { el.popover({ content: 'Error connecting server!', trigger: 'focus', html: true, container: 'body', placement: 'auto', title: 'Error!' }).popover('show'); } else { el.popover({ content: data, trigger: 'focus', html: true, container: 'body', placement: 'auto', title: $('<html />').html(data).find('#ratings1:first').data('title') }).popover('show'); } } }); }).on('mouseleave', 'span[data-popover-content-url]', function () { $(this).popover('hide'); }); }); </script> }
خروجی partial view به صورت json نیست. بنابراین باید اطلاعات نهایی آنرا در callback ویژهی complete دریافت کرد. مقدار data دریافتی، معادل اطلاعات رندر شدهی partial view است. به همین جهت آنرا به خاصیت content متد popver ارسال میکنیم. همچنین چون خروجی patrtial view به همراه html است، نیاز است خاصیت html متد popover نیز به true تنظیم شود. در خاصیت title، نحوهی دسترسی به مقدار data-title تنظیم شدهی در partial view را مشاهده میکنید.
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید:
RemotePopOver.zip