diff --git a/src/source/raster_tile_source.js b/src/source/raster_tile_source.js index a70857b2d13..af786786992 100644 --- a/src/source/raster_tile_source.js +++ b/src/source/raster_tile_source.js @@ -38,6 +38,7 @@ class RasterTileSource extends Evented implements Source { tiles: Array; _loaded: boolean; + _avoidXHR: boolean; _options: RasterSourceSpecification | RasterDEMSourceSpecification; _tileJSONRequest: ?Cancelable; @@ -56,6 +57,7 @@ class RasterTileSource extends Evented implements Source { this._loaded = false; this._options = extend({}, options); + this._avoidXHR = false; extend(this, pick(options, ['url', 'scheme', 'tileSize'])); } @@ -114,6 +116,13 @@ class RasterTileSource extends Evented implements Source { delete (img: any).cacheControl; delete (img: any).expires; + // if the tiles have aggressive caching (retained for at least 1 hour), + // switch to faster image loading technique for subsequent tile loads + const timeout = tile.getExpiryTimeout(); + if (timeout === undefined || timeout > 1000 * 60 * 60) { + this._avoidXHR = true; + } + const context = this.map.painter.context; const gl = context.gl; tile.texture = this.map.painter.getTileTexture(img.width); @@ -132,7 +141,7 @@ class RasterTileSource extends Evented implements Source { callback(null); } - }); + }, this._avoidXHR); } abortTile(tile: Tile, callback: Callback) { diff --git a/src/util/ajax.js b/src/util/ajax.js index 63e96d28a60..13b5dee380e 100644 --- a/src/util/ajax.js +++ b/src/util/ajax.js @@ -130,8 +130,21 @@ function sameOrigin(url) { const transparentPngUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII='; -export const getImage = function(requestParameters: RequestParameters, callback: Callback): Cancelable { - // request the image with XHR to work around caching issues +export const getImage = function(requestParameters: RequestParameters, callback: Callback, avoidXHR?: boolean): Cancelable { + // if we know for sure that the tile is cached for a long time, avoid XHR for better performance + // https://github.com/mapbox/mapbox-gl-js/issues/6643 + if (avoidXHR && requestParameters.headers === undefined && requestParameters.credentials === undefined) { + const img: HTMLImageElement = new window.Image(); + const url = requestParameters.url; + if (!sameOrigin(url)) { + img.crossOrigin = 'Anonymous'; + } + img.onload = () => callback(null, img); + img.src = url; + return {cancel: () => { img.src = transparentPngUrl; }}; + } + + // otherwise request the image with XHR to work around caching issues // see https://github.com/mapbox/mapbox-gl-js/issues/1470 return getArrayBuffer(requestParameters, (err, imgData) => { if (err) {