Skip to content

Commit

Permalink
Fix iOS unchanged local assets refetched from packager in development
Browse files Browse the repository at this point in the history
Summary:
Hi,

This PR fixes the problem described by chrisnojima in facebook/react-native#9581 (comment)

**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 facebook/react-native#9795

Differential Revision: D3876945

Pulled By: davidaurelio

fbshipit-source-id: f41f4719e87644692a690123fd6e54eead9cc87d
  • Loading branch information
jeanregisser authored and Facebook Github Bot 6 committed Sep 19, 2016
1 parent 2311a28 commit 047cbf9
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
12 changes: 8 additions & 4 deletions react-packager/src/Server/__tests__/Server-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,49 +337,53 @@ describe('processRequest', () => {
describe('/assets endpoint', () => {
it('should serve simple case', () => {
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'));

server.processRequest(req, res);
jest.runAllTimers();
expect(res.setHeader).toBeCalledWith('Cache-Control', 'max-age=31536000');
expect(res.end).toBeCalledWith('i am image');
});

it('should parse the platform option', () => {
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'));

server.processRequest(req, res);
jest.runAllTimers();
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');
});

it('should serve range request', () => {
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';

AssetServer.prototype.get.mockImpl(() => Promise.resolve(mockData));

server.processRequest(req, res);
jest.runAllTimers();
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));
});

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 res = {end: jest.fn()};
const res = {end: jest.fn(), setHeader: jest.fn()};

AssetServer.prototype.get.mockImpl(() => Promise.resolve('i am image'));

server.processRequest(req, res);
jest.runAllTimers();
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');
});
});
Expand Down
7 changes: 6 additions & 1 deletion react-packager/src/Server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,12 @@ class Server {
const assetEvent = Activity.startEvent('Processing asset request', {asset: assetPath[1]});
this._assetServer.get(assetPath[1], urlObj.query.platform)
.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 => {
console.error(error.stack);
res.writeHead('404');
Expand Down

0 comments on commit 047cbf9

Please sign in to comment.