Merge pull request #209 from sharelatex/ho-hash-static

Main.js Ide.js and libs.js (now libraries.js) use hash in file name when minified
This commit is contained in:
Henry Oswald 2017-12-15 09:52:23 +00:00 committed by GitHub
commit 7693d274b7
9 changed files with 65 additions and 62 deletions

View file

@ -67,6 +67,10 @@ public/minjs/
Gemfile.lock Gemfile.lock
public/stylesheets/ol-style.*.css
public/stylesheets/style.*.css
*.swp *.swp
.DS_Store .DS_Store

View file

@ -205,12 +205,12 @@ module.exports = (grunt) ->
modules: [ modules: [
{ {
name: "main", name: "main",
exclude: ["libs"] exclude: ["libraries"]
}, { }, {
name: "ide", name: "ide",
exclude: ["libs", "pdfjs-dist/build/pdf"] exclude: ["pdfjs-dist/build/pdf", "libraries"]
}, { },{
name: "libs" name: "libraries"
},{ },{
name: "ace/mode-latex" name: "ace/mode-latex"
},{ },{

View file

@ -12,7 +12,7 @@ Modules = require "./Modules"
Url = require "url" Url = require "url"
PackageVersions = require "./PackageVersions" PackageVersions = require "./PackageVersions"
htmlEncoder = new require("node-html-encoder").Encoder("numerical") htmlEncoder = new require("node-html-encoder").Encoder("numerical")
fingerprints = {} hashedFiles = {}
Path = require 'path' Path = require 'path'
Features = require "./Features" Features = require "./Features"
@ -30,43 +30,39 @@ getFileContent = (filePath)->
filePath = Path.join __dirname, "../../../", "public#{filePath}" filePath = Path.join __dirname, "../../../", "public#{filePath}"
exists = fs.existsSync filePath exists = fs.existsSync filePath
if exists if exists
content = fs.readFileSync filePath content = fs.readFileSync filePath, "UTF-8"
return content return content
else else
logger.log filePath:filePath, "file does not exist for fingerprints" logger.log filePath:filePath, "file does not exist for hashing"
return "" return ""
logger.log "Generating file fingerprints..." logger.log "Generating file hashes..."
pathList = [ pathList = [
["#{jsPath}libs/#{fineuploader}.js"] "#{jsPath}libs/require.js"
["#{jsPath}libs/require.js"] "#{jsPath}ide.js"
["#{jsPath}ide.js"] "#{jsPath}main.js"
["#{jsPath}main.js"] "#{jsPath}libraries.js"
["#{jsPath}libs.js"] "/stylesheets/style.css"
["#{jsPath}#{ace}/ace.js","#{jsPath}#{ace}/mode-latex.js","#{jsPath}#{ace}/worker-latex.js","#{jsPath}#{ace}/snippets/latex.js"] "/stylesheets/ol-style.css"
["#{jsPath}libs/#{pdfjs}/pdf.js"]
["#{jsPath}libs/#{pdfjs}/pdf.worker.js"]
["#{jsPath}libs/#{pdfjs}/compatibility.js"]
["/stylesheets/style.css"]
["/stylesheets/ol-style.css"]
] ]
for paths in pathList for path in pathList
contentList = _.map(paths, getFileContent) content = getFileContent(path)
content = contentList.join("")
hash = crypto.createHash("md5").update(content).digest("hex") hash = crypto.createHash("md5").update(content).digest("hex")
_.each paths, (filePath)->
logger.log "#{filePath}: #{hash}"
fingerprints[filePath] = hash
getFingerprint = (path) -> splitPath = path.split("/")
if fingerprints[path]? filenameSplit = splitPath.pop().split(".")
return fingerprints[path] filenameSplit.splice(filenameSplit.length-1, 0, hash)
else splitPath.push(filenameSplit.join("."))
logger.err "No fingerprint for file: #{path}"
return ""
logger.log "Finished generating file fingerprints" hashPath = splitPath.join("/")
hashedFiles[path] = hashPath
fsHashPath = Path.join __dirname, "../../../", "public#{hashPath}"
fs.writeFileSync(fsHashPath, content)
logger.log "Finished hashing static content"
cdnAvailable = Settings.cdn?.web?.host? cdnAvailable = Settings.cdn?.web?.host?
darkCdnAvailable = Settings.cdn?.web?.darkHost? darkCdnAvailable = Settings.cdn?.web?.darkHost?
@ -120,29 +116,35 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
res.locals.fullJsPath = Url.resolve(staticFilesBase, jsPath) res.locals.fullJsPath = Url.resolve(staticFilesBase, jsPath)
res.locals.lib = PackageVersions.lib res.locals.lib = PackageVersions.lib
res.locals.buildJsPath = (jsFile, opts = {})-> res.locals.buildJsPath = (jsFile, opts = {})->
path = Path.join(jsPath, jsFile) path = Path.join(jsPath, jsFile)
doFingerPrint = opts.fingerprint != false if opts.hashedPath
path = hashedFiles[path]
if !opts.qs? if !opts.qs?
opts.qs = {} opts.qs = {}
if !opts.qs?.fingerprint? and doFingerPrint
opts.qs.fingerprint = getFingerprint(path)
if opts.cdn != false if opts.cdn != false
path = Url.resolve(staticFilesBase, path) path = Url.resolve(staticFilesBase, path)
qs = querystring.stringify(opts.qs) qs = querystring.stringify(opts.qs)
if opts.removeExtension == true
path = path.slice(0,-3)
if qs? and qs.length > 0 if qs? and qs.length > 0
path = path + "?" + qs path = path + "?" + qs
return path return path
res.locals.buildCssPath = (cssFile)-> res.locals.buildCssPath = (cssFile, opts)->
path = Path.join("/stylesheets/", cssFile) path = Path.join("/stylesheets/", cssFile)
return Url.resolve(staticFilesBase, path) + "?fingerprint=" + getFingerprint(path) if opts?.hashedPath
hashedPath = hashedFiles[path]
return Url.resolve(staticFilesBase, hashedPath)
return Url.resolve(staticFilesBase, path)
res.locals.buildImgPath = (imgFile)-> res.locals.buildImgPath = (imgFile)->
path = Path.join("/img/", imgFile) path = Path.join("/img/", imgFile)
@ -227,10 +229,6 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
return req.query?[field] return req.query?[field]
next() next()
webRouter.use (req, res, next)->
res.locals.fingerprint = getFingerprint
next()
webRouter.use (req, res, next)-> webRouter.use (req, res, next)->
res.locals.formatPrice = SubscriptionFormatters.formatPrice res.locals.formatPrice = SubscriptionFormatters.formatPrice
next() next()

View file

@ -23,7 +23,7 @@ html(itemscope, itemtype='http://schema.org/Product')
link(rel="apple-touch-icon-precomposed", href="/" + settings.brandPrefix + "apple-touch-icon-precomposed.png") link(rel="apple-touch-icon-precomposed", href="/" + settings.brandPrefix + "apple-touch-icon-precomposed.png")
link(rel="mask-icon", href="/" + settings.brandPrefix + "mask-favicon.svg", color="#a93529") link(rel="mask-icon", href="/" + settings.brandPrefix + "mask-favicon.svg", color="#a93529")
link(rel='stylesheet', href=buildCssPath("/" + settings.brandPrefix + "style.css")) link(rel='stylesheet', href=buildCssPath("/" + settings.brandPrefix + "style.css", {hashedPath:true}))
block _headLinks block _headLinks
@ -57,7 +57,7 @@ html(itemscope, itemtype='http://schema.org/Product')
script(type="text/javascript"). script(type="text/javascript").
window.csrfToken = "#{csrfToken}"; window.csrfToken = "#{csrfToken}";
script(src=buildJsPath("libs/jquery-1.11.1.min.js", {fingerprint:false})) script(src=buildJsPath("libs/jquery-1.11.1.min.js"))
script(type="text/javascript"). script(type="text/javascript").
var noCdnKey = "nocdn=true" var noCdnKey = "nocdn=true"
var cdnBlocked = typeof jQuery === 'undefined' var cdnBlocked = typeof jQuery === 'undefined'
@ -68,7 +68,7 @@ html(itemscope, itemtype='http://schema.org/Product')
block scripts block scripts
script(src=buildJsPath("libs/angular-1.6.4.min.js", {fingerprint:false})) script(src=buildJsPath("libs/angular-1.6.4.min.js"))
script. script.
window.sharelatex = { window.sharelatex = {
@ -142,9 +142,10 @@ html(itemscope, itemtype='http://schema.org/Product')
window.requirejs = { window.requirejs = {
"paths" : { "paths" : {
"moment": "libs/#{lib('moment')}", "moment": "libs/#{lib('moment')}",
"fineuploader": "libs/#{lib('fineuploader')}" "fineuploader": "libs/#{lib('fineuploader')}",
"main": "#{buildJsPath('main.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
}, },
"urlArgs": "fingerprint=#{fingerprint(jsPath + 'main.js')}-#{fingerprint(jsPath + 'libs.js')}",
"config":{ "config":{
"moment":{ "moment":{
"noGlobal": true "noGlobal": true
@ -152,9 +153,9 @@ html(itemscope, itemtype='http://schema.org/Product')
} }
}; };
script( script(
data-main=buildJsPath('main.js', {fingerprint:false}), data-main=buildJsPath('main.js', {hashedPath:false}),
baseurl=fullJsPath, baseurl=fullJsPath,
src=buildJsPath('libs/require.js') src=buildJsPath('libs/require.js', {hashedPath:true})
) )
include contact-us-modal include contact-us-modal

View file

@ -98,9 +98,9 @@ block requirejs
script(type="text/javascript" src='/socket.io/socket.io.js') script(type="text/javascript" src='/socket.io/socket.io.js')
//- don't use cdn for workers //- don't use cdn for workers
- var aceWorkerPath = buildJsPath(lib('ace'), {cdn:false,fingerprint:false}) - var aceWorkerPath = buildJsPath(lib('ace'), {cdn:false})
- var pdfWorkerPath = buildJsPath('/libs/' + lib('pdfjs') + '/pdf.worker', {cdn:false,fingerprint:false}) - var pdfWorkerPath = buildJsPath('/libs/' + lib('pdfjs') + '/pdf.worker', {cdn:false})
- var pdfCMapsPath = buildJsPath('/libs/' + lib('pdfjs') + '/bcmaps/', {cdn:false,fingerprint:false}) - var pdfCMapsPath = buildJsPath('/libs/' + lib('pdfjs') + '/bcmaps/', {cdn:false})
//- We need to do .replace(/\//g, '\\/') do that '</script>' -> '<\/script>' //- We need to do .replace(/\//g, '\\/') do that '</script>' -> '<\/script>'
//- and doesn't prematurely end the script tag. //- and doesn't prematurely end the script tag.
@ -126,14 +126,15 @@ block requirejs
window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)}; window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)};
window.requirejs = { window.requirejs = {
"paths" : { "paths" : {
"mathjax": "#{buildJsPath('/libs/mathjax/MathJax.js', {cdn:false, fingerprint:false, qs:{config:'TeX-AMS_HTML'}})}", "mathjax": "#{buildJsPath('/libs/mathjax/MathJax.js', {cdn:false, qs:{config:'TeX-AMS_HTML'}})}",
"moment": "libs/#{lib('moment')}", "moment": "libs/#{lib('moment')}",
"pdfjs-dist/build/pdf": "libs/#{lib('pdfjs')}/pdf", "pdfjs-dist/build/pdf": "libs/#{lib('pdfjs')}/pdf",
"pdfjs-dist/build/pdf.worker": "#{pdfWorkerPath}", "pdfjs-dist/build/pdf.worker": "#{pdfWorkerPath}",
"ace": "#{lib('ace')}", "ace": "#{lib('ace')}",
"fineuploader": "libs/#{lib('fineuploader')}" "fineuploader": "libs/#{lib('fineuploader')}",
"ide": "#{buildJsPath('ide.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
}, },
"urlArgs" : "fingerprint=#{fingerprint(jsPath + 'ide.js')}-#{fingerprint(jsPath + 'libs.js')}",
"waitSeconds": 0, "waitSeconds": 0,
"shim": { "shim": {
"pdfjs-dist/build/pdf": { "pdfjs-dist/build/pdf": {
@ -155,14 +156,13 @@ block requirejs
} }
} }
}; };
window.aceFingerprint = "#{fingerprint(jsPath + lib('ace') + '/ace.js')}"
window.aceWorkerPath = "#{aceWorkerPath}"; window.aceWorkerPath = "#{aceWorkerPath}";
window.pdfCMapsPath = "#{pdfCMapsPath}" window.pdfCMapsPath = "#{pdfCMapsPath}"
window.uiConfig = JSON.parse('!{JSON.stringify(uiConfig).replace(/\//g, "\\/")}'); window.uiConfig = JSON.parse('!{JSON.stringify(uiConfig).replace(/\//g, "\\/")}');
script( script(
data-main=buildJsPath("ide.js", {fingerprint:false}), data-main=buildJsPath("ide.js", {hashedPath:false}),
baseurl=fullJsPath, baseurl=fullJsPath,
data-ace-base=buildJsPath(lib('ace'), {fingerprint:false}), data-ace-base=buildJsPath(lib('ace')),
src=buildJsPath('libs/require.js') src=buildJsPath('libs/require.js', {hashedPath:true})
) )

View file

@ -1,5 +1,5 @@
define [ define [
"libs" "libraries"
"modules/recursionHelper" "modules/recursionHelper"
"modules/errorCatcher" "modules/errorCatcher"
"modules/localStorage" "modules/localStorage"

View file

@ -33,7 +33,7 @@ define [
if !ace.config._moduleUrl? if !ace.config._moduleUrl?
ace.config._moduleUrl = ace.config.moduleUrl ace.config._moduleUrl = ace.config.moduleUrl
ace.config.moduleUrl = (args...) -> ace.config.moduleUrl = (args...) ->
url = ace.config._moduleUrl(args...) + "?fingerprint=#{window.aceFingerprint}" url = ace.config._moduleUrl(args...)
return url return url
App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, metadata, graphics, preamble, files, $http, $q) -> App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, metadata, graphics, preamble, files, $http, $q) ->

View file

@ -1,5 +1,5 @@
define [ define [
"libs" "libraries"
], () -> ], () ->
angular.module('underscore', []).factory '_', -> angular.module('underscore', []).factory '_', ->
return window._ return window._