2013-03-28 51 views
2

我使用servicestack/bundler在PowerShell构建脚本中合并和缩小我的js & css文件。如何将JavaScript和css文件作为PowerShell构建过程的一部分进行版本化?

作为此构建过程的一部分,我想在我的_Layout文件中找到生成的javascript和css文件,并自动附加查询字符串版本。

例如

<link type="text/css" rel="stylesheet" href="/Content/app.min.css?v=1")" /> 
<script type="text/javascript" src="/Content/app.min.js?v=1")"></script> 

成为

<link type="text/css" rel="stylesheet" href="/Content/app.min.css?v=2")" /> 
<script type="text/javascript" src="/Content/app.min.js?v=2")"></script> 

什么会在PowerShell中做到这一点的最有效方法是什么?

回答

1

我已经想通了,并已将解决方案上传到github。我选择在文件名instead of appending a querystring parameter at the end of the file内使用MD5散列。这是因为一些代理不使用querystrings缓存文件。

此解决方案如果没有更改也不会有版本文件。

这里的解决方案带有注释以提高可读性。

#region Variables 
    $directoryPath = Split-Path ((Get-Variable MyInvocation).Value).MyCommand.Path # directory the script is running from (document root) 
    $jsFilePath = "assets\scripts\"             # scripts path will end with trailing slash "\" 
    $cssFilePath = "assets\css\"              # css path will end with a trailing slash "\" 
    $jsFileNameRegex = [regex] '(nameOfYourProject\.).*(\.min\.js)'     # myApp.asdf1234.min.js 
    $cssFileNameRegex = [regex] '(nameOfYourProject\.).*(\.min\.css)'    # myApp.asdf1234.min.js 
    $filesContainingVersionedResourceRefs = @("$directoryPath\index.html")   # array of files to search for script/css references 
#endregion 


#region Functions 

# Function which versions javascript and css files using the content hash. 
# NOTE: this assumes that you have two "default" versions of your combined files 
# nameOfYourProject.css/js 
# nameOfYourProject.min.css/js 
function versionResource($fileToVersionRegex, $filePath){ 

    # Gets the default file name from the regex 
    $defaultFileName = $fileToVersionRegex.ToString() -replace "(\()|(\))|(\\)|(\*)", "" 
    $defaultFileName = $defaultFileName -replace "\.\.\.", "." 

    # Gets the content of the default file and creates a hash 
    $fileContent = Get-Content $filePath\$defaultFileName 
    $md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider 
    $utf8 = new-object -TypeName System.Text.UTF8Encoding 
    $hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($fileContent))) 
    $versionHash = $hash.Replace('-', '') 

    # Creates a new file name based on the content hash 
    $newFileName = $defaultFileName -replace "\.min", ".$versionHash.min" 

    # Tries to get the old versioned file name 
    $fileToVersion = Get-ChildItem $filePath | Where-Object {$_.Name -match $fileToVersionRegex} 
    if($fileToVersion -ne $null) { 
     $oldFileName = $fileToVersion.Name 
    } 

    # $newFileName is still just a string at this point. 
    # If the new version name doesn't match the old version name, 
    # then we know that we need to update everything to the new version. 
    if($oldFileName -ne $newFileName) { 

     # OPTIONAL 
     # remove the obsolete version of the file to be versioned 
     # You may choose to NOT remove the versioned file, however 
     # since it "should" be in your version control, you can roll back if necessary 
     if($fileToVersion -ne $null) { 
      Remove-Item $filePath$oldFileName -Force -ErrorAction SilentlyContinue 
     } 

     # rename the default file with the new file name 
     Rename-Item -literalPath $filePath$defaultFileName -NewName $newFileName 

     # loop through all of the specified source files and replace with the appropriate versioned file 
     foreach($private:file in $filesContainingVersionedResourceRefs){ 
      $fileContent = Get-Content $private:file 
      Clear-Content $file 

      if($oldFileName -ne $null){ 
       # replace the old version string if it exists 
       $newFileContent = $fileContent -replace "$oldFileName","$newFileName" 
      } else { 
       # replace the default version string if it exists 
       $newFileContent = $fileContent -replace "$defaultFileName","$newFileName"     
      } 

      Add-Content $private:file $newFileContent 

     } 
    } 

    # OPTIONAL: remove original files 
    # this just keeps your directory clean and free of unneeded versions of the css/js 
    $private:nonMinifiedVersion = $defaultFileName -replace ".min", "" 
    Remove-Item -LiteralPath $filePath$defaultFileName -ErrorAction SilentlyContinue 
    Remove-Item -LiteralPath $filePath$private:nonMinifiedVersion -ErrorAction SilentlyContinue 

} 

# version the Javascript 
versionResource $jsFileNameRegex $jsFilePath 


# version the css 
versionResource $cssFileNameRegex $cssFilePath 
+0

代理不会奇迹般地缓存您的资源,除非您设置适当的HTTP缓存标头。为文件名添加散列只是解决方案的一部分。不要忘记HTTP头max-age和Cache-Control。 – 2013-04-01 00:14:03

+0

@VincePanuccio这显然不言而喻。对我来说,这是在我的asp.net web.config中实现的,但其他人将实现它,但他们需要。这个答案是关于如何版本的JavaScript,而不是如何缓存JavaScript。 – 2013-04-02 02:42:47

相关问题