Exemple #1
0
        /// <summary>
        /// Generates the URLs for a given bundle
        /// </summary>
        /// <param name="bundleName"></param>
        /// <param name="fileExt"></param>
        /// <param name="debug"></param>
        /// <returns></returns>
        private IEnumerable <string> GenerateBundleUrlsAsync(string bundleName, string fileExt, bool debug)
        {
            //TODO: We should cache this, but problem is how do we do that with file watchers enabled? We'd still have to lookup the bundleOptions
            // or maybe we just cache when file watchers are not enabled - probably the way to do it

            var bundle = _bundleManager.GetBundle(bundleName);

            if (bundle == null)
            {
                throw new BundleNotFoundException(bundleName);
            }

            if (bundle.Files.Count == 0)
            {
                return(Enumerable.Empty <string>());
            }

            var result = new List <string>();

            //get the bundle options from the bundle if they have been set otherwise with the defaults
            var bundleOptions = bundle.GetBundleOptions(_bundleManager, debug);

            //if not processing as composite files, then just use their native file paths
            if (!bundleOptions.ProcessAsCompositeFile)
            {
                var files = _fileSetGenerator.GetOrderedFileSet(bundle,
                                                                _processorFactory.CreateDefault(
                                                                    //the file type in the bundle will always be the same
                                                                    bundle.Files[0].DependencyType));
                result.AddRange(files.Select(d => d.FilePath));
                return(result);
            }

            var cacheBuster = _cacheBusterResolver.GetCacheBuster(bundleOptions.GetCacheBusterType());

            var url = _urlManager.GetUrl(bundleName, fileExt, debug, cacheBuster);

            if (!string.IsNullOrWhiteSpace(url))
            {
                result.Add(url);
            }

            return(result);
        }
        /// <summary>
        /// Handles requests for named bundles
        /// </summary>
        /// <param name="bundle">The bundle model</param>
        /// <returns></returns>
        public async Task <IActionResult> Bundle(
            [FromServices] BundleRequestModel bundle)
        {
            if (!_bundleManager.TryGetValue(bundle.FileKey, out Bundle foundBundle))
            {
                return(NotFound());
            }

            var bundleOptions = foundBundle.GetBundleOptions(_bundleManager, bundle.Debug);

            //now we need to determine if this bundle has already been created
            var compositeFilePath = new FileInfo(_fileSystemHelper.GetCurrentCompositeFilePath(bundle.CacheBuster, bundle.Compression, bundle.FileKey));

            if (compositeFilePath.Exists)
            {
                _logger.LogDebug($"Returning bundle '{bundle.FileKey}' from cache");

                //this is already processed, return it
                return(File(compositeFilePath.OpenRead(), bundle.Mime));
            }

            //the bundle doesn't exist so we'll go get the files, process them and create the bundle
            //TODO: We should probably lock here right?! we don't want multiple threads trying to do this at the same time, we'll need a dictionary of locks to do this effectively

            //get the files for the bundle
            var files = _fileSetGenerator.GetOrderedFileSet(foundBundle,
                                                            _processorFactory.CreateDefault(
                                                                //the file type in the bundle will always be the same
                                                                foundBundle.Files[0].DependencyType))
                        .ToArray();

            if (files.Length == 0)
            {
                return(NotFound());
            }

            using (var bundleContext = new BundleContext(bundle, compositeFilePath))
            {
                var watch = new Stopwatch();
                watch.Start();
                _logger.LogDebug($"Processing bundle '{bundle.FileKey}', debug? {bundle.Debug} ...");

                //we need to do the minify on the original files
                foreach (var file in files)
                {
                    await _preProcessManager.ProcessAndCacheFileAsync(file, bundleOptions, bundleContext);
                }

                //Get each file path to it's hashed location since that is what the pre-processed file will be saved as
                Lazy <IFileInfo> fi;
                var filePaths = files.Select(
                    x => _fileSystemHelper.GetCacheFilePath(x, bundleOptions.FileWatchOptions.Enabled, Path.GetExtension(x.FilePath), bundle.CacheBuster, out fi));

                using (var resultStream = await GetCombinedStreamAsync(filePaths, bundleContext))
                {
                    //compress the response (if enabled)
                    var compressedStream = await Compressor.CompressAsync(
                        //do not compress anything if it's not enabled in the bundle options
                        bundleOptions.CompressResult?bundle.Compression : CompressionType.none,
                        resultStream);

                    //save the resulting compressed file, if compression is not enabled it will just save the non compressed format
                    // this persisted file will be used in the CheckNotModifiedAttribute which will short circuit the request and return
                    // the raw file if it exists for further requests to this path
                    await CacheCompositeFileAsync(compositeFilePath, compressedStream);

                    _logger.LogDebug($"Processed bundle '{bundle.FileKey}' in {watch.ElapsedMilliseconds}ms");

                    //return the stream
                    return(File(compressedStream, bundle.Mime));
                }
            }
        }