mirror of https://github.com/status-im/metro.git
Fix iOS unchanged local assets refetched from packager in development
Summary: Hi, This PR fixes the problem described by chrisnojima in https://github.com/facebook/react-native/issues/9581#issuecomment-243766310 **Test plan** In development mode, - Run an app with an image: `<Image source={ require('./logo.png') }/>` - Notice that you see the following in packager console: ```txt 6:46:42 PM] <START> processing asset request logo.png [6:46:42 PM] <END> processing asset request logo.png (1ms) ``` - Reload the app, or navigate to another page of the app with the same image - Notice that you see again: ```txt 6:47:23 PM] <START> processing asset request logo.png [6:47:23 PM] <END> processing asset request logo.png (1ms) ``` Now wih the fix applied, notice that you only see `logo.png` fetched once, even if you reload or show the same image in a different part of the app. Let me know what you think. Closes https://github.com/facebook/react-native/pull/9795 Differential Revision: D3876945 Pulled By: davidaurelio fbshipit-source-id: f41f4719e87644692a690123fd6e54eead9cc87d
This commit is contained in:
parent
2311a28cb2
commit
047cbf9d59
|
@ -337,30 +337,32 @@ describe('processRequest', () => {
|
||||||
describe('/assets endpoint', () => {
|
describe('/assets endpoint', () => {
|
||||||
it('should serve simple case', () => {
|
it('should serve simple case', () => {
|
||||||
const req = {url: '/assets/imgs/a.png'};
|
const req = {url: '/assets/imgs/a.png'};
|
||||||
const res = {end: jest.fn()};
|
const res = {end: jest.fn(), setHeader: jest.fn()};
|
||||||
|
|
||||||
AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));
|
AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));
|
||||||
|
|
||||||
server.processRequest(req, res);
|
server.processRequest(req, res);
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
|
expect(res.setHeader).toBeCalledWith('Cache-Control', 'max-age=31536000');
|
||||||
expect(res.end).toBeCalledWith('i am image');
|
expect(res.end).toBeCalledWith('i am image');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse the platform option', () => {
|
it('should parse the platform option', () => {
|
||||||
const req = {url: '/assets/imgs/a.png?platform=ios'};
|
const req = {url: '/assets/imgs/a.png?platform=ios'};
|
||||||
const res = {end: jest.fn()};
|
const res = {end: jest.fn(), setHeader: jest.fn()};
|
||||||
|
|
||||||
AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));
|
AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));
|
||||||
|
|
||||||
server.processRequest(req, res);
|
server.processRequest(req, res);
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(AssetServer.prototype.get).toBeCalledWith('imgs/a.png', 'ios');
|
expect(AssetServer.prototype.get).toBeCalledWith('imgs/a.png', 'ios');
|
||||||
|
expect(res.setHeader).toBeCalledWith('Cache-Control', 'max-age=31536000');
|
||||||
expect(res.end).toBeCalledWith('i am image');
|
expect(res.end).toBeCalledWith('i am image');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should serve range request', () => {
|
it('should serve range request', () => {
|
||||||
const req = {url: '/assets/imgs/a.png?platform=ios', headers: {range: 'bytes=0-3'}};
|
const req = {url: '/assets/imgs/a.png?platform=ios', headers: {range: 'bytes=0-3'}};
|
||||||
const res = {end: jest.fn(), writeHead: jest.fn()};
|
const res = {end: jest.fn(), writeHead: jest.fn(), setHeader: jest.fn()};
|
||||||
const mockData = 'i am image';
|
const mockData = 'i am image';
|
||||||
|
|
||||||
AssetServer.prototype.get.mockImpl(() => Promise.resolve(mockData));
|
AssetServer.prototype.get.mockImpl(() => Promise.resolve(mockData));
|
||||||
|
@ -368,18 +370,20 @@ describe('processRequest', () => {
|
||||||
server.processRequest(req, res);
|
server.processRequest(req, res);
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(AssetServer.prototype.get).toBeCalledWith('imgs/a.png', 'ios');
|
expect(AssetServer.prototype.get).toBeCalledWith('imgs/a.png', 'ios');
|
||||||
|
expect(res.setHeader).toBeCalledWith('Cache-Control', 'max-age=31536000');
|
||||||
expect(res.end).toBeCalledWith(mockData.slice(0, 4));
|
expect(res.end).toBeCalledWith(mockData.slice(0, 4));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should serve assets files\'s name contain non-latin letter', () => {
|
it('should serve assets files\'s name contain non-latin letter', () => {
|
||||||
const req = {url: '/assets/imgs/%E4%B8%BB%E9%A1%B5/logo.png'};
|
const req = {url: '/assets/imgs/%E4%B8%BB%E9%A1%B5/logo.png'};
|
||||||
const res = {end: jest.fn()};
|
const res = {end: jest.fn(), setHeader: jest.fn()};
|
||||||
|
|
||||||
AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));
|
AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));
|
||||||
|
|
||||||
server.processRequest(req, res);
|
server.processRequest(req, res);
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(AssetServer.prototype.get).toBeCalledWith('imgs/主页/logo.png', undefined);
|
expect(AssetServer.prototype.get).toBeCalledWith('imgs/主页/logo.png', undefined);
|
||||||
|
expect(res.setHeader).toBeCalledWith('Cache-Control', 'max-age=31536000');
|
||||||
expect(res.end).toBeCalledWith('i am image');
|
expect(res.end).toBeCalledWith('i am image');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -493,7 +493,12 @@ class Server {
|
||||||
const assetEvent = Activity.startEvent('Processing asset request', {asset: assetPath[1]});
|
const assetEvent = Activity.startEvent('Processing asset request', {asset: assetPath[1]});
|
||||||
this._assetServer.get(assetPath[1], urlObj.query.platform)
|
this._assetServer.get(assetPath[1], urlObj.query.platform)
|
||||||
.then(
|
.then(
|
||||||
data => res.end(this._rangeRequestMiddleware(req, res, data, assetPath)),
|
data => {
|
||||||
|
// Tell clients to cache this for 1 year.
|
||||||
|
// This is safe as the asset url contains a hash of the asset.
|
||||||
|
res.setHeader('Cache-Control', 'max-age=31536000');
|
||||||
|
res.end(this._rangeRequestMiddleware(req, res, data, assetPath));
|
||||||
|
},
|
||||||
error => {
|
error => {
|
||||||
console.error(error.stack);
|
console.error(error.stack);
|
||||||
res.writeHead('404');
|
res.writeHead('404');
|
||||||
|
|
Loading…
Reference in New Issue