-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: live reload port fallback if port is used #899
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
1e993bd
Move start reload server into separate module
be9aa74
Find an unused port when starting the live reload server
556bead
Move findUnusedPort into module
7e44955
Add tests for findUnusedPort module
e8c6d18
Refactor findUnusedPort
fa2c523
Move starting of servers into separate module and add tests
befd8c6
Remove unused constants.js
437f87f
Zap extra line breaks
ae6b0bc
Add tests for liveReloadServer
815f4e5
Merge branch 'master' into live-reload-port
8e8a331
Rename serverController to start
152621e
Move start into lib/server
4698940
Add portfinder package
6b26fa1
Replace findUnusedPort with portfinder
6979f86
Merge branch 'master' into live-reload-port
febf0d5
nits
endiliey File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
jest.mock('gaze'); | ||
jest.mock('../readMetadata.js'); | ||
jest.mock('tiny-lr'); | ||
|
||
// When running Jest the siteConfig import fails because siteConfig doesn't exist | ||
// relative to the cwd of the tests. Rather than mocking out cwd just mock | ||
// siteConfig virtually. | ||
jest.mock(`${process.cwd()}/siteConfig.js`, () => jest.fn(), {virtual: true}); | ||
|
||
const liveReloadServer = require('../liveReloadServer.js'); | ||
|
||
describe('get reload script', () => { | ||
test('when server started, returns url with correct port', () => { | ||
const port = 1234; | ||
liveReloadServer.start(port); | ||
const expectedUrl = `http://localhost:${port}/livereload.js`; | ||
expect(liveReloadServer.getReloadScriptUrl()).toBe(expectedUrl); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const program = require('commander'); | ||
const openBrowser = require('react-dev-utils/openBrowser'); | ||
const portFinder = require('portfinder'); | ||
const liveReloadServer = require('../liveReloadServer.js'); | ||
const server = require('../server.js'); | ||
|
||
const siteConfig = require(`${process.cwd()}/siteConfig.js`); | ||
|
||
// When running Jest the siteConfig import fails because siteConfig doesn't exist | ||
// relative to the cwd of the tests. Rather than mocking out cwd just mock | ||
// siteConfig virtually. | ||
jest.mock(`${process.cwd()}/siteConfig.js`, () => jest.fn(), {virtual: true}); | ||
|
||
jest.mock('commander'); | ||
jest.mock('react-dev-utils/openBrowser'); | ||
jest.mock('portfinder'); | ||
jest.mock('../liveReloadServer.js'); | ||
jest.mock('../server.js'); | ||
jest.mock('process'); | ||
|
||
console.log = jest.fn(); | ||
|
||
const start = require('../start.js'); | ||
|
||
beforeEach(() => jest.resetAllMocks()); | ||
|
||
describe('start live reload', () => { | ||
test('uses inital port 35729', () => { | ||
portFinder.getPortPromise.mockResolvedValue(); | ||
start.startLiveReloadServer(); | ||
expect(portFinder.getPortPromise).toHaveBeenCalledWith({port: 35729}); | ||
}); | ||
|
||
test('when an unused port is found, starts the live reload server on that port', () => { | ||
expect.assertions(1); | ||
const unusedPort = 1234; | ||
portFinder.getPortPromise.mockResolvedValue(unusedPort); | ||
return start.startLiveReloadServer().then(() => { | ||
expect(liveReloadServer.start).toHaveBeenCalledWith(unusedPort); | ||
}); | ||
}); | ||
|
||
test('when no unused port found, returns error', () => { | ||
expect.assertions(1); | ||
const unusedPortError = new Error('no unused port'); | ||
portFinder.getPortPromise.mockRejectedValue(unusedPortError); | ||
return expect(start.startLiveReloadServer()).rejects.toEqual( | ||
unusedPortError | ||
); | ||
}); | ||
}); | ||
|
||
describe('start server', () => { | ||
test('when custom port provided as parameter, uses as inital port', () => { | ||
const customPort = 1234; | ||
program.port = customPort; | ||
portFinder.getPortPromise.mockResolvedValue(); | ||
start.startServer(); | ||
expect(portFinder.getPortPromise).toBeCalledWith({port: customPort}); | ||
delete program.port; | ||
}); | ||
|
||
test('when port environment variable set and no custom port, used as inital port', () => { | ||
const customPort = '4321'; | ||
process.env.PORT = customPort; | ||
portFinder.getPortPromise.mockResolvedValue(); | ||
start.startServer(); | ||
expect(portFinder.getPortPromise).toBeCalledWith({port: customPort}); | ||
delete process.env.PORT; | ||
}); | ||
|
||
test('when no custom port specified, uses port 3000', () => { | ||
portFinder.getPortPromise.mockResolvedValue(); | ||
start.startServer(); | ||
expect(portFinder.getPortPromise).toBeCalledWith({port: 3000}); | ||
}); | ||
|
||
test('when unused port found, starts server on that port', () => { | ||
expect.assertions(1); | ||
const port = 1357; | ||
portFinder.getPortPromise.mockResolvedValue(port); | ||
return start.startServer().then(() => { | ||
expect(server).toHaveBeenCalledWith(port); | ||
}); | ||
}); | ||
|
||
test('when unused port found, opens browser to server address', () => { | ||
expect.assertions(1); | ||
const baseUrl = '/base_url'; | ||
siteConfig.baseUrl = baseUrl; | ||
const port = 2468; | ||
portFinder.getPortPromise.mockResolvedValue(port); | ||
const expectedServerAddress = `http://localhost:${port}${baseUrl}`; | ||
return start.startServer().then(() => { | ||
expect(openBrowser).toHaveBeenCalledWith(expectedServerAddress); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('start docusaurus', () => { | ||
test('when watch enabled, starts live reload server', () => { | ||
expect.assertions(1); | ||
program.watch = true; | ||
portFinder.getPortPromise.mockResolvedValue(); | ||
return start.startDocusaurus().then(() => { | ||
expect(liveReloadServer.start).toBeCalled(); | ||
}); | ||
}); | ||
|
||
test('when live reload fails to start, server still started', () => { | ||
expect.assertions(1); | ||
program.watch = true; | ||
console.warn = jest.fn(); | ||
portFinder.getPortPromise | ||
.mockRejectedValueOnce('could not find live reload port') | ||
.mockResolvedValueOnce(); | ||
return start.startDocusaurus().then(() => { | ||
expect(server).toBeCalled(); | ||
}); | ||
}); | ||
|
||
test('live reload disabled, only starts docusarus server', () => { | ||
expect.assertions(2); | ||
program.watch = false; | ||
portFinder.getPortPromise.mockResolvedValue(); | ||
return start.startDocusaurus().then(() => { | ||
expect(liveReloadServer.start).not.toBeCalled(); | ||
expect(server).toBeCalled(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const gaze = require('gaze'); | ||
const tinylr = require('tiny-lr'); | ||
const readMetadata = require('./readMetadata.js'); | ||
|
||
let reloadScriptUrl; | ||
|
||
function start(port) { | ||
process.env.NODE_ENV = 'development'; | ||
const server = tinylr(); | ||
server.listen(port, () => { | ||
console.log('LiveReload server started on port %d', port); | ||
}); | ||
|
||
gaze( | ||
[`../${readMetadata.getDocsPath()}/**/*`, '**/*', '!node_modules/**/*'], | ||
function() { | ||
this.on('all', () => { | ||
server.notifyClients(['/']); | ||
}); | ||
} | ||
); | ||
|
||
reloadScriptUrl = `http://localhost:${port}/livereload.js`; | ||
} | ||
|
||
const getReloadScriptUrl = () => reloadScriptUrl; | ||
|
||
module.exports = { | ||
start, | ||
getReloadScriptUrl, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const program = require('commander'); | ||
const openBrowser = require('react-dev-utils/openBrowser'); | ||
const portFinder = require('portfinder'); | ||
const liveReloadServer = require('./liveReloadServer.js'); | ||
const server = require('./server.js'); | ||
|
||
const CWD = process.cwd(); | ||
|
||
function startLiveReloadServer() { | ||
const promise = portFinder.getPortPromise({port: 35729}).then(port => { | ||
liveReloadServer.start(port); | ||
}); | ||
return promise; | ||
} | ||
|
||
function startServer() { | ||
const initialServerPort = | ||
parseInt(program.port, 10) || process.env.PORT || 3000; | ||
const promise = portFinder | ||
.getPortPromise({port: initialServerPort}) | ||
.then(port => { | ||
server(port); | ||
const {baseUrl} = require(`${CWD}/siteConfig.js`); | ||
const serverAddress = `http://localhost:${port}${baseUrl}`; | ||
console.log('Docusaurus server started on port %d', port); | ||
openBrowser(serverAddress); | ||
}); | ||
return promise; | ||
} | ||
|
||
function startDocusaurus() { | ||
if (program.watch) { | ||
return startLiveReloadServer() | ||
.catch(ex => console.warn(`Failed to start live reload server: ${ex}`)) | ||
.then(() => startServer()); | ||
} | ||
return startServer(); | ||
} | ||
|
||
module.exports = { | ||
startDocusaurus, | ||
startServer, | ||
startLiveReloadServer, | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file has no relationship to the
constants
file, right? You just changed theconstants
file and then made a file move. I am just wondering why GitHub thinks this is a file move.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, the two files are unrelated. I actually deleted the
constants
file in a separate commit, and added thetiny-lr
mock in a later one, so I'm not sure why GitHub thinks this was a file move 😕