我已经想通了,并已将解决方案上传到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
代理不会奇迹般地缓存您的资源,除非您设置适当的HTTP缓存标头。为文件名添加散列只是解决方案的一部分。不要忘记HTTP头max-age和Cache-Control。 – 2013-04-01 00:14:03
@VincePanuccio这显然不言而喻。对我来说,这是在我的asp.net web.config中实现的,但其他人将实现它,但他们需要。这个答案是关于如何版本的JavaScript,而不是如何缓存JavaScript。 – 2013-04-02 02:42:47