9

उत्पन्न सहित मैं एक साइट है कि गतिशील रूप से जावास्क्रिप्ट उत्पन्न करता है। उत्पन्न कोड का वर्णन करता है टाइप-मेटाडाटा और कुछ सर्वर साइड स्थिरांक ताकि ग्राहकों को आसानी से सर्वर की सेवाओं का उपभोग कर सकते हैं - इसलिए यह बहुत संचित करने योग्य है।ASP.NET बंडलिंग/minification: गतिशील रूप से जावास्क्रिप्ट

उत्पन्न जावास्क्रिप्ट एक ASP.NET MVC नियंत्रक द्वारा पेश किया जाता है; तो यह एक उरी है; ~/MyGeneratedJs कहें।

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

मैं गतिशील रूप से एक बंडल में जावास्क्रिप्ट उत्पन्न शामिल कर सकते हैं?

उत्तर

4

डैरिन वर्तमान में केवल bundling स्थिर फाइलों पर काम करता है सही है,। लेकिन आप पुरानी सामग्री अप करने के लिए के साथ एक प्लेसहोल्डर फ़ाइल जोड़ सकते हैं अगर, बंडलिंग सेटअप फ़ाइल परिवर्तन सूचनाएं जो स्वचालित रूप से जब प्लेसहोल्डर फ़ाइल परिवर्तन का पता लगाने जाएगा करता है।

इसके अलावा हम जल्द ही वर्चुअलपाथप्रोवाइडर्स का उपयोग करने जा रहे हैं जो गतिशील रूप से जेनरेट की गई सामग्री की सेवा करने का एक तरीका हो सकता है।

अद्यतन: 1.1-alpha1 रिहाई जो VirtualPathProviders साथ वीपीपी

+0

यह अच्छा लगता है! क्या आपके पास कोई ब्लॉग या कुछ समाचार साइट है जिसे आप इस तरह के विकास के लिए अनुशंसा करना चाहते हैं? –

+0

हमने अभी हमारी कोडप्लेक्स साइट सार्वजनिक कर दी है, कोड अभी तक नहीं है, लेकिन शायद यह है कि आप लंबे समय तक क्या चाहते हैं: http://aspnetoptimization.codeplex.com –

+1

वास्तव में यह समझ में नहीं आता कि प्लेसहोल्डर फ़ाइल का क्या मतलब है। यदि मेरे पास डायनेमिक एमवीसी रूट के समान डिस्क के साथ डिस्क पर एक फ़ाइल है, तो इसे वापस कर दिया जाएगा और मेरी कार्रवाई कभी निष्पादित नहीं होगी। मैं क्या खो रहा हूँ? –

3

यह संभव नहीं है। बंडल केवल स्थिर फाइलों के साथ काम करते हैं।

+0

यदि आवश्यक हो तो मैं प्लेसहोल्डर फ़ाइल जोड़ने के साथ ठीक हूं - मैं चाहता हूं कि सामग्री स्वचालित रूप से सर्वर-साइड कोड के साथ समन्वयित हो। –

5

के लिए समर्थन हासिल है यह अब संभव है अब बाहर है। बंडलिंग प्रक्रिया में गतिशील सामग्री के एकीकरण के लिए निम्न चरणों की आवश्यकता होती है:

  1. आवश्यक सामग्री का अनुरोध/निर्माण करने वाले तर्क को लिखना।

    public static class ControllerActionHelper 
    { 
        public static string RenderControllerActionToString(string virtualPath) 
        { 
         HttpContext httpContext = CreateHttpContext(virtualPath); 
         HttpContextWrapper httpContextWrapper = new HttpContextWrapper(httpContext); 
    
         RequestContext httpResponse = new RequestContext() 
         { 
          HttpContext = httpContextWrapper, 
          RouteData = RouteTable.Routes.GetRouteData(httpContextWrapper) 
         }; 
    
         // Set HttpContext.Current if RenderActionToString is called outside of a request 
         if (HttpContext.Current == null) 
         { 
          HttpContext.Current = httpContext; 
         } 
    
         IControllerFactory controllerFactory = ControllerBuilder.Current.GetControllerFactory(); 
         IController controller = controllerFactory.CreateController(httpResponse, 
          httpResponse.RouteData.GetRequiredString("controller")); 
         controller.Execute(httpResponse); 
    
         return httpResponse.HttpContext.Response.Output.ToString(); 
        } 
    
        private static HttpContext CreateHttpContext(string virtualPath) 
        { 
         HttpRequest httpRequest = new HttpRequest(string.Empty, ToDummyAbsoluteUrl(virtualPath), string.Empty); 
         HttpResponse httpResponse = new HttpResponse(new StringWriter()); 
    
         return new HttpContext(httpRequest, httpResponse); 
        } 
    
        private static string ToDummyAbsoluteUrl(string virtualPath) 
        { 
         return string.Format("http://dummy.net{0}", VirtualPathUtility.ToAbsolute(virtualPath)); 
        } 
    } 
    
  2. एक आभासी पथ प्रदाता है कि मौजूदा एक लपेटता लागू करने और सभी आभासी रास्तों कि गतिशील सामग्री वितरित करना चाहिए रोकना: नियंत्रक से जनरेट कर रहा है सामग्री सीधे काम का एक सा की आवश्यकता है।

    public class ControllerActionVirtualPathProvider : VirtualPathProvider 
    { 
        public ControllerActionVirtualPathProvider(VirtualPathProvider virtualPathProvider) 
        { 
         // Wrap an existing virtual path provider 
         VirtualPathProvider = virtualPathProvider; 
        } 
    
        protected VirtualPathProvider VirtualPathProvider { get; set; } 
    
        public override string CombineVirtualPaths(string basePath, string relativePath) 
        { 
         return VirtualPathProvider.CombineVirtualPaths(basePath, relativePath); 
        } 
    
        public override bool DirectoryExists(string virtualDir) 
        { 
         return VirtualPathProvider.DirectoryExists(virtualDir); 
        } 
    
        public override bool FileExists(string virtualPath) 
        { 
         if (ControllerActionHelper.IsControllerActionRoute(virtualPath)) 
         { 
          return true; 
         } 
    
         return VirtualPathProvider.FileExists(virtualPath); 
        } 
    
        public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, 
         DateTime utcStart) 
        { 
         AggregateCacheDependency aggregateCacheDependency = new AggregateCacheDependency(); 
    
         List<string> virtualPathDependenciesCopy = virtualPathDependencies.Cast<string>().ToList(); 
    
         // Create CacheDependencies for our virtual Controller Action paths 
         foreach (string virtualPathDependency in virtualPathDependenciesCopy.ToList()) 
         { 
          if (ControllerActionHelper.IsControllerActionRoute(virtualPathDependency)) 
          { 
           aggregateCacheDependency.Add(new ControllerActionCacheDependency(virtualPathDependency)); 
           virtualPathDependenciesCopy.Remove(virtualPathDependency); 
          } 
         } 
    
         // Aggregate them with the base cache dependency for virtual file paths 
         aggregateCacheDependency.Add(VirtualPathProvider.GetCacheDependency(virtualPath, virtualPathDependenciesCopy, 
          utcStart)); 
    
         return aggregateCacheDependency; 
        } 
    
        public override string GetCacheKey(string virtualPath) 
        { 
         return VirtualPathProvider.GetCacheKey(virtualPath); 
        } 
    
        public override VirtualDirectory GetDirectory(string virtualDir) 
        { 
         return VirtualPathProvider.GetDirectory(virtualDir); 
        } 
    
        public override VirtualFile GetFile(string virtualPath) 
        { 
         if (ControllerActionHelper.IsControllerActionRoute(virtualPath)) 
         { 
          return new ControllerActionVirtualFile(virtualPath, 
           new MemoryStream(Encoding.Default.GetBytes(ControllerActionHelper.RenderControllerActionToString(virtualPath)))); 
         } 
    
         return VirtualPathProvider.GetFile(virtualPath); 
        } 
    
        public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) 
        { 
         return VirtualPathProvider.GetFileHash(virtualPath, virtualPathDependencies); 
        } 
    
        public override object InitializeLifetimeService() 
        { 
         return VirtualPathProvider.InitializeLifetimeService(); 
        } 
    } 
    
    public class ControllerActionVirtualFile : VirtualFile 
    { 
        public CustomVirtualFile (string virtualPath, Stream stream) 
         : base(virtualPath) 
        { 
         Stream = stream; 
        } 
    
        public Stream Stream { get; private set; } 
    
        public override Stream Open() 
        { 
         return Stream; 
        } 
    } 
    

    तुम भी CacheDependency लागू करने के लिए यदि आप इसे की जरूरत है:

    public class ControllerActionCacheDependency : CacheDependency 
    { 
        public ControllerActionCacheDependency(string virtualPath, int actualizationTime = 10000) 
        { 
         VirtualPath = virtualPath; 
         LastContent = GetContentFromControllerAction(); 
    
         Timer = new Timer(CheckDependencyCallback, this, actualizationTime, actualizationTime); 
        } 
    
        private string LastContent { get; set; } 
    
        private Timer Timer { get; set; } 
    
        private string VirtualPath { get; set; } 
    
        protected override void DependencyDispose() 
        { 
         if (Timer != null) 
         { 
          Timer.Dispose(); 
         } 
    
         base.DependencyDispose(); 
        } 
    
        private void CheckDependencyCallback(object sender) 
        { 
         if (Monitor.TryEnter(Timer)) 
         { 
          try 
          { 
           string contentFromAction = GetContentFromControllerAction(); 
    
           if (contentFromAction != LastContent) 
           { 
            LastContent = contentFromAction; 
            NotifyDependencyChanged(sender, EventArgs.Empty); 
           } 
          } 
          finally 
          { 
           Monitor.Exit(Timer); 
          } 
         } 
        } 
    
        private string GetContentFromControllerAction() 
        { 
         return ControllerActionHelper.RenderControllerActionToString(VirtualPath); 
        } 
    } 
    
  3. अपने आभासी पथ प्रदाता रजिस्टर:

    public static void RegisterBundles(BundleCollection bundles) 
    { 
        // Set the virtual path provider 
        BundleTable.VirtualPathProvider = new ControllerActionVirtualPathProvider(BundleTable.VirtualPathProvider); 
    
        bundles.Add(new Bundle("~/bundle") 
         .Include("~/Content/static.js") 
         .Include("~/JavaScript/Route1") 
         .Include("~/JavaScript/Route2")); 
    } 
    
  4. वैकल्पिक: अपने विचारों को Intellisense समर्थन जोड़ें। अपने दृश्य के भीतर <script> टैग का उपयोग करें और उन्हें एक कस्टम ViewResult द्वारा हटाया जा करते हैं:

    public class DynamicContentViewResult : ViewResult 
    { 
        public DynamicContentViewResult() 
        { 
         StripTags = false; 
        } 
    
        public string ContentType { get; set; } 
    
        public bool StripTags { get; set; } 
    
        public string TagName { get; set; } 
    
        public override void ExecuteResult(ControllerContext context) 
        { 
         if (context == null) 
         { 
          throw new ArgumentNullException("context"); 
         } 
    
         if (string.IsNullOrEmpty(ViewName)) 
         { 
          ViewName = context.RouteData.GetRequiredString("action"); 
         } 
    
         ViewEngineResult result = null; 
    
         if (View == null) 
         { 
          result = FindView(context); 
          View = result.View; 
         } 
    
         string viewResult; 
    
         using (StringWriter viewContentWriter = new StringWriter()) 
         { 
          ViewContext viewContext = new ViewContext(context, View, ViewData, TempData, viewContentWriter); 
    
          View.Render(viewContext, viewContentWriter); 
    
          if (result != null) 
          { 
           result.ViewEngine.ReleaseView(context, View); 
          } 
    
          viewResult = viewContentWriter.ToString(); 
    
          // Strip Tags 
          if (StripTags) 
          { 
           string regex = string.Format("<{0}[^>]*>(.*?)</{0}>", TagName); 
           Match res = Regex.Match(viewResult, regex, 
            RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline | RegexOptions.Singleline); 
    
           if (res.Success && res.Groups.Count > 1) 
           { 
            viewResult = res.Groups[1].Value; 
           } 
           else 
           { 
            throw new InvalidProgramException(
             string.Format("Dynamic content produced by View '{0}' expected to be wrapped in '{1}' tag.", ViewName, TagName)); 
           } 
          } 
         } 
    
         context.HttpContext.Response.ContentType = ContentType; 
         context.HttpContext.Response.Output.Write(viewResult); 
        } 
    } 
    

    एक विस्तार विधि का उपयोग करें या अपने नियंत्रक करने के लिए एक सहायक समारोह जोड़ें:

    public static DynamicContentViewResult JavaScriptView(this Controller controller, string viewName, string masterName, object model) 
    { 
        if (model != null) 
        { 
         controller.ViewData.Model = model; 
        } 
    
        return new DynamicContentViewResult 
        { 
         ViewName = viewName, 
         MasterName = masterName, 
         ViewData = controller.ViewData, 
         TempData = controller.TempData, 
         ViewEngineCollection = controller.ViewEngineCollection, 
         ContentType = "text/javascript", 
         TagName = "script", 
         StripTags = true 
        }; 
    } 
    

चरणों समान हैं अन्य प्रकार की गतिशील सामग्री के लिए। उदाहरण के लिए Bundling and Minification and Embedded Resources देखें।

यदि आप इसे आजमाने की कोशिश करना चाहते हैं तो मैंने GitHub पर अवधारणा भंडार का सबूत जोड़ा।

संबंधित मुद्दे